001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.forms.datatype;
018:
019: import java.lang.reflect.Field;
020: import java.lang.reflect.Modifier;
021: import java.util.Iterator;
022: import java.util.Locale;
023:
024: import org.apache.cocoon.forms.FormsConstants;
025: import org.apache.cocoon.xml.AttributesImpl;
026: import org.apache.cocoon.xml.XMLUtils;
027: import org.apache.commons.lang.enums.Enum;
028: import org.apache.commons.lang.enums.EnumUtils;
029: import org.xml.sax.ContentHandler;
030: import org.xml.sax.SAXException;
031:
032: /**
033: * This type of selection list outputs a list of items
034: * corresponding to the possible instances of an {@link org.apache.cocoon.forms.datatype.typeimpl.EnumType}.
035: * <p>Example usage:</p>
036: * <pre>
037: * <fd:selection-list type="enum" class="com.example.Sex"/>
038: * </pre>
039: * <p>Produces the following output:</p>
040: * <pre>
041: * <fi:selection-list>
042: * <fi:item value=""/>
043: * <fi:item value="com.example.Sex.MALE">
044: * <fi:label>
045: * <i18n:text>com.example.Sex.MALE</i18n:text>
046: * </fi:label>
047: * </fi:item>
048: * <fi:item value="com.example.Sex.FEMALE">
049: * <fi:label>
050: * <i18n:text>com.example.Sex.FEMALE</i18n:text>
051: * </fi:label>
052: * </fi:item>
053: * </fi:selection-list>
054: * </pre>
055: *
056: * <p>If you don't want an initial null value, add a
057: * <code>nullable="false"</code> attribute to the
058: * <code>fd:selection-list</code> element.</p>
059: *
060: * @version $Id: EnumSelectionList.java 449149 2006-09-23 03:58:05Z crossley $
061: */
062: public class EnumSelectionList implements SelectionList {
063: public static final String TEXT_EL = "text";
064:
065: private Datatype datatype;
066: private Class clazz;
067: private boolean nullable;
068: private String nullText;
069:
070: /**
071: * @param className
072: * @param datatype
073: */
074: public EnumSelectionList(String className, Datatype datatype,
075: boolean nullable) throws ClassNotFoundException {
076: this .datatype = datatype;
077: this .nullable = nullable;
078: this .clazz = Class.forName(className);
079: }
080:
081: public EnumSelectionList(String className, Datatype datatype,
082: boolean nullable, String nullText)
083: throws ClassNotFoundException {
084: this (className, datatype, nullable);
085: this .nullText = nullText;
086: }
087:
088: /* (non-Javadoc)
089: * @see org.apache.cocoon.forms.datatype.SelectionList#getDatatype()
090: */
091: public Datatype getDatatype() {
092: return datatype;
093: }
094:
095: /* (non-Javadoc)
096: * @see org.apache.cocoon.forms.datatype.SelectionList#generateSaxFragment(org.xml.sax.ContentHandler, java.util.Locale)
097: */
098: public void generateSaxFragment(ContentHandler contentHandler,
099: Locale locale) throws SAXException {
100: try {
101: contentHandler.startElement(FormsConstants.INSTANCE_NS,
102: SELECTION_LIST_EL,
103: FormsConstants.INSTANCE_PREFIX_COLON
104: + SELECTION_LIST_EL,
105: XMLUtils.EMPTY_ATTRIBUTES);
106: // Create void element
107: if (nullable) {
108: AttributesImpl voidAttrs = new AttributesImpl();
109: voidAttrs.addCDATAAttribute("value", "");
110: contentHandler.startElement(FormsConstants.INSTANCE_NS,
111: ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON
112: + ITEM_EL, voidAttrs);
113: if (this .nullText != null) {
114: contentHandler.startElement(
115: FormsConstants.INSTANCE_NS, LABEL_EL,
116: FormsConstants.INSTANCE_PREFIX_COLON
117: + LABEL_EL,
118: XMLUtils.EMPTY_ATTRIBUTES);
119: contentHandler.startElement(FormsConstants.I18N_NS,
120: TEXT_EL, FormsConstants.I18N_PREFIX_COLON
121: + TEXT_EL,
122: XMLUtils.EMPTY_ATTRIBUTES);
123: contentHandler.characters(nullText.toCharArray(),
124: 0, nullText.length());
125: contentHandler.endElement(FormsConstants.I18N_NS,
126: TEXT_EL, FormsConstants.I18N_PREFIX_COLON
127: + TEXT_EL);
128: contentHandler.endElement(
129: FormsConstants.INSTANCE_NS, LABEL_EL,
130: FormsConstants.INSTANCE_PREFIX_COLON
131: + LABEL_EL);
132: }
133: contentHandler.endElement(FormsConstants.INSTANCE_NS,
134: ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON
135: + ITEM_EL);
136: }
137: // Test if we have an apache enum class
138: boolean apacheEnumDone = false;
139: if (Enum.class.isAssignableFrom(clazz)) {
140: Iterator iter = EnumUtils.iterator(clazz);
141: if (iter != null) {
142: apacheEnumDone = true;
143: while (iter.hasNext()) {
144: Enum element = (Enum) iter.next();
145: String stringValue = clazz.getName() + "."
146: + element.getName();
147: generateItem(contentHandler, stringValue);
148: }
149: }
150: }
151: // If it's not an apache enum or we didn't manage to read the enum list, then proceed with common method.
152: if (!apacheEnumDone) {
153: Field fields[] = clazz.getDeclaredFields();
154: for (int i = 0; i < fields.length; ++i) {
155: int mods = fields[i].getModifiers();
156: if (Modifier.isPublic(mods)
157: && Modifier.isStatic(mods)
158: && Modifier.isFinal(mods)
159: && fields[i].get(null).getClass().equals(
160: clazz)) {
161: String stringValue = clazz.getName() + "."
162: + fields[i].getName();
163: generateItem(contentHandler, stringValue);
164: }
165: }
166: }
167: // End the selection-list
168: contentHandler.endElement(FormsConstants.INSTANCE_NS,
169: SELECTION_LIST_EL,
170: FormsConstants.INSTANCE_PREFIX_COLON
171: + SELECTION_LIST_EL);
172: } catch (Exception e) {
173: throw new SAXException(
174: "Got exception trying to get enum's values", e);
175: }
176: }
177:
178: /**
179: * Generates a single selection list item.
180: * @param contentHandler The content handler we are streaming sax events to.
181: * @param stringValue The string name of the item, composed by FQN and enum item.
182: * @throws SAXException
183: */
184: private void generateItem(ContentHandler contentHandler,
185: String stringValue) throws SAXException {
186: // Output this item
187: AttributesImpl itemAttrs = new AttributesImpl();
188: itemAttrs.addCDATAAttribute("value", stringValue);
189: contentHandler.startElement(FormsConstants.INSTANCE_NS,
190: ITEM_EL,
191: FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL,
192: itemAttrs);
193: contentHandler.startElement(FormsConstants.INSTANCE_NS,
194: LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON
195: + LABEL_EL, XMLUtils.EMPTY_ATTRIBUTES);
196: // TODO: make i18n element optional
197: contentHandler.startElement(FormsConstants.I18N_NS, TEXT_EL,
198: FormsConstants.I18N_PREFIX_COLON + TEXT_EL,
199: XMLUtils.EMPTY_ATTRIBUTES);
200: contentHandler.characters(stringValue.toCharArray(), 0,
201: stringValue.length());
202: contentHandler.endElement(FormsConstants.I18N_NS, TEXT_EL,
203: FormsConstants.I18N_PREFIX_COLON + TEXT_EL);
204: contentHandler.endElement(FormsConstants.INSTANCE_NS, LABEL_EL,
205: FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL);
206: contentHandler.endElement(FormsConstants.INSTANCE_NS, ITEM_EL,
207: FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL);
208: }
209: }
|