/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.cocoon.forms.datatype; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Iterator; import java.util.Locale; import org.apache.cocoon.forms.FormsConstants; import org.apache.cocoon.xml.AttributesImpl; import org.apache.cocoon.xml.XMLUtils; import org.apache.commons.lang.enums.Enum; import org.apache.commons.lang.enums.EnumUtils; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; /** * This type of selection list outputs a list of items * corresponding to the possible instances of an {@link org.apache.cocoon.forms.datatype.typeimpl.EnumType}. * <p>Example usage:</p> * <pre> * <fd:selection-list type="enum" class="com.example.Sex"/> * </pre> * <p>Produces the following output:</p> * <pre> * <fi:selection-list> * <fi:item value=""/> * <fi:item value="com.example.Sex.MALE"> * <fi:label> * <i18n:text>com.example.Sex.MALE</i18n:text> * </fi:label> * </fi:item> * <fi:item value="com.example.Sex.FEMALE"> * <fi:label> * <i18n:text>com.example.Sex.FEMALE</i18n:text> * </fi:label> * </fi:item> * </fi:selection-list> * </pre> * * <p>If you don't want an initial null value, add a * <code>nullable="false"</code> attribute to the * <code>fd:selection-list</code> element.</p> * * @version $Id$ */ public class EnumSelectionList implements SelectionList { public static final String TEXT_EL = "text"; private Datatype datatype; private Class clazz; private boolean nullable; private String nullText; /** * @param className * @param datatype */ public EnumSelectionList(String className, Datatype datatype, boolean nullable) throws ClassNotFoundException { this.datatype = datatype; this.nullable = nullable; this.clazz = Class.forName(className); } public EnumSelectionList(String className, Datatype datatype, boolean nullable, String nullText) throws ClassNotFoundException { this(className, datatype, nullable); this.nullText = nullText; } /* (non-Javadoc) * @see org.apache.cocoon.forms.datatype.SelectionList#getDatatype() */ public Datatype getDatatype() { return datatype; } /* (non-Javadoc) * @see org.apache.cocoon.forms.datatype.SelectionList#generateSaxFragment(org.xml.sax.ContentHandler, java.util.Locale) */ public void generateSaxFragment(ContentHandler contentHandler, Locale locale) throws SAXException { try { contentHandler.startElement(FormsConstants.INSTANCE_NS, SELECTION_LIST_EL, FormsConstants.INSTANCE_PREFIX_COLON + SELECTION_LIST_EL, XMLUtils.EMPTY_ATTRIBUTES); // Create void element if (nullable) { AttributesImpl voidAttrs = new AttributesImpl(); voidAttrs.addCDATAAttribute("value", ""); contentHandler.startElement(FormsConstants.INSTANCE_NS, ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL, voidAttrs); if (this.nullText != null) { contentHandler.startElement(FormsConstants.INSTANCE_NS, LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL, XMLUtils.EMPTY_ATTRIBUTES); contentHandler.startElement(FormsConstants.I18N_NS, TEXT_EL, FormsConstants.I18N_PREFIX_COLON + TEXT_EL, XMLUtils.EMPTY_ATTRIBUTES); contentHandler.characters(nullText.toCharArray(), 0, nullText.length()); contentHandler.endElement(FormsConstants.I18N_NS, TEXT_EL, FormsConstants.I18N_PREFIX_COLON + TEXT_EL); contentHandler.endElement(FormsConstants.INSTANCE_NS, LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL); } contentHandler.endElement(FormsConstants.INSTANCE_NS, ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL); } // Test if we have an apache enum class boolean apacheEnumDone = false; if (Enum.class.isAssignableFrom(clazz)) { Iterator iter = EnumUtils.iterator(clazz); if (iter != null) { apacheEnumDone = true; while (iter.hasNext()) { Enum element = (Enum) iter.next(); String stringValue = clazz.getName() + "." + element.getName(); generateItem(contentHandler, stringValue); } } } // If it's not an apache enum or we didn't manage to read the enum list, then proceed with common method. if (!apacheEnumDone) { Field fields[] = clazz.getDeclaredFields(); for (int i = 0 ; i < fields.length ; ++i) { int mods = fields[i].getModifiers(); if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods) && fields[i].get(null).getClass().equals(clazz)) { String stringValue = clazz.getName() + "." + fields[i].getName(); generateItem(contentHandler, stringValue); } } } // End the selection-list contentHandler.endElement(FormsConstants.INSTANCE_NS, SELECTION_LIST_EL, FormsConstants.INSTANCE_PREFIX_COLON + SELECTION_LIST_EL); } catch (Exception e) { throw new SAXException("Got exception trying to get enum's values", e); } } /** * Generates a single selection list item. * @param contentHandler The content handler we are streaming sax events to. * @param stringValue The string name of the item, composed by FQN and enum item. * @throws SAXException */ private void generateItem(ContentHandler contentHandler, String stringValue) throws SAXException { // Output this item AttributesImpl itemAttrs = new AttributesImpl(); itemAttrs.addCDATAAttribute("value", stringValue); contentHandler.startElement(FormsConstants.INSTANCE_NS, ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL, itemAttrs); contentHandler.startElement(FormsConstants.INSTANCE_NS, LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL, XMLUtils.EMPTY_ATTRIBUTES); // TODO: make i18n element optional contentHandler.startElement(FormsConstants.I18N_NS, TEXT_EL, FormsConstants.I18N_PREFIX_COLON + TEXT_EL, XMLUtils.EMPTY_ATTRIBUTES); contentHandler.characters(stringValue.toCharArray(), 0, stringValue.length()); contentHandler.endElement(FormsConstants.I18N_NS, TEXT_EL, FormsConstants.I18N_PREFIX_COLON + TEXT_EL); contentHandler.endElement(FormsConstants.INSTANCE_NS, LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON + LABEL_EL); contentHandler.endElement(FormsConstants.INSTANCE_NS, ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON + ITEM_EL); } }