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.woody.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.woody.Constants;
026: import org.apache.cocoon.xml.AttributesImpl;
027: import org.apache.commons.jxpath.JXPathContext;
028: import org.apache.commons.jxpath.Pointer;
029: import org.apache.excalibur.xml.sax.XMLizable;
030:
031: import org.xml.sax.ContentHandler;
032: import org.xml.sax.SAXException;
033:
034: /**
035: * A selection list that takes its values from the flow page data.
036: *
037: * @see org.apache.cocoon.woody.datatype.FlowJXPathSelectionListBuilder
038: * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
039: * @version CVS $Id: FlowJXPathSelectionList.java 433543 2006-08-22 06:22:54Z crossley $
040: */
041: public class FlowJXPathSelectionList implements SelectionList {
042:
043: private Context context;
044: private String listPath;
045: private String valuePath;
046: private String labelPath;
047: private Datatype datatype;
048: private Object model;
049:
050: public FlowJXPathSelectionList(Context context, String listPath,
051: String valuePath, String labelPath, Datatype datatype) {
052: this .context = context;
053: this .listPath = listPath;
054: this .valuePath = valuePath;
055: this .labelPath = labelPath;
056: this .datatype = datatype;
057: }
058:
059: /**
060: * Builds a dynamic selection list from an in-memory collection.
061: * @see org.apache.cocoon.woody.formmodel.Field#setSelectionList(Object model, String valuePath, String labelPath)
062: * @param model The collection used as a model for the selection list.
063: * @param valuePath An XPath expression referring to the attribute used
064: * to populate the values of the list's items.
065: * @param labelPath An XPath expression referring to the attribute used
066: * to populate the labels of the list's items.
067: * @param datatype
068: */
069: public FlowJXPathSelectionList(Object model, String valuePath,
070: String labelPath, Datatype datatype) {
071: this .model = model;
072: this .valuePath = valuePath;
073: this .labelPath = labelPath;
074: this .datatype = datatype;
075: }
076:
077: public Datatype getDatatype() {
078: return this .datatype;
079: }
080:
081: public void generateSaxFragment(ContentHandler contentHandler,
082: Locale locale) throws SAXException {
083: JXPathContext ctx = null;
084: Iterator iter = null;
085: if (model == null) {
086: Object flowData = FlowHelper.getContextObject(ContextHelper
087: .getObjectModel(this .context));
088: if (flowData == null) {
089: throw new SAXException(
090: "No flow data to produce selection list");
091: }
092:
093: // Move to the list location
094: ctx = JXPathContext.newContext(flowData);
095:
096: // Iterate on all elements of the list
097: iter = ctx.iteratePointers(this .listPath);
098: } else {
099: // Move to the list location
100: ctx = JXPathContext.newContext(model);
101:
102: // Iterate on all elements of the list
103: iter = ctx.iteratePointers(".");
104: }
105:
106: // Start the selection-list
107: contentHandler.startElement(Constants.WI_NS, SELECTION_LIST_EL,
108: Constants.WI_PREFIX_COLON + SELECTION_LIST_EL,
109: Constants.EMPTY_ATTRS);
110:
111: while (iter.hasNext()) {
112: String stringValue = "";
113: Object label = null;
114:
115: // Get a context on the current item
116: Pointer ptr = (Pointer) iter.next();
117: if (ptr.getValue() != null) {
118: JXPathContext itemCtx = ctx.getRelativeContext(ptr);
119:
120: // Get the value as a string
121: Object value = itemCtx.getValue(this .valuePath);
122:
123: // List may contain null value, and (per contract with convertors),
124: // convertors are not invoked on nulls.
125: if (value != null) {
126: stringValue = this .datatype.convertToString(value,
127: locale);
128: }
129:
130: // Get the label (can be ommitted)
131: itemCtx.setLenient(true);
132: label = itemCtx.getValue(this .labelPath);
133: if (label == null) {
134: label = stringValue;
135: }
136: }
137:
138: // Output this item
139: AttributesImpl itemAttrs = new AttributesImpl();
140: itemAttrs.addCDATAAttribute("value", stringValue);
141: contentHandler.startElement(Constants.WI_NS, ITEM_EL,
142: Constants.WI_PREFIX_COLON + ITEM_EL, itemAttrs);
143: if (label != null) {
144: contentHandler.startElement(Constants.WI_NS, LABEL_EL,
145: Constants.WI_PREFIX_COLON + LABEL_EL,
146: Constants.EMPTY_ATTRS);
147: if (label instanceof XMLizable) {
148: ((XMLizable) label).toSAX(contentHandler);
149: } else {
150: String stringLabel = label.toString();
151: contentHandler.characters(
152: stringLabel.toCharArray(), 0, stringLabel
153: .length());
154: }
155: contentHandler.endElement(Constants.WI_NS, LABEL_EL,
156: Constants.WI_PREFIX_COLON + LABEL_EL);
157: }
158: contentHandler.endElement(Constants.WI_NS, ITEM_EL,
159: Constants.WI_PREFIX_COLON + ITEM_EL);
160: }
161:
162: // End the selection-list
163: contentHandler.endElement(Constants.WI_NS, SELECTION_LIST_EL,
164: Constants.WI_PREFIX_COLON + SELECTION_LIST_EL);
165: }
166: }
|