KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 1999-2004 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.woody.formmodel;
17
18 import org.apache.cocoon.woody.datatype.SelectionList;
19 import org.apache.cocoon.woody.validation.ValidationError;
20 import org.apache.cocoon.woody.validation.ValidationErrorAware;
21 import org.apache.cocoon.woody.event.WidgetEvent;
22 import org.apache.cocoon.woody.event.ValueChangedEvent;
23 import org.apache.cocoon.woody.Constants;
24 import org.apache.cocoon.woody.FormContext;
25 import org.apache.cocoon.woody.util.I18nMessage;
26 import org.apache.cocoon.xml.AttributesImpl;
27 import org.xml.sax.ContentHandler JavaDoc;
28 import org.xml.sax.SAXException JavaDoc;
29
30 import java.util.Locale JavaDoc;
31
32 /**
33  * A MultiValueField is mostly the same as a normal {@link Field}, but can
34  * hold multiple values. A MultiValueField should have a Datatype which
35  * has a SelectionList, because the user will always select the values
36  * from a list. A MultiValueField has no concept of "required", you should
37  * instead use the ValueCountValidationRule to check how many items the user
38  * has selected.
39  *
40  * <p>A MultiValueField also has a {@link org.apache.cocoon.woody.datatype.Datatype Datatype}
41  * associated with it. In case of MultiValueFields, this Datatype will always be an array
42  * type, thus {@link org.apache.cocoon.woody.datatype.Datatype#isArrayType()} will
43  * always return true, and this in return has an influence on the kind of validation rules that
44  * can be used with the Datatype (see {@link org.apache.cocoon.woody.datatype.Datatype Datatype}
45  * description for more information).
46  *
47  * @version $Id: MultiValueField.java 30932 2004-07-29 17:35:38Z vgritsenko $
48  */

49 public class MultiValueField extends AbstractWidget implements ValidationErrorAware, SelectableWidget {
50     private SelectionList selectionList;
51     private MultiValueFieldDefinition fieldDefinition;
52     private String JavaDoc[] enteredValues;
53     private Object JavaDoc[] values;
54     private ValidationError validationError;
55
56     public MultiValueField(MultiValueFieldDefinition definition) {
57         super.setDefinition(definition);
58         this.fieldDefinition = definition;
59         setLocation(definition.getLocation());
60     }
61
62     public String JavaDoc getId() {
63         return definition.getId();
64     }
65
66     public void readFromRequest(FormContext formContext) {
67         enteredValues = formContext.getRequest().getParameterValues(getFullyQualifiedId());
68         validationError = null;
69         values = null;
70
71         boolean conversionFailed = false;
72         if (enteredValues != null) {
73             // Normally, for MultiValueFields, the user selects the values from
74
// a SelectionList, and the values in a SelectionList are garanteed to
75
// be valid, so the conversion from String to native datatype should
76
// never fail. But it could fail if users start messing around with
77
// request parameters.
78
Object JavaDoc[] tempValues = new Object JavaDoc[enteredValues.length];
79             for (int i = 0; i < enteredValues.length; i++) {
80                 String JavaDoc param = enteredValues[i];
81                 tempValues[i] = fieldDefinition.getDatatype().convertFromString(param, formContext.getLocale());
82                 if (tempValues[i] == null) {
83                     conversionFailed = true;
84                     break;
85                 }
86             }
87
88             if (!conversionFailed)
89                 values = tempValues;
90             else
91                 values = null;
92         } else {
93             values = new Object JavaDoc[0];
94         }
95     }
96
97     public boolean validate(FormContext formContext) {
98         if (values != null)
99             validationError = fieldDefinition.getDatatype().validate(values, new ExpressionContextImpl(this));
100         else
101             validationError = new ValidationError(new I18nMessage("multivaluefield.conversionfailed", Constants.I18N_CATALOGUE));
102
103
104         return validationError == null ? super.validate(formContext) : false;
105     }
106
107     private static final String JavaDoc MULTIVALUEFIELD_EL = "multivaluefield";
108     private static final String JavaDoc VALUES_EL = "values";
109     private static final String JavaDoc VALUE_EL = "value";
110     private static final String JavaDoc VALIDATION_MSG_EL = "validation-message";
111
112     public void generateSaxFragment(ContentHandler JavaDoc contentHandler, Locale JavaDoc locale) throws SAXException JavaDoc {
113         AttributesImpl attrs = new AttributesImpl();
114         attrs.addCDATAAttribute("id", getFullyQualifiedId());
115         contentHandler.startElement(Constants.WI_NS, MULTIVALUEFIELD_EL, Constants.WI_PREFIX_COLON + MULTIVALUEFIELD_EL, attrs);
116
117         contentHandler.startElement(Constants.WI_NS, VALUES_EL, Constants.WI_PREFIX_COLON + VALUES_EL, Constants.EMPTY_ATTRS);
118         if (values != null) {
119             for (int i = 0; i < values.length; i++) {
120                 contentHandler.startElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL, Constants.EMPTY_ATTRS);
121                 String JavaDoc value = fieldDefinition.getDatatype().getPlainConvertor().convertToString(values[i], locale, null);
122                 contentHandler.characters(value.toCharArray(), 0, value.length());
123                 contentHandler.endElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL);
124             }
125         } else if (enteredValues != null) {
126             for (int i = 0; i < enteredValues.length; i++) {
127                 contentHandler.startElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL, Constants.EMPTY_ATTRS);
128                 String JavaDoc value = fieldDefinition.getDatatype().getPlainConvertor().convertToString(enteredValues[i], locale, null);
129                 contentHandler.characters(value.toCharArray(), 0, value.length());
130                 contentHandler.endElement(Constants.WI_NS, VALUE_EL, Constants.WI_PREFIX_COLON + VALUE_EL);
131             }
132         }
133         contentHandler.endElement(Constants.WI_NS, VALUES_EL, Constants.WI_PREFIX_COLON + VALUES_EL);
134
135         // generate label, help, hint, etc.
136
definition.generateDisplayData(contentHandler);
137
138         // the selection list (a MultiValueField has per definition always a SelectionList)
139
if (this.selectionList != null) {
140             this.selectionList.generateSaxFragment(contentHandler, locale);
141         } else {
142             fieldDefinition.getSelectionList().generateSaxFragment(contentHandler, locale);
143         }
144
145         // validation message element
146
if (validationError != null) {
147             contentHandler.startElement(Constants.WI_NS, VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON + VALIDATION_MSG_EL, Constants.EMPTY_ATTRS);
148             validationError.generateSaxFragment(contentHandler);
149             contentHandler.endElement(Constants.WI_NS, VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON + VALIDATION_MSG_EL);
150         }
151
152         contentHandler.endElement(Constants.WI_NS, MULTIVALUEFIELD_EL, Constants.WI_PREFIX_COLON + MULTIVALUEFIELD_EL);
153     }
154
155     public void generateLabel(ContentHandler JavaDoc contentHandler) throws SAXException JavaDoc {
156         definition.generateLabel(contentHandler);
157     }
158
159     public Object JavaDoc getValue() {
160         return values;
161     }
162
163     public void setValue(Object JavaDoc value) {
164         if (value == null) {
165             setValues(new Object JavaDoc[0]);
166         } else if (value.getClass().isArray()) {
167             setValues((Object JavaDoc[])value);
168         } else {
169             throw new RuntimeException JavaDoc("Cannot set value of field \"" + getFullyQualifiedId() + "\" with an object of type " + value.getClass().getName());
170         }
171     }
172
173     public void setValues(Object JavaDoc[] values) {
174         // check that all the objects in the array correspond to the datatype
175
for (int i = 0; i < values.length; i++) {
176             if (!fieldDefinition.getDatatype().getTypeClass().isAssignableFrom(values[i].getClass()))
177                 throw new RuntimeException JavaDoc("Cannot set value of field \"" + getFullyQualifiedId() + "\" with an object of type " + values[i].getClass().getName());
178         }
179         this.values = values;
180     }
181
182     /**
183      * Set this field's selection list.
184      * @param selectionList The new selection list.
185      */

