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.util.Iterator;
020: import java.util.Locale;
021:
022: import org.apache.avalon.framework.context.Context;
023: import org.apache.cocoon.components.ContextHelper;
024: import org.apache.cocoon.components.flow.FlowHelper;
025: import org.apache.cocoon.forms.FormsConstants;
026: import org.apache.cocoon.forms.util.I18nMessage;
027: import org.apache.cocoon.xml.AttributesImpl;
028: import org.apache.cocoon.xml.XMLUtils;
029: import org.apache.commons.jxpath.JXPathContext;
030: import org.apache.commons.jxpath.Pointer;
031: import org.apache.excalibur.xml.sax.XMLizable;
032:
033: import org.xml.sax.ContentHandler;
034: import org.xml.sax.SAXException;
035:
036: /**
037: * A selection list that takes its values from the flow page data.
038: *
039: * @see org.apache.cocoon.forms.datatype.FlowJXPathSelectionListBuilder
040: * @version $Id: FlowJXPathSelectionList.java 449149 2006-09-23 03:58:05Z crossley $
041: */
042: public class FlowJXPathSelectionList implements SelectionList {
043:
044: private Context context;
045: private String listPath;
046: private String valuePath;
047: private String labelPath;
048: private Datatype datatype;
049: private Object model;
050: private boolean nullable = false;
051: private String nullText;
052: private boolean nullTextIsI18nKey = false;
053: private String i18nCatalog;
054: private boolean labelIsI18nKey = false;
055:
056: public FlowJXPathSelectionList(Context context, String listPath,
057: String valuePath, String labelPath, Datatype datatype,
058: String nullText, boolean nullTextIsI18nKey,
059: String i18nCatalog, boolean labelIsI18nKey) {
060: this .context = context;
061: this .listPath = listPath;
062: this .valuePath = valuePath;
063: this .labelPath = labelPath;
064: this .datatype = datatype;
065: this .nullText = nullText;
066: this .nullable = (nullText != null);
067: this .nullTextIsI18nKey = nullTextIsI18nKey;
068: this .i18nCatalog = i18nCatalog;
069: this .labelIsI18nKey = labelIsI18nKey;
070: }
071:
072: /**
073: * Builds a dynamic selection list from an in-memory collection.
074: * @see org.apache.cocoon.forms.formmodel.Field#setSelectionList(Object model, String valuePath, String labelPath)
075: * @param model The collection used as a model for the selection list.
076: * @param valuePath An XPath expression referring to the attribute used
077: * to populate the values of the list's items.
078: * @param labelPath An XPath expression referring to the attribute used
079: * to populate the labels of the list's items.
080: * @param datatype
081: */
082: public FlowJXPathSelectionList(Object model, String valuePath,
083: String labelPath, Datatype datatype) {
084: this .model = model;
085: this .valuePath = valuePath;
086: this .labelPath = labelPath;
087: this .datatype = datatype;
088: }
089:
090: public Datatype getDatatype() {
091: return this .datatype;
092: }
093:
094: public void generateSaxFragment(ContentHandler contentHandler,
095: Locale locale) throws SAXException {
096: JXPathContext ctx = null;
097: Iterator iter = null;
098: if (model == null) {
099: Object flowData = FlowHelper.getContextObject(ContextHelper
100: .getObjectModel(this .context));
101: if (flowData == null) {
102: throw new SAXException(
103: "No flow data to produce selection list");
104: }
105:
106: // Move to the list location
107: ctx = JXPathContext.newContext(flowData);
108:
109: // Iterate on all elements of the list
110: iter = ctx.iteratePointers(this .listPath);
111: } else {
112: // Move to the list location
113: ctx = JXPathContext.newContext(model);
114:
115: // Iterate on all elements of the list
116: iter = ctx.iteratePointers(".");
117: }
118:
119: // Start the selection-list
120: contentHandler.startElement(FormsConstants.INSTANCE_NS,
121: SELECTION_LIST_EL, FormsConstants.INSTANCE_PREFIX_COLON
122: + SELECTION_LIST_EL, XMLUtils.EMPTY_ATTRIBUTES);
123: if (this .nullable) {
124: final AttributesImpl voidAttrs = new AttributesImpl();
125: voidAttrs.addCDATAAttribute("value", "");
126: contentHandler.startElement(FormsConstants.INSTANCE_NS,
127: ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON
128: + ITEM_EL, voidAttrs);
129:
130: if (this .nullText != null) {
131: contentHandler.startElement(FormsConstants.INSTANCE_NS,
132: LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON
133: + LABEL_EL, XMLUtils.EMPTY_ATTRIBUTES);
134:
135: if (this .nullTextIsI18nKey) {
136: if ((this .i18nCatalog != null)
137: && (this .i18nCatalog.trim().length() > 0)) {
138: new I18nMessage(this .nullText, this .i18nCatalog)
139: .toSAX(contentHandler);
140: } else {
141: new I18nMessage(this .nullText)
142: .toSAX(contentHandler);
143: }
144: } else {
145: contentHandler.characters(this .nullText
146: .toCharArray(), 0, this .nullText.length());
147: }
148:
149: contentHandler.endElement(FormsConstants.INSTANCE_NS,
150: LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON
151: + LABEL_EL);
152: }
153:
154: contentHandler.endElement(FormsConstants.INSTANCE_NS,
155: ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON
156: + ITEM_EL);
157: }
158:
159: while (iter.hasNext()) {
160: String stringValue = "";
161: Object label = null;
162:
163: // Get a context on the current item
164: Pointer ptr = (Pointer) iter.next();
165: if (ptr.getValue() != null) {
166: JXPathContext itemCtx = ctx.getRelativeContext(ptr);
167:
168: // Get the value as a string
169: Object value = itemCtx.getValue(this .valuePath);
170:
171: // List may contain null value, and (per contract with convertors),
172: // convertors are not invoked on nulls.
173: if (value != null) {
174: stringValue = this .datatype.convertToString(value,
175: locale);
176: }
177:
178: // Get the label (can be ommitted)
179: if (this .labelPath != null) {
180: itemCtx.setLenient(true);
181: label = itemCtx.getValue(this .labelPath);
182: }
183: }
184:
185: // Output this item
186: AttributesImpl itemAttrs = new AttributesImpl();
187: itemAttrs.addCDATAAttribute("value", stringValue);
188: contentHandler.startElement(FormsConstants.INSTANCE_NS,
189: ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON
190: + ITEM_EL, itemAttrs);
191: if (label != null) {
192: contentHandler.startElement(FormsConstants.INSTANCE_NS,
193: LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON
194: + LABEL_EL, XMLUtils.EMPTY_ATTRIBUTES);
195: if (label instanceof XMLizable) {
196: ((XMLizable) label).toSAX(contentHandler);
197: } else if (this .labelIsI18nKey) {
198: String stringLabel = label.toString();
199:
200: if ((this .i18nCatalog != null)
201: && (this .i18nCatalog.trim().length() > 0)) {
202: new I18nMessage(stringLabel, this .i18nCatalog)
203: .toSAX(contentHandler);
204: } else {
205: new I18nMessage(stringLabel)
206: .toSAX(contentHandler);
207: }
208: } else {
209: String stringLabel = label.toString();
210: contentHandler.characters(
211: stringLabel.toCharArray(), 0, stringLabel
212: .length());
213: }
214: contentHandler.endElement(FormsConstants.INSTANCE_NS,
215: LABEL_EL, FormsConstants.INSTANCE_PREFIX_COLON
216: + LABEL_EL);
217: }
218: contentHandler.endElement(FormsConstants.INSTANCE_NS,
219: ITEM_EL, FormsConstants.INSTANCE_PREFIX_COLON
220: + ITEM_EL);
221: }
222:
223: // End the selection-list
224: contentHandler.endElement(FormsConstants.INSTANCE_NS,
225: SELECTION_LIST_EL, FormsConstants.INSTANCE_PREFIX_COLON
226: + SELECTION_LIST_EL);
227: }
228: }
|