teichmann@5861: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5861: * Software engineering by Intevation GmbH teichmann@5861: * teichmann@5993: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5861: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5993: * documentation coming with Dive4Elements River for details. teichmann@5861: */ teichmann@5861: teichmann@5835: package org.dive4elements.river.client.server; ingo@1571: teichmann@8071: import java.util.Collections; rrenkert@7824: import java.util.HashMap; teichmann@8071: import java.util.Map; rrenkert@7824: ingo@1571: import javax.xml.xpath.XPathConstants; ingo@1571: teichmann@8071: import org.w3c.dom.Attr; ingo@1571: import org.w3c.dom.Element; rrenkert@7824: import org.w3c.dom.NamedNodeMap; rrenkert@7824: import org.w3c.dom.Node; ingo@1571: import org.w3c.dom.NodeList; ingo@1571: import org.apache.log4j.Logger; teichmann@5835: import org.dive4elements.artifacts.common.ArtifactNamespaceContext; teichmann@5835: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@5835: import org.dive4elements.river.client.shared.model.Data; teichmann@5835: import org.dive4elements.river.client.shared.model.DataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultData; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultDataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.DoubleArrayData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntegerArrayData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntegerData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntegerOptionsData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntegerRangeData; rrenkert@7824: import org.dive4elements.river.client.shared.model.MultiAttributeData; rrenkert@7824: import org.dive4elements.river.client.shared.model.MultiDataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.StringData; teichmann@5835: import org.dive4elements.river.client.shared.model.StringOptionsData; teichmann@5835: import org.dive4elements.river.client.shared.model.LongRangeData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntDataItem; ingo@1571: ingo@1571: /** ingo@1571: * @author Ingo Weinzierl ingo@1571: */ ingo@1571: public class DataFactory { ingo@1571: teichmann@8203: private static final Logger log = Logger.getLogger(DataFactory.class); ingo@1571: ingo@1571: public static final String NS_URI = ArtifactNamespaceContext.NAMESPACE_URI; ingo@1571: ingo@1571: ingo@1571: /** ingo@1571: * Creates a new Data instance based on the art:type attribute of ingo@1571: * element. ingo@1571: * ingo@1571: * @param element The Data element. ingo@1571: * ingo@1571: * @return a Data instance. ingo@1571: */ ingo@1571: public static Data createDataFromElement(Element element) { ingo@2528: String name = element.getAttributeNS(NS_URI, "name"); ingo@2528: String type = element.getAttributeNS(NS_URI, "type"); ingo@2528: String label = element.getAttributeNS(NS_URI, "label"); ingo@2528: ingo@2528: label = label != null && label.length() > 0 ? label : name; ingo@1571: ingo@1575: try { teichmann@8203: log.debug("Create Data instance for: " + name + " | " + type); ingo@1571: ingo@1575: if (type == null || type.length() == 0) { ingo@2528: return createDefaultData(element, name, label); ingo@1575: } ingo@1575: ingo@1575: type = type.toLowerCase(); ingo@1575: ingo@1575: if (type.equals(StringData.TYPE)) { ingo@2528: return createStringData(element, name, label); ingo@1575: } ingo@1575: else if (type.equals(IntegerData.TYPE)) { ingo@2528: return createIntegerData(element, name, label); ingo@1575: } ingo@2532: else if (type.equals(StringOptionsData.TYPE)) { ingo@2532: return createStringOptionsData(element, name, label); ingo@2532: } ingo@1575: else if (type.equals(IntegerOptionsData.TYPE)) { ingo@2528: return createIntegerOptionsData(element, name, label); ingo@1575: } ingo@1575: else if (type.equals(IntegerRangeData.TYPE)) { ingo@2528: return createIntegerRangeData(element, name, label); ingo@1575: } ingo@1575: else if (type.equals(IntegerArrayData.TYPE)) { ingo@2528: return createIntegerArrayData(element, name, label); ingo@1575: } ingo@1575: else if (type.equals(DoubleArrayData.TYPE)) { ingo@2528: return createDoubleArrayData(element, name, label); ingo@1575: } raimund@2468: else if (type.equals(LongRangeData.TYPE)) { ingo@2528: return createLongRangeData(element, name, label); raimund@2468: } rrenkert@7824: else if (type.equals(MultiAttributeData.TYPE)) { rrenkert@7824: return createMultiAttributeData(element, name, label); rrenkert@7824: } ingo@1575: else { ingo@2528: return createDefaultData(element, name, label); ingo@1575: } ingo@1571: } ingo@1575: catch (Exception e) { teichmann@8203: log.error("Error while data creation for: " + name); ingo@1571: } ingo@1575: ingo@1575: return null; ingo@1571: } ingo@1571: ingo@1571: rrenkert@7824: public static Data createMultiAttributeData( rrenkert@7824: Element element, rrenkert@7824: String name, rrenkert@7824: String label) { rrenkert@7824: return new MultiAttributeData( rrenkert@7824: name, rrenkert@7824: label, teichmann@8071: extractMultiDataItems(element), teichmann@8071: extractMeta(element)); teichmann@8071: } teichmann@8071: teichmann@8071: tom@8856: private static Map> extractMeta( tom@8856: Element element tom@8856: ) { teichmann@8071: NodeList nl = element.getElementsByTagName("meta"); teichmann@8071: int N = nl.getLength(); teichmann@8071: if (N < 1) { teichmann@8203: log.debug("No meta data found for multi attribute data"); teichmann@8071: return Collections.>emptyMap(); teichmann@8071: } teichmann@8071: Map> map = teichmann@8071: new HashMap>(); teichmann@8071: teichmann@8071: for (int i = 0; i < N; ++i) { teichmann@8071: Element e = (Element)nl.item(i); teichmann@8071: NamedNodeMap attrs = e.getAttributes(); teichmann@8071: Map kvs = new HashMap(); teichmann@8071: for (int j = 0, A = attrs.getLength(); j < A; ++j) { teichmann@8071: Attr attr = (Attr)attrs.item(j); teichmann@8071: kvs.put(attr.getName(), attr.getValue()); teichmann@8071: } teichmann@8071: map.put(e.getTagName(), kvs); teichmann@8071: } teichmann@8071: teichmann@8071: return map; rrenkert@7824: } rrenkert@7824: rrenkert@7824: rrenkert@7824: protected static DataItem[] extractMultiDataItems(Element element) { rrenkert@7824: NodeList itemList = (NodeList) XMLUtils.xpath( rrenkert@7824: element, rrenkert@7824: "art:item", rrenkert@7824: XPathConstants.NODESET, rrenkert@7824: ArtifactNamespaceContext.INSTANCE); rrenkert@7824: rrenkert@7824: if (itemList == null || itemList.getLength() == 0) { teichmann@8203: log.debug("No old data items found."); rrenkert@7824: return null; rrenkert@7824: } rrenkert@7824: rrenkert@7824: int count = itemList.getLength(); rrenkert@7824: rrenkert@7824: MultiDataItem[] items = new MultiDataItem[count]; rrenkert@7824: rrenkert@7824: for (int i = 0; i < count; i++) { rrenkert@7824: Element tmp = (Element) itemList.item(i); rrenkert@7824: rrenkert@7824: HashMap data = new HashMap(); rrenkert@7824: String label = tmp.getAttributeNS(NS_URI, "label"); rrenkert@7824: NamedNodeMap attributes = tmp.getAttributes(); teichmann@8071: for (int j = 0, L = attributes.getLength(); j < L; j++) { rrenkert@7824: Node n = attributes.item(j); rrenkert@7824: if (n.getNodeName().equals("label")) { rrenkert@7824: continue; rrenkert@7824: } rrenkert@7824: data.put(n.getNodeName(), n.getNodeValue()); rrenkert@7824: } rrenkert@7824: items[i] = new MultiDataItem(label, label, data); rrenkert@7824: } rrenkert@7824: return items; rrenkert@7824: } rrenkert@7824: rrenkert@7824: ingo@1571: /** ingo@1571: * This method creates a new instance of DefaultData which has no real type ingo@1571: * set. ingo@1571: * ingo@1571: * @param ele The Data element. ingo@1571: * @param name The name of the Data instance. ingo@1571: * ingo@1571: * @return an instance of DefaultData. ingo@1571: */ tom@8856: protected static Data createDefaultData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { teichmann@8203: log.debug("Create new DefaultData"); ingo@2528: return new DefaultData(name, label, "default", extractDataItems(ele)); ingo@1571: } ingo@1571: ingo@1571: ingo@1571: /** ingo@1575: * This method creates a new instance of StringData which has a type ingo@1575: * "string" set. ingo@1575: * ingo@1575: * @param ele The Data element. ingo@1575: * @param name The name of the Data instance. ingo@1575: * ingo@1575: * @return an instance of StringData. ingo@1575: */ tom@8856: protected static Data createStringData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { ingo@2528: return new StringData(name, label, extractDataItems(ele)); ingo@1575: } ingo@1575: ingo@1575: ingo@1575: /** ingo@1575: * This method creates a new instance of DefaultData which has a type ingo@1575: * "integer" set. ingo@1575: * ingo@1575: * @param ele The Data element. ingo@1575: * @param name The name of the Data instance. ingo@1575: * ingo@1575: * @return an instance of IntegerData. ingo@1575: */ tom@8856: protected static Data createIntegerData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { ingo@2528: return new IntegerData(name, label, extractDataItems(ele)); ingo@1575: } ingo@1575: ingo@1575: ingo@1575: /** ingo@2532: * This method creates a new instance of StringOptionsData which has a type ingo@2532: * "options" set. ingo@2532: * ingo@2532: * @param ele The Data element. ingo@2532: * @param name The name of the Data instance. ingo@2532: * ingo@2532: * @return an instance of StringOptionsData. ingo@2532: */ tom@8856: protected static Data createStringOptionsData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { ingo@2532: return new StringOptionsData(name, label, extractDataItems(ele)); ingo@2532: } ingo@2532: ingo@2532: ingo@2532: /** ingo@1575: * This method creates a new instance of DefaultData which has a type ingo@1575: * "intoptions" set. ingo@1575: * ingo@1575: * @param ele The Data element. ingo@1575: * @param name The name of the Data instance. ingo@1575: * ingo@1575: * @return an instance of IntegerOptionsData. ingo@1575: */ tom@8856: protected static Data createIntegerOptionsData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { ingo@2528: return new IntegerOptionsData(name, label, extractDataItems(ele)); ingo@1575: } ingo@1575: ingo@1575: ingo@1575: /** ingo@1575: * This method creates a new instance of DefaultData which has a type ingo@1575: * "intrange" set. ingo@1575: * ingo@1575: * @param ele The Data element. ingo@1575: * @param name The name of the Data instance. ingo@1575: * ingo@1575: * @return an instance of IntegerRangeData. ingo@1575: */ tom@8856: protected static Data createIntegerRangeData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { ingo@1575: DataItem[] items = extractDataItems(ele); ingo@1575: String rawValue = items[0].getStringValue(); ingo@1575: ingo@1575: String[] minmax = rawValue.split(";"); ingo@1575: ingo@1575: return new IntegerRangeData( ingo@1575: name, ingo@2528: label, ingo@1575: Integer.valueOf(minmax[0]), ingo@1575: Integer.valueOf(minmax[1])); ingo@1575: } ingo@1575: ingo@1575: ingo@1575: /** ingo@1575: * This method creates a new instance of DefaultData which has a type ingo@1575: * "integerarray" set. ingo@1575: * ingo@1575: * @param ele The Data element. ingo@1575: * @param name The name of the Data instance. ingo@1575: * ingo@1575: * @return an instance of IntegerArrayData. ingo@1575: */ tom@8856: protected static Data createIntegerArrayData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { raimund@2535: IntDataItem[] items = extractIntDataItems(ele); raimund@2535: return new IntegerArrayData(name, label, items); ingo@1575: } ingo@1575: ingo@1575: ingo@1575: /** ingo@1575: * This method creates a new instance of DefaultData which has a type ingo@1575: * "doublearray" set. ingo@1575: * ingo@1575: * @param ele The Data element. ingo@1575: * @param name The name of the Data instance. ingo@1575: * ingo@1575: * @return an instance of DoubleArrayData. ingo@1575: */ tom@8856: protected static Data createDoubleArrayData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { ingo@1595: DataItem[] items = extractDataItems(ele); ingo@1595: String rawValue = items[0].getStringValue(); ingo@1595: ingo@1595: String[] values = rawValue.split(";"); ingo@1595: double[] doubles = new double[values.length]; ingo@1595: ingo@1595: for (int i = 0; i < values.length; i++) { ingo@1595: try { ingo@1595: doubles[i] = Double.valueOf(values[i]); ingo@1595: } ingo@1595: catch (NumberFormatException nfe) { teichmann@8203: log.warn("Error while parsing DoubleArrayData: " + nfe); ingo@1595: } ingo@1595: } ingo@1595: ingo@2528: return new DoubleArrayData(name, label, doubles); ingo@1575: } ingo@1575: ingo@1575: ingo@1575: /** ingo@1571: * This method extracts the art:item elements placed under elements. ingo@1571: * ingo@1571: * @param element A data node that contains items. ingo@1571: * ingo@1571: * @return a list of DataItems. ingo@1571: */ ingo@1571: protected static DataItem[] extractDataItems(Element element) { ingo@1571: NodeList itemList = (NodeList) XMLUtils.xpath( ingo@1571: element, ingo@1571: "art:item", ingo@1571: XPathConstants.NODESET, ingo@1571: ArtifactNamespaceContext.INSTANCE); ingo@1571: ingo@1571: if (itemList == null || itemList.getLength() == 0) { teichmann@8203: log.debug("No data items found."); ingo@1571: return null; ingo@1571: } ingo@1571: ingo@1571: int count = itemList.getLength(); ingo@1571: ingo@1571: DataItem[] items = new DataItem[count]; ingo@1571: teichmann@8203: log.debug("There are " + count + " data items in element."); ingo@2532: ingo@1571: for (int i = 0; i < count; i++) { ingo@1571: Element tmp = (Element) itemList.item(i); ingo@1571: ingo@1571: String value = tmp.getAttributeNS(NS_URI, "value"); ingo@1571: String label = tmp.getAttributeNS(NS_URI, "label"); ingo@1571: teichmann@8203: log.debug("Found data item:"); teichmann@8203: log.debug(" label: " + label); teichmann@8203: log.debug(" value: " + value); ingo@2532: ingo@1571: items[i] = new DefaultDataItem(label, label, value); ingo@1571: } ingo@1571: ingo@1571: return items; ingo@1571: } raimund@2468: raimund@2468: raimund@2468: /** raimund@2535: * This method extracts the art:item elements placed under elements. raimund@2535: * raimund@2535: * @param element A data node that contains items. raimund@2535: * raimund@2535: * @return a list of DataItems. raimund@2535: */ raimund@2535: protected static IntDataItem[] extractIntDataItems(Element element) { raimund@2535: NodeList itemList = (NodeList) XMLUtils.xpath( raimund@2535: element, raimund@2535: "art:item", raimund@2535: XPathConstants.NODESET, raimund@2535: ArtifactNamespaceContext.INSTANCE); raimund@2535: raimund@2535: if (itemList == null || itemList.getLength() == 0) { teichmann@8203: log.debug("No old data items found."); raimund@2535: return null; raimund@2535: } raimund@2535: raimund@2535: int count = itemList.getLength(); raimund@2535: raimund@2535: IntDataItem[] items = new IntDataItem[count]; raimund@2535: raimund@2535: for (int i = 0; i < count; i++) { raimund@2535: Element tmp = (Element) itemList.item(i); raimund@2535: raimund@2535: String value = tmp.getAttributeNS(NS_URI, "value"); raimund@2535: String label = tmp.getAttributeNS(NS_URI, "label"); raimund@2535: raimund@2535: try { raimund@2535: int data = Integer.parseInt(value); raimund@2535: items[i] = new IntDataItem(label, label, data); raimund@2535: } raimund@2535: catch(NumberFormatException nfe) { teichmann@8203: log.debug(nfe, nfe); raimund@2535: } raimund@2535: } raimund@2535: return items; raimund@2535: } raimund@2535: raimund@2535: /** raimund@2468: * This method creates a new instance of LongRangeData which has a type raimund@2468: * "longrange" set. raimund@2468: * raimund@2468: * @param ele The Data element. raimund@2468: * @param name The name of the Data instance. raimund@2468: * raimund@2468: * @return an instance of IntegerRangeData. raimund@2468: */ tom@8856: protected static Data createLongRangeData( tom@8856: Element ele, tom@8856: String name, tom@8856: String label tom@8856: ) { raimund@2468: DataItem[] items = extractDataItems(ele); raimund@2468: String rawValue = items[0].getStringValue(); raimund@2468: raimund@2468: String[] minmax = rawValue.split(";"); raimund@2468: raimund@2468: return new LongRangeData( raimund@2468: name, ingo@2528: label, raimund@2468: Long.valueOf(minmax[0]), raimund@2468: Long.valueOf(minmax[1])); raimund@2468: } raimund@2468: ingo@1571: } ingo@1571: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :