Author: hlship
Date: Tue Oct 24 13:16:48 2006
New Revision: 467463
URL: http://svn.apache.org/viewvc?view=rev&rev=467463
Log:
Switch tests to use nice mocks instead of strict mocks
Give greater control over invoking super class methods when adding new methods
to a class
Add @Mixins and @MixinClasses annotation
Change ComponentWorker to collect mixin information (from @Mixins and
@MixinClasses)
Update PageLoader to make use of declared instance mixins
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/MixinClasses.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Mixins.java
tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableEmbeddedComponentModelImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactory.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/EmbeddedComponentModel.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InstanceMixin.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InstanceMixin.html
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/MixinClasses.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/MixinClasses.java?view=auto&rev=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/MixinClasses.java
(added)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/MixinClasses.java
Tue Oct 24 13:16:48 2006
@@ -0,0 +1,22 @@
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Used to attach one or more instance mixins to an embedded component. Each
mixin is specified as a
+ * specific class. This annotation is only recognized when used in conjuction
with the
+ * [EMAIL PROTECTED] Component} annotation.
+ *
+ * @see Mixins
+ */
[EMAIL PROTECTED](FIELD)
[EMAIL PROTECTED]
[EMAIL PROTECTED](RUNTIME)
+public @interface MixinClasses {
+ Class[] value();
+}
Added:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Mixins.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Mixins.java?view=auto&rev=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Mixins.java
(added)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/annotations/Mixins.java
Tue Oct 24 13:16:48 2006
@@ -0,0 +1,24 @@
+package org.apache.tapestry.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Used to attach one ore more instance mixin to an embedded component. Each
mixin is specified in
+ * terms of a logical mixin type name. This annotation is only recognized when
used in conjuction
+ * with the [EMAIL PROTECTED] Component} annotation.
+ *
+ * @see MixinClasses
+ */
[EMAIL PROTECTED](FIELD)
[EMAIL PROTECTED]
[EMAIL PROTECTED](RUNTIME)
+public @interface Mixins {
+
+ /** One or more mixin type names, from which actual mixin class names can
be resolved. */
+ String[] value();
+}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableComponentModelImpl.java
Tue Oct 24 13:16:48 2006
@@ -220,4 +220,8 @@
return logicalFieldName;
}
+ public boolean isRootClass()
+ {
+ return _parentModel == null;
+ }
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableEmbeddedComponentModelImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableEmbeddedComponentModelImpl.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableEmbeddedComponentModelImpl.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/model/MutableEmbeddedComponentModelImpl.java
Tue Oct 24 13:16:48 2006
@@ -14,14 +14,15 @@
package org.apache.tapestry.internal.model;
-import static org.apache.tapestry.ioc.IOCUtilities.toSimpleId;
import static org.apache.tapestry.util.CollectionFactory.newMap;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.tapestry.internal.util.InternalUtils;
import org.apache.tapestry.model.MutableEmbeddedComponentModel;
+import org.apache.tapestry.util.CollectionFactory;
public class MutableEmbeddedComponentModelImpl implements
MutableEmbeddedComponentModel
{
@@ -35,8 +36,8 @@
private Map<String, String> _parameters;
- /** Maps for simple mixin name to fully qualified mixin class name. */
- private Map<String, String> _mixins;
+ /** List of mixin class names. */
+ private List<String> _mixinClassNames;
public MutableEmbeddedComponentModelImpl(String id, String componentType,
String componentClassName, String declaredClass)
@@ -95,31 +96,27 @@
return InternalUtils.get(_parameters, parameterName);
}
- public String getMixinClassName(String mixinName)
+ public List<String> getMixinClassNames()
{
- return InternalUtils.get(_mixins, mixinName);
- }
+ if (_mixinClassNames == null)
+ return Collections.emptyList();
- public List<String> getMixinNames()
- {
- return InternalUtils.sortedKeys(_mixins);
+ return Collections.unmodifiableList(_mixinClassNames);
}
public void addMixin(String mixinClassName)
{
- String simpleName = toSimpleId(mixinClassName);
-
- if (_mixins == null)
+ if (_mixinClassNames == null)
{
- _mixins = newMap();
+ _mixinClassNames = CollectionFactory.newList();
}
else
{
- if (_mixins.containsKey(simpleName))
- throw new
IllegalArgumentException(ModelMessages.duplicateMixin(simpleName, _id));
+ if (_mixinClassNames.contains(mixinClassName))
+ throw new IllegalArgumentException(ModelMessages
+ .duplicateMixin(mixinClassName, _id));
}
- _mixins.put(simpleName, mixinClassName);
+ _mixinClassNames.add(mixinClassName);
}
-
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorker.java
Tue Oct 24 13:16:48 2006
@@ -60,23 +60,33 @@
{
List<MethodSignature> methods =
transformation.findMethodsWithAnnotation(_methodAnnotation);
+ // Except in the root class, don't bother to add a new method unless
there's something to
+ // call (beside super).
+
if (methods.isEmpty())
return;
BodyBuilder builder = new BodyBuilder();
builder.begin();
- // Check to see if the event is aborted on entry (shouldn't happen),
or from super-class
- // implementation (a real possibility).
+ // If in a subclass, invoke the super class version first.
- builder.addln(CHECK_ABORT_FLAG);
+ if (!model.isRootClass())
+ {
+ builder.addln("super.%s($$);",
_lifecycleMethodSignature.getMethodName());
+ builder.addln(CHECK_ABORT_FLAG);
+ }
for (MethodSignature sig : methods)
addMethodCallToBody(builder, sig, transformation);
builder.end();
- transformation.extendMethod(_lifecycleMethodSignature,
builder.toString());
+ // Let's see if this works; for base classes, we are adding an empty
method the adding a
+ // non-empty
+ // method "on top of it".
+
+ transformation.addMethod(_lifecycleMethodSignature,
builder.toString());
}
private void addMethodCallToBody(BodyBuilder builder, MethodSignature sig,
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/ComponentWorker.java
Tue Oct 24 13:16:48 2006
@@ -15,21 +15,31 @@
package org.apache.tapestry.internal.services;
import org.apache.tapestry.annotations.Component;
+import org.apache.tapestry.annotations.MixinClasses;
+import org.apache.tapestry.annotations.Mixins;
import org.apache.tapestry.internal.util.InternalUtils;
+import org.apache.tapestry.model.ComponentModel;
import org.apache.tapestry.model.MutableComponentModel;
import org.apache.tapestry.model.MutableEmbeddedComponentModel;
import org.apache.tapestry.services.ClassTransformation;
+import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.ComponentClassTransformWorker;
import org.apache.tapestry.services.TransformConstants;
/**
* Finds fields with the [EMAIL PROTECTED]
org.apache.tapestry.annotations.Component} annotation and updates
- * the model.
- *
- *
+ * the model. Also checks for the [EMAIL PROTECTED] Mixins} and [EMAIL
PROTECTED] MixinClasses} annotations and uses them
+ * to update the [EMAIL PROTECTED] ComponentModel}.
*/
public class ComponentWorker implements ComponentClassTransformWorker
{
+ private final ComponentClassResolver _resolver;
+
+ public ComponentWorker(final ComponentClassResolver resolver)
+ {
+ _resolver = resolver;
+ }
+
public void transform(ClassTransformation transformation,
MutableComponentModel model)
{
for (String fieldName :
transformation.findFieldsWithAnnotation(Component.class))
@@ -60,7 +70,37 @@
transformation
.extendMethod(TransformConstants.CONTAINING_PAGE_DID_LOAD_SIGNATURE, body);
+ addMixinClasses(fieldName, transformation, embedded);
+ addMixinTypes(fieldName, transformation, embedded);
+
transformation.claimField(fieldName, annotation);
+ }
+ }
+
+ private void addMixinClasses(String fieldName, ClassTransformation
transformation,
+ MutableEmbeddedComponentModel model)
+ {
+ MixinClasses annotation = transformation.getFieldAnnotation(fieldName,
MixinClasses.class);
+
+ if (annotation == null)
+ return;
+
+ for (Class c : annotation.value())
+ model.addMixin(c.getName());
+ }
+
+ private void addMixinTypes(String fieldName, ClassTransformation
transformation,
+ MutableEmbeddedComponentModel model)
+ {
+ Mixins annotation = transformation.getFieldAnnotation(fieldName,
Mixins.class);
+
+ if (annotation == null)
+ return;
+
+ for (String typeName : annotation.value())
+ {
+ String mixinClassName =
_resolver.resolveMixinTypeToClassName(typeName);
+ model.addMixin(mixinClassName);
}
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/InternalClassTransformationImpl.java
Tue Oct 24 13:16:48 2006
@@ -150,12 +150,10 @@
"resources",
null);
- MethodSignature sig = new MethodSignature(Modifier.PUBLIC,
ComponentResources.class
- .getName(), "getComponentResources", null, null);
+ MethodSignature sig = new MethodSignature(Modifier.PUBLIC |
Modifier.FINAL,
+ ComponentResources.class.getName(), "getComponentResources",
null, null);
- // Override the default, empty implementation to simply return the
field.
-
- extendMethod(sig, "return " + _resourcesFieldName + ";");
+ addMethod(sig, "return " + _resourcesFieldName + ";");
}
@SuppressNullCheck
@@ -479,12 +477,17 @@
newMethod.setBody(null);
_ctClass.addMethod(newMethod);
+
+ MethodSignature sig = getMethodSignature(newMethod);
+
+ addMethodToDescription("add default", sig, "<default>");
}
catch (CannotCompileException ex)
{
throw new
RuntimeException(ServicesMessages.errorAddingMethod(_ctClass, method
.getName(), ex), ex);
}
+
}
/**
@@ -541,18 +544,43 @@
CtClass[] parameters = buildCtClassList(signature.getParameterTypes());
CtClass[] exceptions = buildCtClassList(signature.getExceptionTypes());
- CtMethod method = new CtMethod(returnType, signature.getMethodName(),
parameters, _ctClass);
+ String action = "add";
- // TODO: Check for duplicate method add
+ try
+ {
+ CtMethod existing =
_ctClass.getDeclaredMethod(signature.getMethodName(), parameters);
- method.setModifiers(signature.getModifiers());
+ if (existing != null)
+ {
+ action = "replace";
+
+ _ctClass.removeMethod(existing);
+ }
+ }
+ catch (NotFoundException ex)
+ {
+ // That's ok. Kind of sloppy to rely on a thrown exception; wish
getDeclaredMethod()
+ // would return null for
+ // that case. Alternately, we could maintain a set of the method
signatures of declared
+ // or added methods.
+ }
try
{
+
+ CtMethod method = new CtMethod(returnType,
signature.getMethodName(), parameters,
+ _ctClass);
+
+ // TODO: Check for duplicate method add
+
+ method.setModifiers(signature.getModifiers());
+
method.setBody(methodBody);
method.setExceptionTypes(exceptions);
_ctClass.addMethod(method);
+
+ _addedMethods.add(method);
}
catch (CannotCompileException ex)
{
@@ -566,9 +594,7 @@
throw new RuntimeException(ex);
}
- _addedMethods.add(method);
-
- addMethodToDescription("add", signature, methodBody);
+ addMethodToDescription(action, signature, methodBody);
}
private CtClass[] buildCtClassList(String[] typeNames)
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactory.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactory.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactory.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactory.java
Tue Oct 24 13:16:48 2006
@@ -89,4 +89,17 @@
* used to resolve the mixin class name
*/
void addMixinByTypeName(ComponentPageElement component, String mixinType);
+
+ /**
+ * Adds a mixin to the element.
+ * <p>
+ * Sure, this isn't quite a <em>factory</em> method, but PEF has all the
tools to accomplish
+ * this handy, as opposed to PageLoaderImpl.
+ *
+ * @param component
+ * the component to which a mixin will be added
+ * @param mixinClassName
+ * fully qualified class name of the mixin
+ */
+ void addMixinByClassName(ComponentPageElement component, String
mixinClassName);
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageElementFactoryImpl.java
Tue Oct 24 13:16:48 2006
@@ -183,6 +183,11 @@
{
String mixinClassName =
_componentClassResolver.resolveMixinTypeToClassName(mixinType);
+ addMixinByClassName(component, mixinClassName);
+ }
+
+ public void addMixinByClassName(ComponentPageElement component, String
mixinClassName)
+ {
Instantiator mixinInstantiator = _componentInstantiatorSource
.findInstantiator(mixinClassName);
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/internal/services/PageLoaderImpl.java
Tue Oct 24 13:16:48 2006
@@ -318,7 +318,7 @@
embeddedComponentClassName,
startComponent.getLocation());
- addMixinsToComponent(newComponent,
startComponent.getMixins());
+ addMixinsToComponent(newComponent, embeddedModel,
startComponent.getMixins());
add(loadingElement, activeComponent, newComponent);
@@ -366,13 +366,20 @@
}
}
- private void addMixinsToComponent(ComponentPageElement component, String
mixins)
+ private void addMixinsToComponent(ComponentPageElement component,
EmbeddedComponentModel model,
+ String mixins)
{
- if (mixins == null)
- return;
+ if (model != null)
+ {
+ for (String mixinClassName : model.getMixinClassNames())
+ _pageElementFactory.addMixinByClassName(component,
mixinClassName);
+ }
- for (String type : mixins.split(","))
- _pageElementFactory.addMixinByTypeName(component, type);
+ if (mixins != null)
+ {
+ for (String type : mixins.split(","))
+ _pageElementFactory.addMixinByTypeName(component, type);
+ }
}
private void addParametersFromModel(EmbeddedComponentModel model,
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/ComponentModel.java
Tue Oct 24 13:16:48 2006
@@ -18,6 +18,7 @@
import org.apache.commons.logging.Log;
import org.apache.tapestry.Resource;
+import org.apache.tapestry.annotations.ComponentClass;
import org.apache.tapestry.annotations.Persist;
/**
@@ -82,4 +83,13 @@
* @throw IllegalArgumentException if the named field is not marked as
persistent
*/
String getFieldPersistenceStrategy(String fieldName);
+
+ /**
+ * Returns true if the modeled component is a root class, a component
class whose parent does
+ * not have the [EMAIL PROTECTED] ComponentClass} annotation. This is
often used to determine whether to
+ * invoke the super-class implementation of certain methods.
+ *
+ * @return true if a root class, false if a subclass
+ */
+ boolean isRootClass();
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/EmbeddedComponentModel.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/EmbeddedComponentModel.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/EmbeddedComponentModel.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/model/EmbeddedComponentModel.java
Tue Oct 24 13:16:48 2006
@@ -43,14 +43,9 @@
String getParameterValue(String parameterName);
/**
- * Returns the names of all mixins added to this component, sorted
alphabetically. These are the
- * "logical" names for each mixin, which is the class name of the mixin,
less the package
- * prefix.
- *
- * @return the names of the added mixins, sorted alphabetically
+ * Returns the fully qualified class names of all mixins added to this
component, sorted
+ * alphabetically.
*/
- List<String> getMixinNames();
+ List<String> getMixinClassNames();
- /** Returns the fully qualified class name of an added mixin, given the
mixin's simple name. */
- String getMixinClassName(String mixinName);
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/ClassTransformation.java
Tue Oct 24 13:16:48 2006
@@ -37,8 +37,6 @@
* <p>
* The majority of methods concern the <em>declared</em> members (field and
methods) of a specific
* class, rather than any fields or methods inherited from a base class.
- *
- *
*/
public interface ClassTransformation
{
@@ -224,7 +222,9 @@
* change the return value, use the <code>$_</code> pseudo variable.
* <p>
* The method may be declared in the class, or may be inherited from a
super-class. For
- * inherited methods, a method is added that first invokes the super
implementation.
+ * inherited methods, a method is added that first invokes the super
implementation. Use
+ * [EMAIL PROTECTED] #addMethod(MethodSignature, String)} when it is
necessary to control when the
+ * super-class method is invoked.
*
* @param signature
* the signature of the method to extend
@@ -244,7 +244,13 @@
*/
String getResourcesFieldName();
- /** Adds a new method to the transformed class. */
+ /**
+ * Adds a new method to the transformed class. Replaces any existing
method declared for the
+ * class. When overriding a super-class method, you should use
+ * [EMAIL PROTECTED] #extendMethod(MethodSignature, String)}, or you
should remember to invoke the super
+ * class implemetation explicitly. Use this method to control when the
super-class
+ * implementation is invoked.
+ */
void addMethod(MethodSignature signature, String methodBody);
/**
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/services/TapestryModule.java
Tue Oct 24 13:16:48 2006
@@ -486,15 +486,14 @@
* of the request</li>
* <li>SetupRender, BeginRender, etc. -- correspond to component render
phases and annotations</li>
* </ul>
- *
- * @param configuration
*/
public static void contributeComponentClassTransformWorker(
OrderedConfiguration<ComponentClassTransformWorker> configuration,
ServiceLocator locator,
@InjectService("tapestry.ioc.MasterObjectProvider")
ObjectProvider objectProvider, @InjectService("InjectionProvider")
InjectionProvider injectionProvider, @InjectService("Environment")
- Environment environment)
+ Environment environment,
@InjectService("tapestry.ComponentClassResolver")
+ ComponentClassResolver resolver)
{
// TODO: Proper scheduling of all of this. Since a given field or
method should
// only have a single annotation, the order doesn't matter so much, as
long as
@@ -502,7 +501,7 @@
configuration.add("Inject", new InjectWorker(objectProvider, locator,
injectionProvider));
configuration.add("Parameter", new ParameterWorker());
- configuration.add("Component", new ComponentWorker());
+ configuration.add("Component", new ComponentWorker(resolver));
configuration.add("Environment", new EnvironmentalWorker(environment));
configuration.add("OnEvent", new OnEventWorker());
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/java/org/apache/tapestry/test/TestBase.java
Tue Oct 24 13:16:48 2006
@@ -28,7 +28,9 @@
* Extends from [EMAIL PROTECTED] org.testng.Assert} to bring in all the
public static assert methods without
* requiring extra imports.
* <p>
- * Provides common mock factory and mock trainer methods.
+ * Provides common mock factory and mock trainer methods. Uses a thread-local
<em>nice</em> mock
+ * control for all created mocks. Nice mocks don't care about the order in
which mock methods are
+ * invoked, and will return an appropriate null/0/false value for any
unexpected method invocations.
*/
public class TestBase extends Assert
{
@@ -37,7 +39,7 @@
@Override
protected IMocksControl initialValue()
{
- return EasyMock.createStrictControl();
+ return EasyMock.createNiceControl();
}
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/main/resources/org/apache/tapestry/internal/model/ModelStrings.properties
Tue Oct 24 13:16:48 2006
@@ -15,5 +15,5 @@
duplicate-parameter=Parameter '%s' of component %s is already defined.
duplicate-parameter-value=A value for parameter '%s' of embedded component %s
(of component class %s) has already been provided.
duplicate-component-id=Embedded component '%s' has already been defined for
component class %s.
-duplicate-mixin=Mixin '%s' for component %s has already been defined.
+duplicate-mixin=Mixin %s (for component %s) has already been defined.
missing-persistent-field=No field persistence strategy has been defined for
field '%s'.
Added: tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt?view=auto&rev=467463
==============================================================================
--- tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt (added)
+++ tapestry/tapestry5/tapestry-core/trunk/src/site/apt/guide/mixins.apt Tue
Oct 24 13:16:48 2006
@@ -0,0 +1,105 @@
+ ---
+ Component Mixins
+ ---
+
+Component Mixins
+
+ Tapestry 5 includes a radical feature, <component mixins>. Component mixins
are a tricky concept; it basically allows
+ a true component to be mixed together with special limited components called
mixins. The component plus its mixins are
+ represented as just a single tag in the component template, but all the
behavior of all the elements.
+
+ The planned uses for this are to add validation to user input fields, or to
add Ajax effects and behaviors to all
+ sorts of components.
+
+ You can think of a mixin as a kind of mashup for a component; it combines
the behavior of the component
+ with the behavior of the mixin, and bundles it all in one place.
+
+ Mixins are used in two different scenarios: <Instance mixins> and
<Implementation mixins>.
+
+Mixin Classes
+
+ Mixin classes are stored in a <<<mixins>>> sub-package, below the
application (or library)
+ root package. This parallels where component and page classes are stored.
+
+ Other than that, mixin classes are exactly the same as any other component
class, including
+ the need for
{{{../apidocs/org/apache/tapestry/annotations/ComponentClass.html}ComponentClass
annotation}}.
+
+Mixin Limitations
+
+ Currently, mixins are allowed to do anything a component can do, including
parameters,
+ render phase methods.
+
+ Mixins may not have a template. They integrate with the component strictly
in terms of invoking
+ render phase methods.
+
+ Mixins may have persistent fields, but currently, this is not implemented
perfectly (there is a potential
+ for a name clash between a mixin and the component or another mixin). Use
persistent fields with
+ mixins with care ... or better yet, delegate persistence to the container
using parameters.
+
+Instance Mixins
+
+ An instance mixin is a mixin applied to a specific <instance> of a
component. This can be done
+ in the {{{templates.html}component template}} with the mixins attribute of
the
+ \<comp\> element. This is a comma-separated list of mixin names.
+
+ Alternately, when the
{{{../apidocs/org/apache/tapestry/annotations/Component.html}Component
annotation}}
+ is used to define the component type, you may specify the mixins in two ways:
+
+ * The {{{../apidocs/org/apache/tapestry/annotations/Mixins.html}Mixins
annotation}} allows a list
+ of mixin names to be specified.
+
+ * The
{{{../apidocs/org/apache/tapestry/annotations/MixinClasses.html}MixinClasses
annotation}}
+ allows a set of mixin class to be specified directly.
+
+ []
+
+ The former is often less verbose, and allows core mixins to be overridden
with application-specific
+ mixins. The later format is more specific and more friendly in terms of
refactoring (renaming a
+ mixin class will rename the entry in the MixinClasses annotation as well).
+
+ Example:
+
++----+
+
+ @Component(parameters=. . .) @Mixins({"Autocomplete", "DefaultFromCookie"})
+ private TextField _userId;
++----+
+
+ This example defines a component of type TextField and mixes in the
<hypothetical> Autocomplete
+ and DefaultFromCookie mixins.
+
+Mixin Parameters
+
+ Mixins are allowed to have parameters, just like components.
+
+ When binding parameters (either in the template, or using the parameters
attribute
+ of the Component annotation).
+
+ Tapestry will match each parameter name against the parameters defined by
each class
+ (which is to say, the component and each mixin).
+
+ If the component and a mix both define a parameter with the same name, then
the component wins:
+ the component's parameter will be bound, and the mixin's parameter will be
unbound.
+
+ Alternately, you may prefix the name of the parameter with the <unqualified>
name of the Mixin class;
+ this eliminates the ambiguity. Example:
+
++-----+
+ @Component(parameters={"Autocomplete.id=auto", . . . })
@Mixins("Autocomplete", "DefaultFromCookie"})
+ private TextField _userId;
++-----+
+
+Implementation Mixins
+
+ Not yet implemented.
+
+Render Phase Ordering
+
+ This is under consideration. To some degree, if a mixin and the core
component both implement
+ methods for the same render phase, then the order of operations for
BeginRender and AfterRender
+ should be reversed.
+
+ Currently, the order is mixins, then render phase methods from the
components' super classes, the render phase
+ methods in the component's class.
+
+
\ No newline at end of file
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
Tue Oct 24 13:16:48 2006
@@ -234,16 +234,27 @@
{
_selenium.open(BASE_URL);
+ final String[] dates =
+ { "Jun 13, 1999", "Jul 15, 2001", "Dec 4, 2005" };
+
clickAndWait("link=InstanceMixin");
String body = _selenium.getHtmlSource();
- assertTrue(body.contains("[Jun 13, 1999]"));
+ for (String date : dates)
+ {
+ String snippet = String.format("[%s]", date);
+ assertTrue(body.contains(snippet), snippet);
+ }
clickAndWait("link=Toggle emphasis");
body = _selenium.getHtmlSource();
- assertTrue(body.contains("[<em>Jun 13, 1999</em>]"));
+ for (String date : dates)
+ {
+ String snippet = String.format("[<em>%s</em>]", date);
+ assertTrue(body.contains(snippet), snippet);
+ }
}
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InstanceMixin.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InstanceMixin.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InstanceMixin.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/integration/app1/pages/InstanceMixin.java
Tue Oct 24 13:16:48 2006
@@ -5,19 +5,40 @@
import java.text.Format;
import java.util.Calendar;
+import org.apache.tapestry.annotations.Component;
import org.apache.tapestry.annotations.ComponentClass;
+import org.apache.tapestry.annotations.MixinClasses;
+import org.apache.tapestry.annotations.Mixins;
import org.apache.tapestry.annotations.OnEvent;
import org.apache.tapestry.annotations.Persist;
import org.apache.tapestry.annotations.Retain;
+import org.apache.tapestry.integration.app1.components.Output;
+import org.apache.tapestry.integration.app1.mixins.Emphasis;
@ComponentClass
public class InstanceMixin
{
+ @Component(parameters =
+ { "value=date2", "format=format", "test=showEmphasis" })
+ @Mixins("Emphasis")
+ private Output _output2;
+
+ @Component(parameters =
+ { "value=date3", "format=format", "test=showEmphasis" })
+ @MixinClasses(Emphasis.class)
+ private Output _output3;
+
@Retain
private final Format _format =
DateFormat.getDateInstance(DateFormat.MEDIUM);
@Retain
- private final Date _date = new Date(99, Calendar.JUNE, 13);
+ private final Date _date1 = new Date(99, Calendar.JUNE, 13);
+
+ @Retain
+ private final Date _date2 = new Date(101, Calendar.JULY, 15);
+
+ @Retain
+ private final Date _date3 = new Date(105, Calendar.DECEMBER, 4);
@Persist
private boolean _showEmphasis;
@@ -27,9 +48,19 @@
return _format;
}
- public Date getDate()
+ public Date getDate1()
+ {
+ return _date1;
+ }
+
+ public Date getDate2()
+ {
+ return _date2;
+ }
+
+ public Date getDate3()
{
- return _date;
+ return _date3;
}
public boolean getShowEmphasis()
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/model/MutableComponentModelImplTest.java
Tue Oct 24 13:16:48 2006
@@ -35,6 +35,25 @@
private static final String CLASS_NAME = "org.example.components.Foo";
@Test
+ public void root_class_vs_sub_class()
+ {
+ Resource r = newResource();
+ Log log = newLog();
+
+ replay();
+
+ MutableComponentModel model = new
MutableComponentModelImpl(CLASS_NAME, log, r, null);
+
+ assertTrue(model.isRootClass());
+
+ MutableComponentModel subModel = new
MutableComponentModelImpl(CLASS_NAME, log, r, model);
+
+ assertFalse(subModel.isRootClass());
+
+ verify();
+ }
+
+ @Test
public void add_new_parameter()
{
Resource r = newResource();
@@ -255,13 +274,13 @@
"Fred",
COMPONENT_CLASS_NAME);
- assertTrue(fred.getMixinNames().isEmpty());
+ assertTrue(fred.getMixinClassNames().isEmpty());
verify();
}
@Test
- public void mixin_names_added_as_simple_name()
+ public void mixin_class_names_remembered_in_order_added()
{
Resource r = newResource();
Log log = newLog();
@@ -278,32 +297,7 @@
fred.addMixin("zip.zop.Zoom");
fred.addMixin("foo.bar.Baz");
- assertEquals(fred.getMixinNames(), Arrays.asList("Baz", "Zoom"));
-
- verify();
- }
-
- @Test
- public void mixin_class_names_available_via_simple_name()
- {
- Resource r = newResource();
- Log log = newLog();
-
- replay();
-
- MutableComponentModel model = new
MutableComponentModelImpl(CLASS_NAME, log, r, null);
-
- MutableEmbeddedComponentModel fred = model.addEmbeddedComponent(
- "fred",
- "Fred",
- COMPONENT_CLASS_NAME);
-
- fred.addMixin("zip.zop.Zoom");
- fred.addMixin("foo.bar.Baz");
-
- assertEquals(fred.getMixinClassName("Zoom"), "zip.zop.Zoom");
- assertEquals(fred.getMixinClassName("Baz"), "foo.bar.Baz");
- assertNull(fred.getMixinClassName("Gloop"));
+ assertEquals(fred.getMixinClassNames(), Arrays.asList("zip.zop.Zoom",
"foo.bar.Baz"));
verify();
}
@@ -327,17 +321,19 @@
try
{
- fred.addMixin("flim.flam.Zoom");
+ fred.addMixin("zip.zop.Zoom");
unreachable();
}
catch (IllegalArgumentException ex)
{
assertEquals(
ex.getMessage(),
- "Mixin 'Zoom' for component fred has already been
defined.");
+ "Mixin zip.zop.Zoom (for component fred) has already been
defined.");
}
- assertEquals(fred.getMixinNames(), Arrays.asList("Zoom"));
+ // Make sure it wasn't actually added.
+
+ assertEquals(fred.getMixinClassNames(), Arrays.asList("zip.zop.Zoom"));
verify();
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/ComponentLifecycleMethodWorkerTest.java
Tue Oct 24 13:16:48 2006
@@ -66,10 +66,10 @@
train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
- train_extendMethod(
+ train_addMethod(
tf,
TransformConstants.SETUP_RENDER_SIGNATURE,
- "{if ($2.isAborted()) return; aMethod(); }");
+ "{ super.setupRender($$); if ($2.isAborted()) return;
aMethod(); }");
replay();
@@ -82,6 +82,42 @@
}
@Test
+ public void method_in_base_class()
+ {
+ ClassTransformation tf = newClassTransformation();
+ MutableComponentModel model = newMutableComponentModel();
+
+ train_isRootClass(model, true);
+
+ List<MethodSignature> sigs = newList();
+
+ sigs.add(new MethodSignature("aMethod"));
+
+ train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
+
+ train_addMethod(
+ tf,
+ TransformConstants.SETUP_RENDER_SIGNATURE,
+ "{ aMethod(); }");
+
+ replay();
+
+ ComponentClassTransformWorker worker = new
ComponentLifecycleMethodWorker(
+ TransformConstants.SETUP_RENDER_SIGNATURE, SetupRender.class);
+
+ worker.transform(tf, model);
+
+ verify();
+
+ }
+
+ protected final void train_isRootClass(MutableComponentModel model,
boolean isRootClass)
+ {
+ model.isRootClass();
+ setReturnValue(isRootClass);
+ }
+
+ @Test
public void method_with_markup_writer_parameter()
{
ClassTransformation tf = newClassTransformation();
@@ -94,10 +130,10 @@
train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
- train_extendMethod(
+ train_addMethod(
tf,
TransformConstants.SETUP_RENDER_SIGNATURE,
- "{ if ($2.isAborted()) return; aMethod($1); }");
+ "{ super.setupRender($$); if ($2.isAborted()) return;
aMethod($1); }");
replay();
@@ -124,10 +160,12 @@
train_getClassName(tf, "biff.Baz");
- train_extendMethod(
+ train_addMethod(
tf,
TransformConstants.SETUP_RENDER_SIGNATURE,
- "{ if ($2.isAborted()) return; ",
+ "{",
+ "super.setupRender($$);",
+ "if ($2.isAborted()) return; ",
"if ($2.storeResult(($w) aMethod(), \"biff.Baz.aMethod()\"))
return;",
"}");
@@ -156,10 +194,11 @@
train_findMethodsWithAnnotation(tf, SetupRender.class, sigs);
train_getClassName(tf, "foo.Bar");
- train_extendMethod(
+ train_addMethod(
tf,
TransformConstants.SETUP_RENDER_SIGNATURE,
- "{ if ($2.isAborted()) return;",
+ "{ super.setupRender($$);",
+ "if ($2.isAborted()) return;",
"if ($2.storeResult(($w) aMethod(), \"foo.Bar.aMethod()\"))
return;",
"bMethod($1); }");
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/services/PageLoaderImplTest.java
Tue Oct 24 13:16:48 2006
@@ -14,7 +14,6 @@
package org.apache.tapestry.internal.services;
-
import java.util.Arrays;
import java.util.Locale;
@@ -127,6 +126,8 @@
train_getComponentType(emodel, "Barney");
+ train_getMixinClassNames(emodel);
+
log.error(ServicesMessages.compTypeConflict("foo", "Fred", "Barney"));
train_getComponentClassName(emodel, "foo.components.Barney");
@@ -161,5 +162,11 @@
loader.loadPage(PAGE_CLASS_NAME, LOCALE);
verify();
+ }
+
+ protected final void train_getMixinClassNames(EmbeddedComponentModel
model, String... names)
+ {
+ model.getMixinClassNames();
+ setReturnValue(Arrays.asList(names));
}
}
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/java/org/apache/tapestry/internal/structure/ComponentPageElementImplTest.java
Tue Oct 24 13:16:48 2006
@@ -368,8 +368,6 @@
private Instantiator newInstantiator(ComponentLifecycle component,
ComponentModel model)
{
- getMocksControl().checkOrder(false);
-
Instantiator ins = newMock(Instantiator.class);
ins.getModel();
Modified:
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InstanceMixin.html
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InstanceMixin.html?view=diff&rev=467463&r1=467462&r2=467463
==============================================================================
---
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InstanceMixin.html
(original)
+++
tapestry/tapestry5/tapestry-core/trunk/src/test/resources/org/apache/tapestry/integration/app1/pages/InstanceMixin.html
Tue Oct 24 13:16:48 2006
@@ -1,10 +1,18 @@
<t:comp type="Border"
xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
- <p> An important date: [<t:comp type="Output"
+ <p> Date #1: [<t:comp type="Output"
mixins="Emphasis"
- value="prop:date"
+ value="prop:date1"
test="prop:showEmphasis"
format="prop:format"/>]
+ </p>
+
+ <p>
+ Date #2: [<t:comp id="output2"/>] (via @Mixins)
+ </p>
+
+ <p>
+ Date #3: [<t:comp id="output3"/>] (via @MixinClasses)
</p>
<p>