Undefined Class and Expected A Class Member - android-studio

I'm tearing my hair out - I'm sure I'm missing something small, but I can't see it for the life of me! Any hints really appreciated. Essentially on the line root.name = 'root'; it's giving me the following errors:
Undefined Class 'root.name' on the 'root.name' section
Expected a Class Member on the '=' sign.
import 'package:uuid/uuid.dart';
class AppLogic {
Item root = new Item();
root.name = 'root';
List<Item> allItems;
void createNewItem(Item parent){
allItems.add(new Item());
}
}
class Item {
DateTime created = DateTime.now();
String name;
String ID = new Uuid().v1();
Item parentID;
List<String> childrenIDs;
Item.fromID(this.ID);
Item.fromName(this.name);
Item();
}

This code is not allowed outside a constructor or method
root.name = 'root';
Only variable declaration (with initialization), method declaration, and constructors are allowed in a class' body.
You could do it like
class AppLogic {
Item root = new Item()..name = 'root';
List<Item> allItems;
void createNewItem(Item parent){
allItems.add(new Item());
}
}

Related

How to mock a object construction that is created using reflection i.e newInstance() method

I have a piece of code below where Employee class creates object of AppraisalCalculator using reflection. I want to mock this AppraisalCalculator object using PowerMockito.
class AppraisalCalculator {
public int appraisal() {
return 300;
}
}
class Employee {
public int updateSalary() {
// line 1
AppraisalCalculator ac =
AppraisalCalculator.class.getConstructor().newInstance();
return ac.appraisal();
}
}
class TestRunner {
#Test
public void test() {
AppraisalCalulator acMock=PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue=600;
Assert.equals(expectedValue,actualValue);
}
}
Here, even though I have mocked the Appraisal calculator object, it still calls the real appraisal() method from AppraisalCalculator. If the actual AppraisalCalculator at line 1 is created using new Operator instead of newInstance() then this mocking works.
Can anyone explain why this is not working if the actual object is created using reflection? What can I do to mock this Object in such scenario?
Let me first start by rephrasing your question will fully working code.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Employee.class)
public class TestRunner {
#Test
public void test() throws Exception {
AppraisalCalculator acMock = PowerMockito.mock(AppraisalCalculator.class);
PowerMockito
.whenNew(AppraisalCalculator.class)
.withNoArguments()
.thenReturn(acMock);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
}
Then, the way PowerMock works is that the PowerMockRunner will look at each class that needs to be prepared (here Employee), then look for a call to the constructor we want to replace and do it. This is done at class loading. The real class bytecode calling the constructor is replaced by the one returning the mock.
The thing is that if you are using reflection, PowerMock can't know by reading the bytecode that this constructor will be called. It will only be known dynamically afterwards. So no mocking done.
If you really do need to create the class to be mocked by reflection, I would actually refactor the code a bit.
In Employee I would add something like
protected AppraisalCalculator getCalculator() {
try {
return AppraisalCalculator.class.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
while is a method dedicated to isolate the calculator construction.
The, just create a child class
#Test
public void testWithChildClass() {
// Note that you don't need PowerMock anymore
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = new Employee() {
#Override
protected AppraisalCalculator getCalculator() {
return acMock;
}
};
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}
or a partial mock (spy)
#Test
public void test2() {
// No PowerMock either here
AppraisalCalculator acMock = Mockito.mock(AppraisalCalculator.class);
when(acMock.appraisal()).thenReturn(600);
Employee emp = spy(new Employee());
doReturn(acMock).when(emp).getCalculator();
int actualValue = emp.updateSalary();
int expectedValue = 600;
assertEquals(expectedValue, actualValue);
}

Adding a field with Groovy AST doesn't generate getter and setter

So I'm writing an AST Transformation that adds a field with the #Delegate annotation to a class
#SimpleAST
class PersonBuilder{
}
Should produce
class PersonBuilder{
#Delegate
Person target = new Person
}
My Interface:
#Retention(RetentionPolicy.RUNTIME)
#Target([ElementType.TYPE])
#GroovyASTTransformationClass("poc.SimpleASTTransformation")
public #interface SimpleAST {
/**
* A class for which builder methods should be created. It will be an error to leave
* this attribute with its default value for some strategies.
*/
Class value()
}
My transformation:
#CompileStatic
#GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
class SimpleASTTransformation implements ASTTransformation {
#Override
void visit(ASTNode[] astNodes, SourceUnit source) {
ClassNode classNode = (ClassNode) astNodes[1]
if (!astNodes) return
if (!astNodes[0]) return
if (!astNodes[1]) return
if (!(astNodes[0] instanceof AnnotationNode)) return
if (!(astNodes[1] instanceof ClassNode)) return
println "Running AST Transformation for ${classNode.getNameWithoutPackage()}..."
AnnotationNode annotationNode = (AnnotationNode) astNodes[0]
ClassExpression classExpression = (ClassExpression) annotationNode.getMember("value")
String packageName = classNode.getPackageName()
String builderClassNameWithoutPackage = classNode.getNameWithoutPackage()
String originalClassNameWithPackage = classExpression.getText()
originalClassNameWithPackage = Validate.checkOriginalClassName(originalClassNameWithPackage)
Class<?> originalClass = Class.forName(originalClassNameWithPackage)
ClassNode originalClassNode = new ClassNode(originalClass)
String originalClassNameWithoutPackage = originalClassNode.getNameWithoutPackage()
println "Generating methods for $originalClassNameWithoutPackage..."
generateTargetField(classNode,originalClass)
println "Transformation applied!"
}
static void generateTargetField(ClassNode classNode, Class originalClass){
ClassNode originalClassNode = new ClassNode(originalClass)
ConstructorCallExpression constructorCallExpression = new ConstructorCallExpression(originalClassNode,new ArgumentListExpression())
FieldNode fieldNode = new FieldNode("target",
2,
originalClassNode,
classNode,
constructorCallExpression)
ArrayList<AnnotationNode> annotationNodes = new ArrayList<>()
annotationNodes.add(new AnnotationNode(new ClassNode(Delegate)))
fieldNode.addAnnotations(annotationNodes)
classNode.addField(fieldNode)
}
}
When I check the byte code there is no getter/setter methods for the fields inside the Class Person (I used #Delegate on the target field)
However, if I Just add the field manually and compile the code I get getter and setters for the fields in class Person.
Person has 2 fields: firstName, lastName both Strings.

Apache Calcite - ReflectiveSchema StackoverflowError

I'm trying to create a simple schema using ReflectiveSchema and then trying to project an Employee "table" using Groovy as my programming language. Code below.
class CalciteDemo {
String doDemo() {
RelNode node = new CalciteAlgebraBuilder().build()
return RelOptUtil.toString(node)
}
class DummySchema {
public final Employee[] emp = [new Employee(1, "Ting"), new Employee(2, "Tong")]
#Override
String toString() {
return "DummySchema"
}
class Employee {
Employee(int id, String name) {
this.id = id
this.name = name
}
public final int id
public final String name
}
}
class CalciteAlgebraBuilder {
FrameworkConfig config
CalciteAlgebraBuilder() {
SchemaPlus rootSchema = Frameworks.createRootSchema(true)
Schema schema = new ReflectiveSchema(new DummySchema())
SchemaPlus rootPlusDummy = rootSchema.add("dummySchema", schema)
this.config = Frameworks.newConfigBuilder().parserConfig(SqlParser.Config.DEFAULT).defaultSchema(rootPlusDummy).traitDefs((List<RelTraitDef>)null).build()
}
RelNode build() {
RelBuilder.create(config).scan("emp").build()
}
}
}
I seem to be correctly passing in the "schema" object to the constructor of the ReflectiveSchema class, but I think its failing while trying to get the fields of the Employee class.
Here's the error
java.lang.StackOverflowError
at java.lang.Class.copyFields(Class.java:3115)
at java.lang.Class.getFields(Class.java:1557)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createStructType(JavaTypeFactoryImpl.java:76)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createType(JavaTypeFactoryImpl.java:160)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createType(JavaTypeFactoryImpl.java:151)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createStructType(JavaTypeFactoryImpl.java:84)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createType(JavaTypeFactoryImpl.java:160)
at org.apache.calcite.jdbc.JavaTypeFactoryImpl.createStructType(JavaTypeFactoryImpl.java:84)
What is wrong with this example?
Seems that by just moving the Employee class a level above, ie. making it a sibling of the DummySchema class, makes the problem go away.
I think the way the org.apache.calcite.jdbc.JavaTypeFactoryImpl of Calcite is written doesn't handle Groovy's internal fields well.

Update a mixed type activity in GetStream.IO using the java stream client loses the type attribute

I have taken the MixedType example code that comes with the java stream client (https://github.com/GetStream/stream-java) and added a update step using updateActivities. After the update the activity stored in stream loses the 'type' attribute. Jackson uses this attribute when you get the activities again and it is deserialising them.
So I get:
Exception in thread "main" Disconnected from the target VM, address: '127.0.0.1:60016', transport: 'socket'
com.fasterxml.jackson.databind.JsonMappingException: Could not resolve type id 'null' into a subtype of [simple type, class io.getstream.client.apache.example.mixtype.MixedType$Match]
at [Source: org.apache.http.client.entity.LazyDecompressingInputStream#29ad44e3; line: 1, column: 619] (through reference chain: io.getstream.client.model.beans.StreamResponse["results"]->java.util.ArrayList[1])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.unknownTypeException(DeserializationContext.java:849)
See here where I have updated the example:
https://github.com/puntaa/stream-java/blob/master/stream-repo-apache/src/test/java/io/getstream/client/apache/example/mixtype/MixedType.java
Any idea what is going on here?
The issue here is originated by Jackson which cannot get the actual instance type of an object inside the collection due to the Java type erasure, if you want to know more about it please read this issue: https://github.com/FasterXML/jackson-databind/issues/336 (which also provides some possible workarounds).
The easiest way to solve it, would be to manually force the value of the property type from within the subclass as shown in the example below:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
#JsonSubTypes({
#JsonSubTypes.Type(value = VolleyballMatch.class, name = "volley"),
#JsonSubTypes.Type(value = FootballMatch.class, name = "football")
})
static abstract class Match extends BaseActivity {
private String type;
public String getType() {
return type;
}
}
static class VolleyballMatch extends Match {
private int nrOfServed;
private int nrOfBlocked;
public VolleyballMatch() {
super.type = "volley";
}
public int getNrOfServed() {
return nrOfServed;
}
public void setNrOfServed(int nrOfServed) {
this.nrOfServed = nrOfServed;
}
public void setNrOfBlocked(int nrOfBlocked) {
this.nrOfBlocked = nrOfBlocked;
}
public int getNrOfBlocked() {
return nrOfBlocked;
}
}
static class FootballMatch extends Match {
private int nrOfPenalty;
private int nrOfScore;
public FootballMatch() {
super.type = "football";
}
public int getNrOfPenalty() {
return nrOfPenalty;
}
public void setNrOfPenalty(int nrOfPenalty) {
this.nrOfPenalty = nrOfPenalty;
}
public int getNrOfScore() {
return nrOfScore;
}
public void setNrOfScore(int nrOfScore) {
this.nrOfScore = nrOfScore;
}
}

Are accessors / mutators auto-defined in Groovy?

In the section on handling Java Beans with Groovy of Groovy In Action, I found this script (slightly modified):
class Book{
String title
}
def groovyBook = new Book()
// explicit way
groovyBook.setTitle('What the heck, really ?')
println groovyBook.getTitle()
// short-hand way
groovyBook.title = 'I am so confused'
println groovyBook.title
There are no such methods in the class Book so how does that work ?
Yes, they are auto defined and calling book.title is actually calling book.getTitle()
See http://groovy.codehaus.org/Groovy+Beans
You can see this in action with the following script:
def debug( clazz ) {
println '----'
clazz.metaClass.methods.findAll { it.name.endsWith( 'Name' ) || it.name.endsWith( 'Age' ) }.each { println it }
}
class A {
String name
int age
}
debug( A )
// Prints
// public int A.getAge()
// public java.lang.String A.getName()
// public void A.setAge(int)
// public void A.setName(java.lang.String)
// Make name final
class B {
final String name
int age
}
debug( B )
// Prints
// public int B.getAge()
// public java.lang.String B.getName()
// public void B.setAge(int)
// Make name private
class C {
private String name
int age
}
debug( C )
// Prints
// public int C.getAge()
// public void C.setAge(int)
// Try protected
class D {
protected String name
int age
}
debug( D )
// Prints
// public int D.getAge()
// public void D.setAge(int)
// And public?
class E {
public String name
int age
}
debug( E )
// Prints
// public int E.getAge()
// public void E.setAge(int)
Several notes:
For all property fields(public ones only), there are autogenerated accesors.
Default visibility is public. So, you should use private/protected keyword to restrict accessor generation.
Inside an accessor there is direct field access. like this.#title
Inside a constructor you have direct access to! This may be unexpected.
For boolean values there are two getters with is and get prefixes.
Each method with such prefixes, even java ones are treated as accessor, and can be referenced in groovy using short syntax.
But sometimes, if you have ambiguous call there may be class cast exception.
Example code for 4-th point.
class A{
private int i = 0;
A(){
i = 4
println("Constructor has direct access. i = $i")
}
void setI(int val) { i = val; println("i is set to $i"); }
int getI(){i}
}
def a = new A() // Constructor has direct access. i = 4
a.i = 5 // i is set to 5
println a.i // 5
​
4-th note is important, if you have some logic in accessor, and want it to be applied every time you call it. So in constructor you should explicit call setI() method!
Example for 7
class A{
private int i = 0;
void setI(String val) { println("String version.")}
void setI(int val) { i = val; println("i is set to $i"); }
}
def a = new A()
a.i = 5 // i is set to 5
a.i = "1s5" // GroovyCastException: Cannot cast object '1s5' with class 'java.lang.String' to class 'int'
​
So, as I see property-like access uses first declared accessor, and don't support overloading. Maybe will be fixed later.
Groovy generates public accessor / mutator methods for fields when and only when there is no access modifier present. For fields declared as public, private or protected no getters and setters will be created.
For fields declared as final only accessors will be created.
All that applies for static fields analogously.

Resources