001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package org.restlet.resource;
020:
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.Map.Entry;
028:
029: import javax.xml.namespace.NamespaceContext;
030: import javax.xml.namespace.QName;
031: import javax.xml.xpath.XPathConstants;
032:
033: import org.restlet.data.MediaType;
034: import org.restlet.util.NodeSet;
035: import org.w3c.dom.Node;
036: import org.w3c.dom.NodeList;
037:
038: /**
039: * Representation based on an XML document. It knows how to evaluate XPath
040: * expressions and how to manage a namespace context.
041: *
042: * @author Jerome Louvel (contact@noelios.com)
043: */
044: public abstract class XmlRepresentation extends OutputRepresentation
045: implements NamespaceContext {
046: /** Internal map of namespaces. */
047: private Map<String, String> namespaces;
048:
049: /** Indicates if processing is namespace aware. */
050: private boolean namespaceAware;
051:
052: /**
053: * Constructor.
054: *
055: * @param mediaType
056: * The representation's mediaType.
057: */
058: public XmlRepresentation(MediaType mediaType) {
059: super (mediaType);
060: this .namespaces = null;
061: this .namespaceAware = false;
062: }
063:
064: /**
065: * Constructor.
066: *
067: * @param mediaType
068: * The representation's mediaType.
069: * @param expectedSize
070: * The expected input stream size.
071: */
072: public XmlRepresentation(MediaType mediaType, long expectedSize) {
073: super (mediaType, expectedSize);
074: this .namespaces = null;
075: this .namespaceAware = false;
076: }
077:
078: /**
079: * Evaluates an XPath expression and returns the result as in the given
080: * return type.
081: *
082: * @param returnType
083: * The qualified name of the return type.
084: * @return The evaluation result.
085: * @see javax.xml.xpath.XPathException
086: * @see javax.xml.xpath.XPathConstants
087: */
088: public abstract Object evaluate(String expression, QName returnType)
089: throws Exception;
090:
091: /**
092: * Evaluates an XPath expression as a boolean. If the evaluation fails, null
093: * will be returned.
094: *
095: * @return The evaluation result.
096: */
097: public Boolean getBoolean(String expression) {
098: return (Boolean) internalEval(expression,
099: XPathConstants.BOOLEAN);
100: }
101:
102: /**
103: * Returns the map of namespaces.
104: *
105: * @return The map of namespaces.
106: */
107: private Map<String, String> getNamespaces() {
108: if (this .namespaces == null)
109: this .namespaces = new HashMap<String, String>();
110: return this .namespaces;
111: }
112:
113: /**
114: * {@inheritDoc javax.xml.namespace.NamespaceContext#getNamespaceURI(java.lang.String}
115: */
116: public String getNamespaceURI(String prefix) {
117: return this .namespaces.get(prefix);
118: }
119:
120: /**
121: * Evaluates an XPath expression as a DOM Node. If the evaluation fails,
122: * null will be returned.
123: *
124: * @return The evaluation result.
125: */
126: public Node getNode(String expression) {
127: return (Node) internalEval(expression, XPathConstants.NODE);
128: }
129:
130: /**
131: * Evaluates an XPath expression as a DOM NodeList. If the evaluation fails,
132: * null will be returned.
133: *
134: * @return The evaluation result.
135: */
136: public NodeSet getNodes(String expression) {
137: NodeList nodes = (NodeList) internalEval(expression,
138: XPathConstants.NODESET);
139: return (nodes == null) ? null : new NodeSet(nodes);
140: }
141:
142: /**
143: * Evaluates an XPath expression as a number. If the evaluation fails, null
144: * will be returned.
145: *
146: * @return The evaluation result.
147: */
148: public Double getNumber(String expression) {
149: return (Double) internalEval(expression, XPathConstants.NUMBER);
150: }
151:
152: /**
153: * {@inheritDoc javax.xml.namespace.NamespaceContext#getPrefix(java.lang.String}
154: */
155: public String getPrefix(String namespaceURI) {
156: String result = null;
157:
158: for (Entry<String, String> entry : getNamespaces().entrySet()) {
159: if ((result == null)
160: && entry.getValue().equals(namespaceURI))
161: result = entry.getKey();
162: }
163:
164: return result;
165: }
166:
167: /**
168: * {@inheritDoc javax.xml.namespace.NamespaceContext#getPrefixes(java.lang.String}
169: */
170: public Iterator<String> getPrefixes(String namespaceURI) {
171: List<String> result = new ArrayList<String>();
172:
173: for (Entry<String, String> entry : getNamespaces().entrySet()) {
174: if (entry.getValue().equals(namespaceURI))
175: result.add(entry.getKey());
176: }
177:
178: return Collections.unmodifiableList(result).iterator();
179: }
180:
181: /**
182: * Evaluates an XPath expression as a string.
183: *
184: * @return The evaluation result.
185: */
186: public String getText(String expression) {
187: return (String) internalEval(expression, XPathConstants.STRING);
188: }
189:
190: /**
191: * Evaluates an XPath expression and returns the result as in the given
192: * return type.
193: *
194: * @param returnType
195: * The qualified name of the return type.
196: * @return The evaluation result.
197: */
198: private Object internalEval(String expression, QName returnType) {
199: try {
200: return evaluate(expression, returnType);
201: } catch (Exception e) {
202: return null;
203: }
204: }
205:
206: /**
207: * Indicates if processing is namespace aware.
208: *
209: * @return True if processing is namespace aware.
210: */
211: public boolean isNamespaceAware() {
212: return this .namespaceAware;
213: }
214:
215: /**
216: * Puts a new mapping between a prefix and a namespace URI.
217: *
218: * @param prefix
219: * The namespace prefix.
220: * @param namespaceURI
221: * The namespace URI.
222: */
223: public void putNamespace(String prefix, String namespaceURI) {
224: getNamespaces().put(prefix, namespaceURI);
225: }
226:
227: /**
228: * Indicates if processing is namespace aware.
229: *
230: * @param namespaceAware
231: * Indicates if processing is namespace aware.
232: */
233: public void setNamespaceAware(boolean namespaceAware) {
234: this.namespaceAware = namespaceAware;
235: }
236:
237: }
|