186     public void setSelectionList(SelectionList selectionList) {
187         if (selectionList != null &&
188             selectionList.getDatatype() != null &&
189             selectionList.getDatatype() != fieldDefinition.getDatatype()) {
190
191             throw new RuntimeException JavaDoc("Tried to assign a SelectionList that is not associated with this widget's datatype.");
192         }
193         this.selectionList = selectionList;
194     }
195
196     /**
197      * Read this field's selection list from an external source.
198      * All Cocoon-supported protocols can be used.
199      * The format of the XML produced by the source should be the
200      * same as in case of inline specification of the selection list,
201      * thus the root element should be a <code>wd:selection-list</code>
202      * element.
203      * @param uri The URI of the source.
204      */

205     public void setSelectionList(String JavaDoc uri) {
206         setSelectionList(this.fieldDefinition.buildSelectionList(uri));
207     }
208
209     /**
210      * Set this field's selection list using values from an in-memory
211      * object. The <code>object</code> parameter should point to a collection
212      * (Java collection or array, or Javascript array) of objects. Each object
213      * belonging to the collection should have a <em>value</em> property and a
214      * <em>label</em> property, whose values are used to specify the <code>value</code>
215      * attribute and the contents of the <code>wd:label</code> child element
216      * of every <code>wd:item</code> in the list.
217      * <p>Access to the values of the above mentioned properties is done
218      * via <a HREF="http://jakarta.apache.org/commons/jxpath/users-guide.html">XPath</a> expressions.
219      * @param model The collection used as a model for the selection list.
220      * @param valuePath An XPath expression referring to the attribute used
221      * to populate the values of the list's items.
222      * @param labelPath An XPath expression referring to the attribute used
223      * to populate the labels of the list's items.
224      */

225     public void setSelectionList(Object JavaDoc model, String JavaDoc valuePath, String JavaDoc labelPath) {
226         setSelectionList(this.fieldDefinition.buildSelectionListFromModel(model, valuePath, labelPath));
227     }
228
229     public void broadcastEvent(WidgetEvent event) {
230         this.fieldDefinition.fireValueChangedEvent((ValueChangedEvent)event);
231     }
232
233     public ValidationError getValidationError() {
234         return this.validationError;
235     }
236
237     public void setValidationError(ValidationError error) {
238         this.validationError = error;
239     }
240 }
241
Popular Tags