Index: C:/devel/rife-svn/trunk/src/unittests/com/uwyn/rife/engine/TestAnnotations2ElementInfo.java =================================================================== --- C:/devel/rife-svn/trunk/src/unittests/com/uwyn/rife/engine/TestAnnotations2ElementInfo.java (revision 3355) +++ C:/devel/rife-svn/trunk/src/unittests/com/uwyn/rife/engine/TestAnnotations2ElementInfo.java (working copy) @@ -220,9 +220,10 @@ assertTrue(elementinfo.containsChildTrigger("input1")); assertTrue(elementinfo.containsChildTrigger("input2")); - assertEquals(elementinfo.getExitNames().size(), 2); + assertEquals(elementinfo.getExitNames().size(), 3); assertTrue(elementinfo.containsExit("exit1")); assertTrue(elementinfo.containsExit("exit2")); + assertTrue(elementinfo.containsExit("exit3")); assertEquals(elementinfo.getSubmissionNames().size(), 3); assertTrue(elementinfo.containsSubmission("submission1")); Index: C:/devel/rife-svn/trunk/src/unittests/com/uwyn/rife/engine/testelements/annotations/Simple.java =================================================================== --- C:/devel/rife-svn/trunk/src/unittests/com/uwyn/rife/engine/testelements/annotations/Simple.java (revision 3355) +++ C:/devel/rife-svn/trunk/src/unittests/com/uwyn/rife/engine/testelements/annotations/Simple.java (working copy) @@ -97,6 +97,9 @@ private UploadedFile mFile2; private String mParam4; + @ExitField + public static final String EXIT_3 = "exit3"; + @InputProperty public void setInput1(int input1) { Index: C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/Annotations2ElementInfo.java =================================================================== --- C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/Annotations2ElementInfo.java (revision 3355) +++ C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/Annotations2ElementInfo.java (working copy) @@ -19,7 +19,9 @@ import com.uwyn.rife.tools.exceptions.BeanUtilsException; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import java.util.SortedSet; @@ -235,6 +237,34 @@ } } + // for fields, we need a bean instance to retrieve their values. + Object beanInstance = element_class.newInstance(); + for (Field field : element_class.getDeclaredFields()) + { + if (field.isAnnotationPresent(ExitField.class)) + { + requireFinalString(field, builder, declarationName); + builder.addExit((String)field.get(beanInstance)); + } + if (field.isAnnotationPresent(FlowlinkField.class)) + { + requireFinalString(field, builder, declarationName); + FlowlinkField flowlink = field.getAnnotation(FlowlinkField.class); + String destId = getElementId(builder, flowlink.destClass(), flowlink.destId()); + FlowLinkBuilder flowlinkbuilder = builder.enterFlowLink((String)field.get(beanInstance)) + .destId(destId) + .snapback(flowlink.snapback()) + .cancelInheritance(flowlink.inheritance().equals(Flowlink.Inheritance.CANCEL)) + .cancelEmbedding(flowlink.embedding().equals(Flowlink.Embedding.CANCEL)) + .redirect(flowlink.redirect()); + for (Datalink datalink : flowlink.datalinks()) + { + flowlinkbuilder.addDataLink(datalink.srcOutput(), datalink.srcOutbean(), datalink.snapback(), datalink.destInput(), datalink.destInbean()); + } + flowlinkbuilder.leaveFlowLink(); + } + } + // Create a set that is sorted according to the method priorities SortedSet method_set = new TreeSet(); for (Method method : element_class.getDeclaredMethods()) @@ -392,8 +422,28 @@ { throw new ElementAnnotationErrorException(declarationName, builder.getSiteBuilder().getDeclarationName(), "Unexpected error while introspecting the class.", e); } + catch (IllegalAccessException e) + { + throw new ElementAnnotationErrorException(declarationName, builder.getSiteBuilder().getDeclarationName(), "Unexpected error while introspecting the class.", e); + } + catch (InstantiationException e) + { + throw new ElementAnnotationErrorException(declarationName, builder.getSiteBuilder().getDeclarationName(), "Unexpected error while introspecting the class.", e); + } } + private void requireFinalString(Field field, ElementInfoBuilder builder, String declarationName) throws UnsupportedElementAnnotationErrorException + { + if (field.getType() != String.class) + { + throw new UnsupportedElementAnnotationErrorException(declarationName, builder.getSiteBuilder().getDeclarationName(), ExitField.class, "on non-String field ("+field.getName()+")", null); + } + if ((field.getModifiers() & Modifier.FINAL) == 0) + { + throw new UnsupportedElementAnnotationErrorException(declarationName, builder.getSiteBuilder().getDeclarationName(), ExitField.class, "on non-final field ("+field.getName()+")", null); + } + } + private String getElementId(ElementInfoBuilder builder, Class elementClass, String elementId) { if (elementClass != void.class) Index: C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/annotations/ExitField.java =================================================================== --- C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/annotations/ExitField.java (revision 0) +++ C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/annotations/ExitField.java (revision 0) @@ -0,0 +1,29 @@ +/* + * Copyright 2001-2006 Geert Bevin + * Distributed under the terms of either: + * - the common development and distribution license (CDDL), v1.0; or + * - the GNU Lesser General Public License, v2.1 or later + * $Id$ + */ +package com.uwyn.rife.engine.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Declares an exit. This annotation may only be used on fields of type + * "final String". + * + * @author Steven Grimm (koreth[remove] at midwinter dot com) + * @version $Revision$ + * @since 1.5 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +@Documented +public @interface ExitField +{ +} Property changes on: C:\devel\rife-svn\trunk\src\framework\com\uwyn\rife\engine\annotations\ExitField.java ___________________________________________________________________ Name: svn:keywords + Id Revision Name: svn:eol-style + native Index: C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/annotations/FlowlinkField.java =================================================================== --- C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/annotations/FlowlinkField.java (revision 0) +++ C:/devel/rife-svn/trunk/src/framework/com/uwyn/rife/engine/annotations/FlowlinkField.java (revision 0) @@ -0,0 +1,84 @@ +/* + * Copyright 2001-2006 Geert Bevin + * Distributed under the terms of either: + * - the common development and distribution license (CDDL), v1.0; or + * - the GNU Lesser General Public License, v2.1 or later + * $Id$ + */ +package com.uwyn.rife.engine.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Documented; + +/** + * Declares a flow link for the element. This annotation may only be used on + * final String fields. The value of the field is used as the source exit name. + * + * @author Geert Bevin (gbevin[remove] at uwyn dot com) + * @version $Revision$ + * @since 1.5 + * @see Flowlink + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD}) +@Documented +public @interface FlowlinkField +{ + /** + * The ID of the destination element for this flow link. + *

