001: /**
002: * Copyright (c) 2007, Aberystwyth University
003: *
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the
012: * following disclaimer.
013: *
014: * - Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * - Neither the name of the Centre for Advanced Software and
020: * Intelligent Systems (CASIS) nor the names of its
021: * contributors may be used to endorse or promote products derived
022: * from this software without specific prior written permission.
023: *
024: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
025: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
026: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
027: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
028: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
029: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
030: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
031: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
032: * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
033: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
034: * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
035: * SUCH DAMAGE.
036: */package org.purl.sword.base;
037:
038: /**
039: * Author : $Author: nst $
040: * Date : $Date: 2007/09/21 15:18:55 $
041: * Revision : $Revision: 1.3 $
042: * Name : $Name: $
043: */
044:
045: import nu.xom.Element;
046: import nu.xom.Node;
047:
048: import java.text.ParseException;
049: import java.text.SimpleDateFormat;
050: import java.util.Date;
051: import java.util.GregorianCalendar;
052:
053: /**
054: * Parent class for all classes that represent an XML element. This provides
055: * some common utility methods that are useful for marshalling and
056: * unmarshalling data.
057: *
058: * @author Neil Taylor
059: */
060: public class XmlElement {
061: /**
062: * The name to use for the prefix.
063: */
064: protected String prefix;
065:
066: /**
067: *
068: */
069: protected String localName;
070:
071: /**
072: *
073: * @param localName
074: */
075: public XmlElement(String localName) {
076: this .localName = localName;
077: }
078:
079: /**
080: * Create a new instance.
081: */
082: public XmlElement(String prefix, String localName) {
083: this .prefix = prefix;
084: this .localName = localName;
085: }
086:
087: /**
088: * The Date format that is used to parse dates to and from the ISO format
089: * in the XML data.
090: */
091: protected static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
092:
093: /**
094: * Extract a boolean value from the specified element. The boolean value
095: * is represented as the string 'true' or 'false' as the only child
096: * of the specified element.
097: *
098: * @param element The element that contains the boolean value.
099: * @return True or false, based on the string in the element's content.
100: * @throws UnmarshallException If the element does not contain a single child, or if
101: * the child does not contain the value 'true' or 'false'.
102: */
103: protected boolean unmarshallBoolean(Element element)
104: throws UnmarshallException {
105: if (element.getChildCount() != 1) {
106: throw new UnmarshallException("Missing Boolean Value", null);
107: }
108:
109: // ok to get the single child element. This should be a text element.
110: try {
111: Node child = element.getChild(0);
112: String value = child.getValue();
113: if ("true".equals(value)) {
114: return true;
115: } else if ("false".equals(value)) {
116: return false;
117: } else {
118: throw new UnmarshallException("Illegal Value");
119: }
120: } catch (IndexOutOfBoundsException ex) {
121: throw new UnmarshallException(
122: "Error accessing Boolean element", ex);
123: }
124:
125: }
126:
127: /**
128: * Extract a string value from the specified element. The value
129: * is the only child of the specified element.
130: *
131: * @param element The element that contains the string value.
132: * @return The string.
133: * @throws UnmarshallException If the element does not contain a single child.
134: */
135: protected String unmarshallString(Element element)
136: throws UnmarshallException {
137: if (element.getChildCount() != 1) {
138: throw new UnmarshallException("Missing String Value", null);
139: }
140:
141: // ok to get the single child element. This should be a text element.
142: try {
143: Node child = element.getChild(0);
144: return child.getValue();
145: } catch (IndexOutOfBoundsException ex) {
146: throw new UnmarshallException(
147: "Error accessing Boolean element", ex);
148: }
149:
150: }
151:
152: /**
153: * Extract an integer value from the specified element. The integer value
154: * is represented as a string in the only child
155: * of the specified element.
156: *
157: * @param element The element that contains the integer.
158: * @return The integer.
159: * @throws UnmarshallException If the element does not contain a single child, or if
160: * the child does not contain the valid integer.
161: */
162: protected int unmarshallInteger(Element element)
163: throws UnmarshallException {
164: if (element.getChildCount() != 1) {
165: throw new UnmarshallException("Missing Integer Value", null);
166: }
167:
168: // ok to get the single child element. This should be a text element.
169: try {
170: Node child = element.getChild(0);
171: return Integer.parseInt(child.getValue());
172: } catch (IndexOutOfBoundsException ex) {
173: throw new UnmarshallException(
174: "Error accessing Boolean element", ex);
175: } catch (NumberFormatException nfex) {
176: throw new UnmarshallException(
177: "Error fomratting the number", nfex);
178: }
179: }
180:
181: /**
182: * Extract an date value from the specified element. The date value
183: * is represented as a string in the only child of the element.
184: *
185: * @param element The element that contains the date.
186: * @return The date.
187: * @throws UnmarshallException If the element does not contain a single child, or if
188: * the child does not contain the valid date.
189: */
190: protected Date unmarshallDate(Element element)
191: throws UnmarshallException {
192: try {
193: String content = unmarshallString(element);
194: return stringToDate(content);
195: } catch (UnmarshallException ue) {
196: throw new UnmarshallException("Error accessing the date.",
197: ue);
198: } catch (ParseException pe) {
199: throw new UnmarshallException("Error accessing the date.",
200: pe);
201: }
202: }
203:
204: /**
205: * Convert the date to a string. If the date is null,
206: * the result will result to a default date of 1st January 1970.
207: * FIXME - is this sensible?
208: *
209: * @param date The Date object.
210: * @return The Date, expressed as a string in the format
211: * yyyy-MM-ddTHH:mm:ssZ.
212: */
213: protected String dateToString(Date date) {
214: if (date == null) {
215: GregorianCalendar cal = new GregorianCalendar(1970, 0, 1,
216: 0, 0, 0);
217: date = cal.getTime();
218: }
219: SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
220: return formatter.format(date);
221: }
222:
223: /**
224: * Convert the string into a Date object.
225: *
226: * @param date The date, represented as a string.
227: * @return A Date.
228: * @throws ParseException If the string does not match the format
229: * of yyyy-MM-ddTHH:mm:ssZ.
230: */
231: protected Date stringToDate(String date) throws ParseException {
232: SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
233: return formatter.parse(date);
234: }
235:
236: /**
237: * Determines if the specified element is an instance of the element name. If
238: * you are checking the name title in the ATOM namespace, then the local name
239: * should be 'title' and the namespaceURI is the URI for the ATOM namespace.
240: *
241: * @param element The specified element.
242: * @param localName The local name for the element.
243: * @param namespaceURI The namespace for the element.
244: * @return True if the element matches the localname and namespace. Otherwise, false.
245: */
246: protected boolean isInstanceOf(Element element, String localName,
247: String namespaceURI) {
248: return (localName.equals(element.getLocalName()) && namespaceURI
249: .equals(element.getNamespaceURI()));
250: }
251:
252: /**
253: * Retrieve the qualified name for this object. This uses the
254: * prefix and local name stored in this object.
255: *
256: * @return A string of the format 'prefix:localName'
257: */
258: public String getQualifiedName() {
259: return getQualifiedName(localName);
260: }
261:
262: /**
263: * Retrieve the qualified name. The prefix for this object is prepended
264: * onto the specified local name.
265: *
266: * @param name the specified local name.
267: * @return A string of the format 'prefix:name'
268: */
269: public String getQualifiedName(String name) {
270: String p = prefix;
271: if (p != null) {
272: p += ":";
273: }
274: return p + name;
275: }
276: }
|