001 package org.trails.component;
002
003 import org.apache.tapestry.IRequestCycle;
004 import org.apache.tapestry.annotations.Parameter;
005 import org.apache.tapestry.form.IPropertySelectionModel;
006 import org.trails.descriptor.annotation.InitialValueDescriptorExtension;
007 import org.trails.descriptor.annotation.PossibleValuesDescriptorExtension;
008
009 import java.util.ArrayList;
010 import java.util.Collection;
011 import java.util.List;
012
013 /** imports for javadocs **/
014 import org.trails.descriptor.annotation.InitialValue;
015 import org.trails.descriptor.annotation.PossibleValues;
016 import ognl.OgnlException;
017
018 /**
019 * Component that renders a select element based on the annotations
020 * {@link InitialValue} and {@link PossibleValues}.
021 * <p/>
022 * If the property has a {@link PossibleValues} annotation, the select will
023 * render its options evaluating the expression passed as the value of the
024 * annotation.<br>
025 * <p/>
026 * If the property has a {@link InitialValue} it will render all
027 * instances of that property type and resubmit the form every time the value
028 * changes, so the related select values can be filtered.<br>
029 *
030 * @author pruggia
031 */
032 public abstract class FilteredAssociationSelect extends AssociationSelect
033 {
034
035 @Parameter(required = true)
036 public abstract Object getPageModel();
037
038 /**
039 * Sets the initial value for the property based on the expression declared
040 * in the {@link InitialValue} annotation.
041 *
042 * @param cycle the request cycle, it's never null.
043 */
044 @Override
045 protected void prepareForRender(final IRequestCycle cycle)
046 {
047 InitialValueDescriptorExtension extension = (InitialValueDescriptorExtension) getPropertyDescriptor()
048 .getExtension(InitialValueDescriptorExtension.class.getName());
049 if (extension != null)
050 {
051 if (getValue() == null)
052 {
053 try
054 {
055 setValue(extension.evaluateExpresion(getPageModel()));
056 } catch (OgnlException e)
057 {
058 // do nothing, don't worry about it
059 }
060 }
061 }
062 super.prepareForRender(cycle);
063 }
064
065 /**
066 * Creates an {@link IPropertySelectionModel} based on properties annotated
067 * with {@link PossibleValues} and {@link InitialValue}.
068 *
069 * @return Returns the selection model, it never returns null.
070 */
071 @Override
072 @SuppressWarnings("unchecked")
073 public IPropertySelectionModel buildSelectionModel()
074 {
075 PossibleValuesDescriptorExtension extension = (PossibleValuesDescriptorExtension) getPropertyDescriptor()
076 .getExtension(PossibleValuesDescriptorExtension.class.getName());
077
078 /* instances passed directly from a collection to the component, no need to build a list. */
079 if (extension != null && getInstances() == null)
080 {
081 // If it's filtered by a "PossibleValues" annotation, we need to
082 // retrieve the list evaluating the ognl expression of the annotation.
083 Collection<Object> col = null;
084 List allObjects = null;
085 try
086 {
087 col = (Collection) extension.evaluateExpresion(getPageModel());
088 } catch (OgnlException e)
089 {
090 col = new ArrayList();
091 }
092 if (col instanceof List)
093 {
094 allObjects = (List) col;
095 } else
096 {
097 allObjects = new ArrayList();
098 allObjects.addAll(col);
099 }
100
101 if (!allObjects.isEmpty())
102 {
103
104 IdentifierSelectionModel selectionModel = new IdentifierSelectionModel(allObjects,
105 getClassDescriptor().getIdentifierDescriptor().getName(), isAllowNone());
106 selectionModel.setNoneLabel(getNoneLabel());
107 return selectionModel;
108 }
109 }
110
111 return super.buildSelectionModel();
112 }
113
114 /**
115 * If the property is annotated with {@link InitialValue}, this
116 * method generates javascript code to submit the form and update the options
117 * for the filtered property.
118 *
119 * @return a fragment of javascript. It never returns null.
120 */
121 public String getOnChangeJavascript()
122 {
123 InitialValueDescriptorExtension extension = (InitialValueDescriptorExtension) getPropertyDescriptor()
124 .getExtension(InitialValueDescriptorExtension.class.getName());
125 if (extension != null)
126 {
127 return "tapestry.form.refresh('form')";
128 /*
129 return "tapestry.form.registerForm('form');tapestry.form.refresh('form')";
130 */
131 } else
132 {
133 return "";
134 }
135 }
136 }