blob: 42446264ce459766fd26e06b5788623fb728204d [file] [log] [blame]
// Copyright 2004, 2005 The Apache Software Foundation
//
// 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.apache.tapestry.enhance;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.ErrorLog;
import org.apache.hivemind.Location;
import org.apache.hivemind.service.BodyBuilder;
import org.apache.hivemind.service.MethodSignature;
import org.apache.tapestry.BaseComponent;
import org.apache.tapestry.BaseComponentTestCase;
import org.apache.tapestry.IBinding;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.binding.BindingSource;
import org.apache.tapestry.event.PageDetachListener;
import org.apache.tapestry.spec.IComponentSpecification;
import org.apache.tapestry.spec.IPropertySpecification;
import org.apache.tapestry.spec.PropertySpecification;
import org.testng.annotations.Test;
/**
* Tests for {@link org.apache.tapestry.enhance.SpecifiedPropertyWorker}.
*
* @author Howard M. Lewis Ship
* @since 4.0
*/
@Test
public class TestSpecifiedPropertyWorker extends BaseComponentTestCase
{
private List buildPropertySpecs(String name, String type, boolean persistent)
{
return buildPropertySpecs(name, type, persistent, null, null);
}
private List buildPropertySpecs(String name, String type, boolean persistent,
Location location, String initialValue)
{
PropertySpecification ps = new PropertySpecification();
ps.setName(name);
ps.setType(type);
ps.setPersistence(persistent ? "session" : null);
ps.setInitialValue(initialValue);
ps.setLocation(location);
return Collections.singletonList(ps);
}
private IComponentSpecification buildComponentSpecification(List propertySpecs)
{
List names = new ArrayList();
Iterator i = propertySpecs.iterator();
while (i.hasNext())
{
IPropertySpecification ps = (IPropertySpecification) i.next();
names.add(ps.getName());
}
IComponentSpecification result = newSpec();
expect(result.getPropertySpecificationNames()).andReturn(names);
i = propertySpecs.iterator();
while (i.hasNext())
{
IPropertySpecification ps = (IPropertySpecification) i.next();
expect(result.getPropertySpecification(ps.getName())).andReturn(ps);
}
return result;
}
private IComponentSpecification buildComponentSpecification(String name, String type,
boolean persistent)
{
return buildComponentSpecification(buildPropertySpecs(name, type, persistent));
}
public enum TestEnum {
First,
Second
}
public void test_Can_Proxy_Enum()
{
Object obj = TestEnum.First;
assert !EnhanceUtils.canProxyPropertyType(obj.getClass());
assert EnhanceUtils.canProxyPropertyType(List.class);
}
public void testAddNormal() throws Exception
{
Location l = newLocation();
IComponentSpecification spec = buildComponentSpecification(buildPropertySpecs(
"fred",
"boolean",
false,
l,
null));
// Training
EnhancementOperation op = newMock(EnhancementOperation.class);
expect(op.convertTypeName("boolean")).andReturn(boolean.class);
op.validateProperty("fred", boolean.class);
op.claimProperty("fred");
op.addField("_$fred", boolean.class);
expect(op.getAccessorMethodName("fred")).andReturn("isFred");
op.addMethod(
Modifier.PUBLIC,
new MethodSignature(boolean.class, "isFred", null, null),
"return _$fred;",
l);
op.addMethod(Modifier.PUBLIC, new MethodSignature(void.class, "setFred", new Class[]
{ boolean.class }, null), "{\n _$fred = $1;\n}\n", l);
op.addField("_$fred$default", boolean.class);
op.extendMethodImplementation(
IComponent.class,
EnhanceUtils.FINISH_LOAD_SIGNATURE,
"_$fred$default = _$fred;");
op.extendMethodImplementation(
PageDetachListener.class,
EnhanceUtils.PAGE_DETACHED_SIGNATURE,
"_$fred = _$fred$default;");
replay();
SpecifiedPropertyWorker w = new SpecifiedPropertyWorker();
w.performEnhancement(op, spec);
verify();
}
public void testAddWithInitialValue() throws Exception
{
BindingSource bs = newMock(BindingSource.class);
Location l = fabricateLocation(12);
IComponentSpecification spec = buildComponentSpecification(buildPropertySpecs(
"fred",
"java.util.List",
false,
l,
"ognl:foo()"));
InitialValueBindingCreator expectedCreator = new InitialValueBindingCreator(bs,
EnhanceMessages.initialValueForProperty("fred"), "ognl:foo()", l);
// Training
EnhancementOperation op = newMock(EnhancementOperation.class);
expect(op.convertTypeName("java.util.List")).andReturn(List.class);
op.validateProperty("fred", List.class);
op.claimProperty("fred");
op.addField("_$fred", List.class);
expect(op.getAccessorMethodName("fred")).andReturn("getFred");
op.addMethod(
Modifier.PUBLIC,
new MethodSignature(List.class, "getFred", null, null),
"return _$fred;",
l);
op.addMethod(Modifier.PUBLIC, new MethodSignature(void.class, "setFred", new Class[]
{ List.class }, null), "{\n _$fred = $1;\n}\n", l);
expect(op.addInjectedField(
"_$fred$initialValueBindingCreator",
InitialValueBindingCreator.class,
expectedCreator)).andReturn("_$fred$initialValueBindingCreator");
op.addField("_$fred$initialValueBinding", IBinding.class);
op
.extendMethodImplementation(
IComponent.class,
EnhanceUtils.FINISH_LOAD_SIGNATURE,
"_$fred$initialValueBinding = _$fred$initialValueBindingCreator.createBinding(this);\n");
expect(op.getClassReference(List.class)).andReturn("_$class$java$util$List");
String code = "_$fred = (java.util.List) _$fred$initialValueBinding.getObject(_$class$java$util$List);\n";
op.extendMethodImplementation(IComponent.class, EnhanceUtils.FINISH_LOAD_SIGNATURE, code);
op.extendMethodImplementation(
PageDetachListener.class,
EnhanceUtils.PAGE_DETACHED_SIGNATURE,
code);
replay();
SpecifiedPropertyWorker w = new SpecifiedPropertyWorker();
w.setBindingSource(bs);
w.performEnhancement(op, spec);
verify();
}
public void test_Add_Persistent() throws Exception
{
IComponentSpecification spec = buildComponentSpecification(
"barney",
"java.lang.String",
true);
// Training
EnhancementOperation op = newMock(EnhancementOperation.class);
expect(op.convertTypeName("java.lang.String")).andReturn(String.class);
op.validateProperty("barney", String.class);
op.claimProperty("barney");
op.addField("_$barney", String.class);
expect(op.getAccessorMethodName("barney")).andReturn("getBarney");
op.addMethod(
Modifier.PUBLIC,
new MethodSignature(String.class, "getBarney", null, null),
"return _$barney;",
null);
BodyBuilder b = new BodyBuilder();
b.begin();
/*
b.addln("if ($1 != null && org.apache.tapestry.record.ObservedProperty.class.isAssignableFrom($1.getClass())) {");
b.add(" $1 = (" + ClassFabUtils.getJavaClassName(String.class) + ")((org.apache.tapestry.record.ObservedProperty)$1)");
b.addln(".getCGProperty();");
b.addln("}");
*/
b.addln("org.apache.tapestry.Tapestry#fireObservedChange(this, \"barney\", ($w) $1);");
b.addln("_$barney = $1;");
b.end();
op.addMethod(Modifier.PUBLIC, new MethodSignature(void.class, "setBarney", new Class[]
{ String.class }, null), b.toString(), null);
op.addField("_$barney$default", String.class);
op.extendMethodImplementation(
IComponent.class,
EnhanceUtils.FINISH_LOAD_SIGNATURE,
"_$barney$default = _$barney;");
op.extendMethodImplementation(
PageDetachListener.class,
EnhanceUtils.PAGE_DETACHED_SIGNATURE,
"_$barney = _$barney$default;");
replay();
SpecifiedPropertyWorker w = new SpecifiedPropertyWorker();
w.performEnhancement(op, spec);
verify();
}
public void testFailure() throws Exception
{
Location l = fabricateLocation(207);
// Should be "java.lang.Long"
List propertySpecs = buildPropertySpecs("wilma", "Long", false, l, null);
IComponentSpecification spec = buildComponentSpecification(propertySpecs);
EnhancementOperation op = newMock(EnhancementOperation.class);
op.convertTypeName("Long");
Throwable ex = new ApplicationRuntimeException("Simulated error.");
expectLastCall().andThrow(ex);
expect(op.getBaseClass()).andReturn(BaseComponent.class);
ErrorLog log = newMock(ErrorLog.class);
log
.error(
"Error adding property wilma to class org.apache.tapestry.BaseComponent: Simulated error.",
l,
ex);
replay();
SpecifiedPropertyWorker w = new SpecifiedPropertyWorker();
w.setErrorLog(log);
w.performEnhancement(op, spec);
verify();
}
}