KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > forms > formmodel > MultiValueField


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.forms.formmodel;
17
18 import java.lang.reflect.Array JavaDoc;
19 import java.util.Locale JavaDoc;
20
21 import org.apache.cocoon.forms.FormsConstants;
22 import org.apache.cocoon.forms.FormContext;
23 import org.apache.cocoon.forms.datatype.Datatype;
24 import org.apache.cocoon.forms.datatype.SelectionList;
25 import org.apache.cocoon.forms.datatype.convertor.ConversionResult;
26 import org.apache.cocoon.forms.datatype.convertor.Convertor;
27 import org.apache.cocoon.forms.event.ValueChangedEvent;
28 import org.apache.cocoon.forms.event.WidgetEvent;
29 import org.apache.cocoon.forms.util.I18nMessage;
30 import org.apache.cocoon.forms.validation.ValidationError;
31 import org.apache.cocoon.forms.validation.ValidationErrorAware;
32 import org.apache.cocoon.xml.XMLUtils;
33 import org.xml.sax.ContentHandler JavaDoc;
34 import org.xml.sax.SAXException JavaDoc;
35
36 /**
37  * A MultiValueField is mostly the same as a normal {@link Field}, but can
38  * hold multiple values. A MultiValueField should have a Datatype which
39  * has a SelectionList, because the user will always select the values
40  * from a list. A MultiValueField has no concept of "required", you should
41  * instead use the ValueCountValidationRule to check how many items the user
42  * has selected.
43  *
44  * <p>A MultiValueField also has a {@link Datatype} associated with it. In
45  * case of MultiValueFields, this Datatype will always be an array
46  * type, thus {@link Datatype#isArrayType()} will always return true, and
47  * this in return has an influence on the kind of validation rules that
48  * can be used with the Datatype (see {@link Datatype} description for more
49  * information).</p>
50  *
51  * @version $Id: MultiValueField.java 328365 2005-10-25 13:57:30Z bruno $
52  */

53 public class MultiValueField extends AbstractWidget
54                              implements ValidationErrorAware, SelectableWidget, DataWidget {
55
56     private static final String JavaDoc MULTIVALUEFIELD_EL = "multivaluefield";
57     private static final String JavaDoc VALUES_EL = "values";
58     private static final String JavaDoc VALUE_EL = "value";
59     private static final String JavaDoc VALIDATION_MSG_EL = "validation-message";
60
61     private final MultiValueFieldDefinition definition;
62
63     private SelectionList selectionList;
64     private String JavaDoc[] enteredValues;
65     private String JavaDoc invalidEnteredValue;
66     private Object JavaDoc[] values;
67     private ValidationError validationError;
68
69     public MultiValueField(MultiValueFieldDefinition definition) {
70         super(definition);
71         this.definition = definition;
72     }
73
74     public void initialize() {
75         this.selectionList = this.definition.getSelectionList();
76         super.initialize();
77     }
78
79     public WidgetDefinition getDefinition() {
80         return definition;
81     }
82
83     public void readFromRequest(FormContext formContext) {
84         if (!getCombinedState().isAcceptingInputs())
85             return;
86
87         enteredValues = formContext.getRequest().getParameterValues(getRequestParameterName());
88         invalidEnteredValue = null;
89         validationError = null;
90         values = null;
91
92         boolean conversionFailed = false;
93         if (enteredValues != null) {
94             Object JavaDoc[] tempValues = (Object JavaDoc[])Array.newInstance(getDatatype().getTypeClass(), enteredValues.length);
95             for (int i = 0; i < enteredValues.length; i++) {
96                 String JavaDoc param = enteredValues[i];
97                 ConversionResult conversionResult = definition.getDatatype().convertFromString(param, formContext.getLocale());
98                 if (conversionResult.isSuccessful()) {
99                     tempValues[i] = conversionResult.getResult();
100                 } else {
101                     conversionFailed = true;
102                     invalidEnteredValue = param;
103                     break;
104                 }
105             }
106
107             if (!conversionFailed)
108                 values = tempValues;
109             else
110                 values = null;
111         } else {
112             values = new Object JavaDoc[0];
113         }
114     }
115
116     public boolean validate() {
117         if (!getCombinedState().isValidatingValues()) {
118             this.wasValid = true;
119             return true;
120         }
121
122         if (values != null) {
123             validationError = definition.getDatatype().validate(values, new ExpressionContextImpl(this));
124         } else if (invalidEnteredValue != null) {
125             validationError = new ValidationError(new I18nMessage("multivaluefield.conversionfailed", new String JavaDoc[] {invalidEnteredValue}, FormsConstants.I18N_CATALOGUE));
126         }
127
128         this.wasValid = validationError == null ? super.validate() : false;
129         return this.wasValid;
130     }
131
132     /**
133      * @return "multivaluefield"
134      */

135     public String JavaDoc getXMLElementName() {
136         return MULTIVALUEFIELD_EL;
137     }
138
139     public void generateItemSaxFragment(ContentHandler JavaDoc contentHandler, Locale JavaDoc locale) throws SAXException JavaDoc {
140         contentHandler.startElement(FormsConstants.INSTANCE_NS, VALUES_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUES_EL, XMLUtils.EMPTY_ATTRIBUTES);
141         Convertor convertor = definition.getDatatype().getConvertor();
142         if (values != null) {
143             for (int i = 0; i < values.length; i++) {
144                 contentHandler.startElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL, XMLUtils.EMPTY_ATTRIBUTES);
145                 String JavaDoc value = convertor.convertToString(values[i], locale, null);
146                 contentHandler.characters(value.toCharArray(), 0, value.length());
147                 contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL);
148             }
149         } else if (enteredValues != null) {
150             for (int i = 0; i < enteredValues.length; i++) {
151                 contentHandler.startElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL, XMLUtils.EMPTY_ATTRIBUTES);
152                 String JavaDoc value = enteredValues[i];
153                 contentHandler.characters(value.toCharArray(), 0, value.length());
154                 contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL);
155             }
156         }
157         contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUES_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUES_EL);
158
159         // the selection list
160
if (this.selectionList != null)
161             this.selectionList.generateSaxFragment(contentHandler, locale);
162
163         // validation message element
164
if (validationError != null) {
165             contentHandler.startElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL, XMLUtils.EMPTY_ATTRIBUTES);
166             validationError.generateSaxFragment(contentHandler);
167             contentHandler.endElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL);
168         }
169     }
170
171
172     public Object JavaDoc getValue() {
173         return values;
174     }
175
176     public void setValue(Object JavaDoc value) {
177         if (value == null) {
178             setValues(new Object JavaDoc[0]);
179         } else if (value.getClass().isArray()) {
180             setValues((Object JavaDoc[])value);
181         } else {
182             throw new RuntimeException JavaDoc("Cannot set value of field \"" + getRequestParameterName() + "\" with an object of type " + value.getClass().getName());
183         }
184         getForm().addWidgetUpdate(this);
185     }
186
187     public void setValues(Object JavaDoc[] values) {
188         // check that all the objects in the array correspond to the datatype
189
for (int i = 0; i < values.length; i++) {
190             if (!definition.getDatatype().getTypeClass().isAssignableFrom(values[i].getClass()))
191                 throw new RuntimeException JavaDoc("Cannot set value of field \"" + getRequestParameterName() + "\" with an object of type " + values[i].getClass().getName());
192         }
193         this.values = values;
194         getForm().addWidgetUpdate(this);
195     }
196
197     /**
198      * Set this field's selection list.
199      * @param selectionList The new selection list.
200      */