If destClass is provided, it will override the + * destId value. + * @see #destClass + * @since 1.5 + */ + String destId() default ""; + + /** + * The Java class of the destination element for this flow link. This + * class should at least have an {@link Elem} annotation. + *

If destClass is provided, it will override the + * destId value. + * @see #destId + * @since 1.5 + */ + Class destClass() default void.class; + + /** + * Indicates whether this flow link is a snapback. + * @since 1.5 + */ + boolean snapback() default false; + + /** + * Indicates whether this flow link will redirect to a dedicated URL + * instead of executing the destination element directly. + * @since 1.5 + */ + boolean redirect() default false; + + /** + * Indicates whether the behavioral inheritance (3D flow) should be + * preserved or cancelled when this flow link is followed. + * @since 1.5 + */ + Inheritance inheritance() default Inheritance.PRESERVE; + + /** + * Indicates whether element embedded should be preserved or cancelled + * when this flow link is followed. + * @since 1.5 + */ + Embedding embedding() default Embedding.PRESERVE; + + /** + * This flow link's data links. + * @since 1.5 + */ + Datalink[] datalinks() default {}; + + public enum Inheritance { PRESERVE, CANCEL } + public enum Embedding { PRESERVE, CANCEL } +} Property changes on: C:\devel\rife-svn\trunk\src\framework\com\uwyn\rife\engine\annotations\FlowlinkField.java ___________________________________________________________________ Name: svn:keywords + Id Revision Name: svn:eol-style + native