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 org.w3c.dom.Document;
020: import org.w3c.dom.Element;
021: import org.w3c.dom.NodeList;
022: import org.w3c.dom.Node;
023: import org.apache.avalon.framework.service.ServiceException;
024: import org.apache.avalon.framework.service.ServiceManager;
025: import org.apache.avalon.framework.service.Serviceable;
026: import org.apache.cocoon.woody.Constants;
027: import org.apache.cocoon.woody.datatype.convertor.Convertor;
028: import org.apache.cocoon.woody.datatype.convertor.DefaultFormatCache;
029: import org.apache.cocoon.woody.util.DomHelper;
030: import org.apache.excalibur.source.Source;
031: import org.apache.excalibur.source.SourceResolver;
032: import org.apache.excalibur.xml.sax.XMLizable;
033: import org.xml.sax.InputSource;
034: import org.xml.sax.SAXException;
035:
036: import java.util.Locale;
037:
038: /**
039: * Builds {@link SelectionList}s from an XML description or an URL.
040: *
041: * <p>Note: the class {@link DynamicSelectionList} also interprets the same wd:selection-list XML, so if
042: * anything changes here to how that XML is interpreted, it also needs to change over there and vice versa.
043: *
044: * @version CVS $Id: DefaultSelectionListBuilder.java 433543 2006-08-22 06:22:54Z crossley $
045: */
046: public class DefaultSelectionListBuilder implements
047: SelectionListBuilder, Serviceable {
048:
049: private ServiceManager serviceManager;
050:
051: public void service(ServiceManager manager) throws ServiceException {
052: this .serviceManager = manager;
053: }
054:
055: public SelectionList build(Element selectionListElement,
056: Datatype datatype) throws Exception {
057: SelectionList selectionList;
058: String src = selectionListElement.getAttribute("src");
059: if (src.length() > 0) {
060: boolean dynamic = DomHelper.getAttributeAsBoolean(
061: selectionListElement, "dynamic", false);
062: if (!dynamic) {
063: selectionListElement = readSelectionList(src);
064: selectionList = buildStaticList(selectionListElement,
065: datatype);
066: } else {
067: selectionList = new DynamicSelectionList(datatype, src,
068: serviceManager);
069: }
070: } else {
071: // selection list is defined inline
072: selectionList = buildStaticList(selectionListElement,
073: datatype);
074: }
075:
076: return selectionList;
077: }
078:
079: private SelectionList buildStaticList(Element selectionListElement,
080: Datatype datatype) throws Exception {
081: StaticSelectionList selectionList = new StaticSelectionList(
082: datatype);
083: Convertor convertor = null;
084: Convertor.FormatCache formatCache = new DefaultFormatCache();
085:
086: NodeList children = selectionListElement.getChildNodes();
087: for (int i = 0; children.item(i) != null; i++) {
088: Node node = children.item(i);
089: if (convertor == null && node instanceof Element
090: && Constants.WD_NS.equals(node.getNamespaceURI())
091: && "convertor".equals(node.getLocalName())) {
092: Element convertorConfigElement = (Element) node;
093: try {
094: convertor = datatype.getBuilder().buildConvertor(
095: convertorConfigElement);
096: } catch (Exception e) {
097: throw new SAXException(
098: "Error building convertor from convertor configuration embedded in selection list XML.",
099: e);
100: }
101: } else if (node instanceof Element
102: && Constants.WD_NS.equals(node.getNamespaceURI())
103: && "item".equals(node.getLocalName())) {
104: if (convertor == null) {
105: convertor = datatype.getConvertor();
106: }
107: Element element = (Element) node;
108: String stringValue = element.getAttribute("value");
109: Object value;
110: if ("".equals(stringValue)) {
111: // Empty value translates into the null object
112: value = null;
113: } else {
114: value = convertor.convertFromString(stringValue,
115: Locale.US, formatCache);
116: if (value == null) {
117: throw new Exception(
118: "Could not convert the value \""
119: + stringValue
120: + "\" to the type "
121: + datatype.getDescriptiveName()
122: + ", defined at "
123: + DomHelper
124: .getLocation(element));
125: }
126: }
127:
128: XMLizable label = null;
129: Element labelEl = DomHelper.getChildElement(element,
130: Constants.WD_NS, "label");
131: if (labelEl != null) {
132: label = DomHelper.compileElementContent(labelEl);
133: }
134: selectionList.addItem(value, label);
135: }
136: }
137:
138: return selectionList;
139: }
140:
141: private Element readSelectionList(String src) throws Exception {
142: SourceResolver resolver = null;
143: Source source = null;
144: try {
145: resolver = (SourceResolver) serviceManager
146: .lookup(SourceResolver.ROLE);
147: source = resolver.resolveURI(src);
148: InputSource inputSource = new InputSource(source
149: .getInputStream());
150: inputSource.setSystemId(source.getURI());
151: Document document = DomHelper.parse(inputSource);
152: Element selectionListElement = document
153: .getDocumentElement();
154: if (!Constants.WD_NS.equals(selectionListElement
155: .getNamespaceURI())
156: || !"selection-list".equals(selectionListElement
157: .getLocalName()))
158: throw new Exception(
159: "Excepted a wd:selection-list element at "
160: + DomHelper
161: .getLocation(selectionListElement));
162: return selectionListElement;
163: } finally {
164: if (source != null)
165: resolver.release(source);
166: if (resolver != null)
167: serviceManager.release(resolver);
168: }
169: }
170: }
|