Hiding instance variables in the EyeInspector or EyeExplorer - reflection

Sometimes I am inspecting or exploring my dowmain objects which contains many instance variables. I want to exclude all of them excepting the current specific ones of the instance I am exploring.
Say I am inspecting MyObject with instance variables: text, size, status.
dependents
owner
window
announcer
...(lots of i.v.)
text
size
status
I want to view:
text
size
status
I have seen you can define the method inspectorClass, but is EyeInspector or EyeExplorer designed to configure this type of view?
Should I subclass SelfEyeElement class?

I just tried and came up with this:
Imagine this is your class:
Object subclass: #MyClass
instanceVariableNames: 'firstVariable secondVariable thirdVariable'
classVariableNames: ''
category: 'MyCategory'
Then make the following inspector class:
EyeInspector subclass: #MyClassInspector
instanceVariableNames: ''
classVariableNames: ''
category: 'MyCategory'
Add the following class method to MyClass:
inspectorClass
^ MyClassInspector
And overwrite #addInstanceVariable: in MyClassInspector:
addInstancesVariable: elements
elements add: (InstanceVariableEyeElement host: self object instVarName: #firstVariable).
elements add: (InstanceVariableEyeElement host: self object instVarName: #secondVariable)
Inspect an instance of MyClass and it shows only firstVariable and secondVariable but not thirdVariable:
Very nice question!
Update: If you want an inspector that shows generally only instance variables specified in the class of an inspected object and not in superclasses of an inspected object you can use this #addInstanceVariable: in your inspector class:
addInstancesVariable: elements
self object class instVarNames do: [:name |
elements add: (InstanceVariableEyeElement host: self object instVarName: name) ]

You might want to work with the customizable tools in Moose. There you can add/change views very easily. In the humane assessment blog you can find examples

Related

Kotlin reflection: findAnnotation<Type>() returns null

I have the following data class:
data class Foo(#field:Password val password: String)
Why does Foo::password.annotations return an empty list?
Also, Foo::password.findAnnotation<Password>() returns null.
The same happens when I use an instance of Foo:
Foo("")::password.annotations
Foo("")::password.findAnnotation<Password>()
However, this java variant works: Foo::password.javaField.getAnnotation(Password::class.java).
This is on kotlin version 1.3.10.
The docs don't give much information on the inner workings of findAnnotation.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property/index.html
fun <T : Annotation> KAnnotatedElement.findAnnotation(): T?
Returns an annotation of the given type on this element.
What am I missing here?
Thanks in advance!
Foo::password.annotations is the list of annotations on the property. In your code, you've used the #field: use site target, which means that the annotation is applied to the backing field, not the property. Therefore, the list of annotations on the property is empty.
The Java variant works because it loads the list of annotations on the field.

Nancy and abstract base module class / creating phantom class instance

I'm building a small application with Nancy
I want to have a kind of base class, that other modules can inherit from.
See below (there is a reason this isn't an abstract class, which I'll explain below)
public class ImportModule<T> : NancyModule
{
protected ImportModule()
: this(typeof(T).Name.ToLower())
{
Get["/"] = _ => "need to select an action - xxx";
Get["/importnew"] = _ => ImportNew(); //note - method omitted for brevity
}
}
When I run my app, I get
Unable to resolve type: My.NameSpace.TypedImporter`1
As a sidenote, if the ImportModule class is abstract, this doesn't happen
Ok-
Now, I could have a class like this:
public class MyCustomImporter : ImportModule<MyCustomType>
{
//overrides....
}
But, elsewhere, in a "DefaultImportModule" I have the following:
var importerModule = Activator.CreateInstance(typeof(ImportModule<>).MakeGenericType(type));
So I need to be able to create a type of importer, based on a type that's passed in
(Basically, if a user hits the url /customer, it's doing the same as a class like this would)
public class CustomerImporter : ImporterModule<Customer>
{
}
So, as I see it, I have two choices:
1) Stop nancy trying to map my ImportModule
2) Instantiate a "phantom class" that inherits from ImportModule and make ImportModule abstract again
There is a discussion in the Nancy group that may be related to your problem, it is certainly related to the non-abstract base modules not being recognised by Nancy. Here is what Andreas HÃ¥kansson had to say:
Nancy locates everything that's inheriting NancyModule and assumes
it's something it can instantiate. Nancy is aware that it cannot
create an instance of an abstract module. So if you have a base-module
that's not abstract then Nancy will attempt to new it up. I'd like to
think that for 99% of the time, having a non-abstract base class is a
broken design.
And here is the link to the discussion:Unable to resolve type: Nancy.Routing.DefaultRouteResolver

<table:column> Roo-tag for property of referenced entity

I've got a two classes (pupil, class) in a Roo-project and their scaffolded views.
pupil and class have a 1:1 relationship
In the list.jspx of pupil I'd like to display a column for a property of class.
I don't know the correct attributes to give to the table:column-tag.
This following example gives the error:
SpelEvaluationException: EL1027Epos 4): Indexing into type 'com.pupil' is not supported
<table:table data="${pupil}" duplicate="true" id="l_com_pupil" path="/admin/pupil" z="user-managed">
<table:column id="c_com_pupil_pupilName" property="pupilName" z="user-managed"/>
<!-- I'd like to display the attribute teacher_name of the class 'class' here but it doesn't work -->
<table:column id="c_com_pupil_class_teacherName" property="teacherName" z="user-managed"/>
</table:table>
Instead of messing around with the jspx files, you can simply do this by implementing a converter for the Teacher entity within the ApplicationServiceFactoryBean.java.
See the below conversion method for an example.
static class com.mycompany.test.controllers.ApplicationConversionServiceFactoryBean.TeacherConverter implements org.springframework.core.convert.converter.Converter<com.mycompany.test.domain.master.Teacher, java.lang.String> {
public String convert(Teacher teacher) {
return new StringBuilder().append(teacher.getName()).toString();
}
}
By default, Roo generates these converters and they are stored within the ApplicationConversionServiceFactoryBean_Roo_ConversionService.aj file.
You can push in refactor the related method for the Teacher entity from this aspectJ file into the
ApplicationServiceFactoryBean.java file and then implement your own conversion which will be used to show the Teacher name across the application as in the above example.
Cheers and all the best with Roo!
This is how I did it, not for listing, but rather for showing the name of the teacher when you view the pupil entity:
Edit the controller and specifically the method show (in the java file, not in the aj file, of course).
Add an attribute to your UI Model, for instance "teacherName" (use Model.addAttribute), where you populate the teacherName with the desired name.
Add in the show.jspx file something like:
<div><label for="_pupilTeacher">Teacher Name:</label><div class="box">${teacherName}</div></div><br/>
(alternatively, you could create a new tagx file with your own parameters)
Hope it helped.
Radu

How do I edit the properties of controls made using QTCreator in Slot declaration?

I made a form using QTCreator. Then I change some of its properties in class constructor like
ui->cancelButton->hide();
It work. Now I declare a custom slot in header file & tried to use controls' properties in Slot implementation in class file (i.e .cpp) like
oldName = lineEDit->text();
but I get error msg
error: 'LineEdit' was not declared in this scope
then I tried like
oldName = ui->nameLine->text();
but it gives same error. How do I use controls' properties in Slots declaration or other functions when I made UI using Designer ??
EDIT: SLOT SOURCE
void addressbook::addContact()
{
oldName = ui->nameLine->text(); //nameLine->text();
oldAddress = ui->addressText->toPlainText(); //addressText->toPlainText();
nameLine->clear();
addressText->clear();
updateInterface(AddingMode);
}
if you creating class Test it would produce 4 files:
1) test.h - your class header
2) test.cpp - your implementation
3) test.ui - form descriptor
4) ui_test.h - file generated from form descriptor,
containing cpp code to create it.
test_ui.h has a class declaration inside, with the set of members with types and names of objects you put on form. Ui::TestClass
your main class will have it as private member
private:
Ui::TestClass ui;
so if you want to adress form elements do it as ui->ObjectNameFromForm
And - have a look onto your ui_*.h classes, it is normal cpp code, and after researching them you may understand much more clear how forms works.

How does component instantiation work with respect to scope type

Even though I have specified the scope type as method, it gets instantiated in CONVERSATION scope.
>
UserHome userHome = (UserHome) Component.getInstance(UserHome.class, ScopeType.METHOD);
This is quite confusing, can someone explain this behavior?
When you call
Component.getInstance(UserHome.class, ScopeType.METHOD);
Seam internal behavior is to call
Object result = Contexts.lookupInStatefulContexts(name);
lookupInStatefulContexts API says
Search for a named attribute in all contexts, in the following order: method, event, page, conversation, session, business process, application.
As your ScopeType.METHOD does not contain your UserHome.class component, The search go on until get its scope (StypeType.CONVERSATION, right ?)
UPDATE
I was under the impression that if you specify the ScopeType to getInstance method you will be able to create the object within that scope
If the target component does not have the desired scope associated, getInstance method does not create the component within that scope. Instead it performs a hierarchical search by using Contexts.lookupInStatefulContexts till get some assigned scope
If you want more than one scope can be assigned to a component, you must scecify it by using #Role (#Roles) annotation
#Name("user")
#Scope(ScopeType.EVENT)
#Role(name="loggedUser", scope=ScopeType.SESSION)
public class User { ... }
So you specify the desired scope
Component.getInstance(User.class, ScopeType.EVENT);
or
Component.getInstance(User.class, ScopeType.SESSION);
remember Seam performs lookup by field/property name
private #In User user; // Take ScopeType.EVENT as scope
private #In User loggedUser; // Take ScopeType.SESSION as scope
I assume your UserHome class extends Seam's EntityHome class. The super class of EntityHome, which is Home, is in scope ScopeType.CONVERSATION:
#Scope(ScopeType.CONVERSATION)
public abstract class Home<T, E> extends MutableController<T>
Either you did not override the scope in your UserHome declaration or Seam ignores #Scope annotations in subclasses if one of the super classes already have an #Scope annotation.

Resources