001: /*
002: * This file is part of the Tucana Echo2 Library.
003: * Copyright (C) 2006.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package tucana.echo2.app.widgetdash;
031:
032: import java.io.StringReader;
033: import java.io.StringWriter;
034: import java.util.HashMap;
035: import java.util.Map;
036:
037: import javax.xml.parsers.DocumentBuilder;
038: import javax.xml.parsers.DocumentBuilderFactory;
039: import javax.xml.parsers.ParserConfigurationException;
040: import javax.xml.transform.Transformer;
041: import javax.xml.transform.TransformerFactory;
042: import javax.xml.transform.dom.DOMSource;
043: import javax.xml.transform.stream.StreamResult;
044:
045: import org.w3c.dom.Document;
046: import org.w3c.dom.Element;
047: import org.w3c.dom.NodeList;
048: import org.xml.sax.InputSource;
049:
050: /**
051: * A utility to marshal a {@link WidgetDashState} object to XML, and to unmarshal
052: * XML to a WidgetPaneState object.
053: *
054: * The format is as follows
055: * <p><code>
056: * <widgetpanestate column-count="3"><br>
057: * <widget identifier="widget1"><br>
058: * <position column="0" column-position="0"/><br>
059: * </widget><br>
060: * <widget identifier="widget2"><br>
061: * <position column="1" column-position="0"/><br>
062: * </widget><br>
063: * <widgetpanestate><br>
064: * </code></p>
065: * @author Jeremy Volkman
066: */
067: public class WidgetDashStateXmlTool {
068:
069: /**
070: * Marshal a WidgetPaneState object to XMl
071: * @param state The WidgetPaneState object
072: * @return The constructed W3C Document
073: */
074: public Document toXmlDocument(WidgetDashState state) {
075: DocumentBuilderFactory factory = DocumentBuilderFactory
076: .newInstance();
077: factory.setNamespaceAware(false);
078: DocumentBuilder builder = null;
079: try {
080: builder = factory.newDocumentBuilder();
081: } catch (ParserConfigurationException pce) {
082: throw new RuntimeException(pce);
083: }
084: Document stateDoc = builder.newDocument();
085:
086: Element root = stateDoc.createElement("widgetpanestate");
087: root.setAttribute("column-count", Integer.toString(state
088: .getColumnCount()));
089:
090: WidgetIdentifier[] identifiers = state.getWidgetIdentifiers();
091: for (int i = 0; i < identifiers.length; i++) {
092: WidgetIdentifier identifier = identifiers[i];
093: WidgetPosition position = state
094: .getWidgetPosition(identifier);
095: Element widgetElement = stateDoc.createElement("widget");
096: widgetElement.setAttribute("identifier", identifier
097: .getIdentifier());
098: if (position != null) {
099: Element positionElement = stateDoc
100: .createElement("position");
101: positionElement.setAttribute("column", Integer
102: .toString(position.getColumn()));
103: positionElement.setAttribute("column-position", Integer
104: .toString(position.getColumnPosition()));
105: widgetElement.appendChild(positionElement);
106: }
107: root.appendChild(widgetElement);
108: }
109:
110: stateDoc.appendChild(root);
111:
112: return stateDoc;
113: }
114:
115: /**
116: * Unmarshal a WidgetPaneState XML representation into a WidgetPaneState object
117: * @param document The XML document
118: * @return a WidgetPaneState object from the document.
119: */
120: public WidgetDashState fromXmlDocument(Document document) {
121: Element rootElement = (Element) document.getFirstChild();
122: int columnCount = WidgetDashState.COLUMN_COUNT_DEFAULT;
123: try {
124: columnCount = Integer.parseInt(rootElement
125: .getAttribute("column-count"));
126: } catch (NumberFormatException e) {
127: }
128:
129: Map widgetsToPositions = new HashMap();
130:
131: NodeList elements = rootElement.getElementsByTagName("widget");
132:
133: for (int i = 0; i < elements.getLength(); i++) {
134: Element widgetElement = (Element) elements.item(i);
135: String identifier = widgetElement
136: .getAttribute("identifier");
137: Element positionElement = (Element) widgetElement
138: .getFirstChild();
139: WidgetPosition position = null;
140: if (positionElement != null) {
141: String column = positionElement.getAttribute("column");
142: String columnPosition = positionElement
143: .getAttribute("column-position");
144: try {
145: position = new WidgetPosition(Integer
146: .parseInt(column), Integer
147: .parseInt(columnPosition));
148: } catch (NumberFormatException e) {
149:
150: }
151: }
152: widgetsToPositions.put(new WidgetIdentifier(identifier),
153: position);
154: }
155:
156: return new WidgetPaneStateImpl(columnCount, widgetsToPositions);
157: }
158:
159: /**
160: * Marshal a WidgetPaneState object to an XML string
161: * @param state The WidgetPaneState object
162: * @return The constructed XML as a string
163: */
164: public String toXmlString(WidgetDashState state) {
165: Document document = toXmlDocument(state);
166: try {
167: TransformerFactory tFactory = TransformerFactory
168: .newInstance();
169:
170: Transformer transformer = tFactory.newTransformer();
171: DOMSource source = new DOMSource(document);
172:
173: StringWriter writer = new StringWriter();
174: StreamResult result = new StreamResult(writer);
175:
176: transformer.transform(source, result);
177: return writer.getBuffer().toString();
178: } catch (Exception e) {
179: throw new RuntimeException(e);
180: }
181: }
182:
183: /**
184: * Unmarshal a WidgetPaneState XML representation into a WidgetPaneState object
185: * @param stateXml The XML document as astring
186: * @return a WidgetPaneState object from the document.
187: */
188: public WidgetDashState fromXmlString(String stateXml) {
189: DocumentBuilderFactory factory = DocumentBuilderFactory
190: .newInstance();
191: factory.setNamespaceAware(false);
192: DocumentBuilder builder = null;
193: try {
194: builder = factory.newDocumentBuilder();
195: Document stateDoc = builder.parse(new InputSource(
196: new StringReader(stateXml)));
197: return fromXmlDocument(stateDoc);
198: } catch (Exception e) {
199: throw new RuntimeException(e);
200: }
201: }
202:
203: /**
204: * Implementation of WidgetPaneState.
205: * @author Jeremy Volkman
206: */
207: private static class WidgetPaneStateImpl implements WidgetDashState {
208:
209: private int columnCount;
210: private Map widgetMap;
211:
212: public WidgetPaneStateImpl(int columnCount, Map widgetMap) {
213: this .columnCount = columnCount;
214: this .widgetMap = widgetMap;
215: }
216:
217: public int getColumnCount() {
218: return columnCount;
219: }
220:
221: public WidgetIdentifier[] getWidgetIdentifiers() {
222: return (WidgetIdentifier[]) widgetMap.keySet().toArray(
223: new WidgetIdentifier[widgetMap.size()]);
224: }
225:
226: public WidgetPosition getWidgetPosition(WidgetIdentifier widget) {
227: return (WidgetPosition) widgetMap.get(widget);
228: }
229:
230: }
231: }
|