/*
* Copyright (C) 2011 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.errai.codegen.test;
import static org.jboss.errai.codegen.meta.MetaClassFactory.parameterizedAs;
import static org.jboss.errai.codegen.meta.MetaClassFactory.typeParametersOf;
import java.lang.annotation.Retention;
import org.jboss.errai.codegen.Context;
import org.jboss.errai.codegen.Parameter;
import org.jboss.errai.codegen.Statement;
import org.jboss.errai.codegen.Variable;
import org.jboss.errai.codegen.builder.ClassStructureBuilder;
import org.jboss.errai.codegen.builder.impl.ClassBuilder;
import org.jboss.errai.codegen.builder.impl.ObjectBuilder;
import org.jboss.errai.codegen.meta.MetaClass;
import org.jboss.errai.codegen.test.model.Bar;
import org.jboss.errai.codegen.test.model.Mrshlr;
import org.jboss.errai.codegen.util.Stmt;
import org.junit.Test;
/**
* @author Mike Brock <cbrock@redhat.com>
* @author Christian Sadilek <csadilek@redhat.com>
*/
public class AnonymousClassStructureBuilderTest extends AbstractCodegenTest {
@Test
public void testAnonymousAnnotation() {
String src = ObjectBuilder.newInstanceOf(Retention.class)
.extend()
.publicOverridesMethod("annotationType")
.append(Stmt.load(Retention.class).returnValue())
.finish()
.finish()
.toJavaString();
assertEquals("failed to generate anonymous annotation with overloaded method",
"new java.lang.annotation.Retention() {\n" +
"public Class annotationType() {\n" +
"return java.lang.annotation.Retention.class;\n" +
"}\n" +
"}", src);
}
@Test
public void testAnonymousClass() {
String src = ObjectBuilder.newInstanceOf(Bar.class, Context.create().autoImport())
.extend()
.publicOverridesMethod("setName", Parameter.of(String.class, "name"))
.append(Stmt.loadClassMember("name").assignValue(Variable.get("name")))
.finish()
.finish()
.toJavaString();
assertEquals("failed to generate anonymous class with overloaded construct",
"new Bar() {\n" +
"public void setName(String name) {\n" +
"this.name = name;\n" +
"}\n" +
"}", src);
}
@Test
public void testAnonymousClassWithConstructor() {
String src = ObjectBuilder.newInstanceOf(Bar.class, Context.create().autoImport())
.extend("test")
.publicOverridesMethod("setName", Parameter.of(String.class, "name"))
.append(Stmt.loadClassMember("name").assignValue(Variable.get("name")))
.finish()
.finish()
.toJavaString();
assertEquals("failed to generate anonymous class with overloaded construct",
"new Bar(\"test\") {\n" +
"public void setName(String name) {\n" +
"this.name = name;\n" +
"}\n" +
"}", src);
}
@Test
public void testAnonymousClassWithInitializationBlock() {
String src = ObjectBuilder.newInstanceOf(Bar.class, Context.create().autoImport())
.extend()
.initialize()
.append(Stmt.loadClassMember("name").assignValue("init"))
.finish()
.publicOverridesMethod("setName", Parameter.of(String.class, "name"))
.append(Stmt.loadClassMember("name").assignValue(Variable.get("name")))
.finish()
.finish()
.toJavaString();
assertEquals("failed to generate anonymous class with overloaded construct",
"new Bar() {\n" +
"{\n" +
"name = \"init\";" +
"\n}\n" +
"public void setName(String name) {\n" +
"this.name = name;\n" +
"}\n" +
"}", src);
}
@Test
public void testAnonymousClassReferencingOuterClass() {
ClassStructureBuilder<?> outer = ClassBuilder.define("org.foo.Outer").publicScope().body();
Statement anonInner =
ObjectBuilder.newInstanceOf(Bar.class, Context.create().autoImport())
.extend()
.publicOverridesMethod("setName", Parameter.of(String.class, "name"))
.append(
Stmt.loadStatic(outer.getClassDefinition(), "this").loadField("outerName").assignValue(
Variable.get("name")))
.append(Stmt.loadStatic(outer.getClassDefinition(), "this").invoke("setOuterName", Variable.get("name")))
.finish()
.finish();
String cls = outer
.publicField("outerName", String.class)
.finish()
.publicMethod(void.class, "setOuterName", Parameter.of(String.class, "outerName"))
.append(Stmt.loadClassMember("outerName").assignValue(Variable.get("outerName")))
.finish()
.publicMethod(void.class, "test")
.append(anonInner)
.finish()
.toJavaString();
assertEquals("failed to generate anonymous class accessing outer class",
"package org.foo;\n" +
"import org.jboss.errai.codegen.test.model.Bar;\n" +
"public class Outer {\n" +
"public String outerName;\n" +
"public void setOuterName(String outerName) {\n" +
"this.outerName = outerName;\n" +
"}\n" +
"public void test() {\n" +
"new Bar() {\n" +
"public void setName(String name) {\n" +
"Outer.this.outerName = name;\n" +
"Outer.this.setOuterName(name);\n" +
"}\n" +
"};\n" +
"}\n" +
"}\n", cls);
}
@Test
public void testAssignmentOfAnonymousClass() {
Statement stmt = ObjectBuilder.newInstanceOf(Retention.class)
.extend()
.publicOverridesMethod("annotationType")
.append(Stmt.load(Retention.class).returnValue())
.finish()
.finish();
Statement declaration = Stmt.declareVariable(java.lang.annotation.Annotation.class)
.named("foo").initializeWith(stmt);
String cls = declaration.generate(Context.create());
assertEquals("java.lang.annotation.Annotation foo = new java.lang.annotation.Retention() {\n" +
" public Class annotationType() {\n" +
" return java.lang.annotation.Retention.class;\n" +
" }\n" +
"\n" +
"\n" +
"};", cls);
}
/** Regression test for ERRAI-363. */
@Test
public void testReferenceToAnonymousClassMember() throws Exception {
ClassStructureBuilder<?> builder = ClassBuilder.define("com.foo.A").publicScope().body();
builder.privateMethod(void.class, "method")
.append(ObjectBuilder.newInstanceOf(Runnable.class).extend()
.privateField("memberOfRunnable", Object.class).finish()
.publicOverridesMethod("run").append(Stmt.loadVariable("memberOfRunnable").invoke("hashCode")).finish()
.finish())
.finish();
String javaString = builder.toJavaString();
assertEquals("package com.foo; public class A { private void method() { new Runnable() { private Object memberOfRunnable; public void run() { memberOfRunnable.hashCode(); } }; } }", javaString);
}
@Test
public void testParameterizedImplementation() throws Exception {
final MetaClass mrshlrClass = parameterizedAs(Mrshlr.class, typeParametersOf(Bar.class));
final ObjectBuilder builder = Stmt.newObject(mrshlrClass).extend()
.publicOverridesMethod("get")
.finish()
.finish();
final String javaString = builder.toJavaString();
assertEquals("new org.jboss.errai.codegen.test.model.Mrshlr<org.jboss.errai.codegen.test.model.Bar>() {\n" +
" public Class<org.jboss.errai.codegen.test.model.Bar> get() {\n" +
"\n" +
" }\n" +
"}", javaString);
}
}