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 :