201     public void setSelectionList(SelectionList selectionList) {
202         if (selectionList == null) {
203             throw new IllegalArgumentException JavaDoc("An MultiValueField's selection list cannot be null.");
204         }
205
206         if (selectionList.getDatatype() != null &&
207             selectionList.getDatatype() != definition.getDatatype()) {
208
209             throw new RuntimeException JavaDoc("Tried to assign a SelectionList that is not associated with this widget's datatype.");
210         }
211         this.selectionList = selectionList;
212         getForm().addWidgetUpdate(this);
213     }
214
215     /**
216      * Read this field's selection list from an external source.
217      * All Cocoon-supported protocols can be used.
218      * The format of the XML produced by the source should be the
219      * same as in case of inline specification of the selection list,
220      * thus the root element should be a <code>fd:selection-list</code>
221      * element.
222      * @param uri The URI of the source.
223      */

224     public void setSelectionList(String JavaDoc uri) {
225         setSelectionList(this.definition.buildSelectionList(uri));
226     }
227
228     /**
229      * Set this field's selection list using values from an in-memory
230      * object. The <code>object</code> parameter should point to a collection
231      * (Java collection or array, or Javascript array) of objects. Each object
232      * belonging to the collection should have a <em>value</em> property and a
233      * <em>label</em> property, whose values are used to specify the <code>value</code>
234      * attribute and the contents of the <code>fd:label</code> child element
235      * of every <code>fd:item</code> in the list.
236      * <p>Access to the values of the above mentioned properties is done
237      * via <a HREF="http://jakarta.apache.org/commons/jxpath/users-guide.html">XPath</a> expressions.
238      * @param model The collection used as a model for the selection list.
239      * @param valuePath An XPath expression referring to the attribute used
240      * to populate the values of the list's items.
241      * @param labelPath An XPath expression referring to the attribute used
242      * to populate the labels of the list's items.
243      */

244     public void setSelectionList(Object JavaDoc model, String JavaDoc valuePath, String JavaDoc labelPath) {
245         setSelectionList(this.definition.buildSelectionListFromModel(model, valuePath, labelPath));
246     }
247
248     public void broadcastEvent(WidgetEvent event) {
249         if (event instanceof ValueChangedEvent) {
250             this.definition.fireValueChangedEvent((ValueChangedEvent)event);
251         } else {
252             // Other kinds of events
253
super.broadcastEvent(event);
254         }
255     }
256
257     public ValidationError getValidationError() {
258         return this.validationError;
259     }
260
261     public void setValidationError(ValidationError error) {
262         this.validationError = error;
263         getForm().addWidgetUpdate(this);
264     }
265
266     public Datatype getDatatype() {
267         return definition.getDatatype();
268     }
269 }
270
Popular Tags