Mercurial > dive4elements > river
view flys-client/src/main/java/de/intevation/flys/client/server/ArtifactDescriptionFactory.java @ 1575:0f2b94408bd1
Added further methods to DataFactory to create concrete Data instances.
flys-client/trunk@3841 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Tue, 31 Jan 2012 15:20:17 +0000 |
parents | 1227878665b5 |
children | f34bbb5fb6d2 |
line wrap: on
line source
package de.intevation.flys.client.server; import java.util.ArrayList; import java.util.List; import javax.xml.xpath.XPathConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.apache.log4j.Logger; import de.intevation.artifacts.common.ArtifactNamespaceContext; import de.intevation.artifacts.common.utils.ClientProtocolUtils; import de.intevation.artifacts.common.utils.XMLUtils; import de.intevation.flys.client.shared.model.ArtifactDescription; import de.intevation.flys.client.shared.model.DataItem; import de.intevation.flys.client.shared.model.DataList; import de.intevation.flys.client.shared.model.DefaultArtifactDescription; import de.intevation.flys.client.shared.model.DefaultData; import de.intevation.flys.client.shared.model.DefaultDataItem; import de.intevation.flys.client.shared.model.DefaultOutputMode; import de.intevation.flys.client.shared.model.IntegerArrayData; import de.intevation.flys.client.shared.model.IntegerRangeData; import de.intevation.flys.client.shared.model.IntegerOptionsData; import de.intevation.flys.client.shared.model.OutputMode; import de.intevation.flys.client.shared.model.Recommendation; import de.intevation.flys.client.shared.model.WQDataItem; /** * This factory class helps creating an {@link ArtifactDescription} based on the * DESCRIBE document of an artifact returned by the artifact server. Use the * {@link createArtifactDescription(org.w3c.dom.Document)} method with the * DESCRIBE document to create such an {@link ArtifactDescription}. * * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public class ArtifactDescriptionFactory { private static final Logger logger = Logger.getLogger(ArtifactDescriptionFactory.class); public static final String XPATH_STATE_NAME = "@art:name"; public static final String XPATH_UIPROVIDER = "@art:uiprovider"; public static final String XPATH_REACHABLE_STATE = "art:state"; public static final String XPATH_STATIC_STATE_NODE = "art:state"; public static final String XPATH_STATIC_DATA_NODE = "art:data"; public static final String XPATH_STATIC_ITEM_NODE = "art:item"; public static final String XPATH_RECOMMENDED_ARTIFACTS = "/art:result/art:recommended-artifacts//*[@factory]"; /** * This method creates the {@link ArtifactDescription} of the DESCRIBE * document <i>doc</i>. * * @param doc A DESCRIBE document. * * @return the {@link ArtifactDescription}. */ public static ArtifactDescription createArtifactDescription(Document doc) { logger.debug("ArtifactDescriptionFactory.createArtifactDescription"); Node currentState = ClientProtocolUtils.getCurrentState(doc); Node staticNode = ClientProtocolUtils.getStaticUI(doc); Node dynamicNode = ClientProtocolUtils.getDynamicUI(doc); Node reachable = ClientProtocolUtils.getReachableStates(doc); NodeList outputs = ClientProtocolUtils.getOutputModes(doc); String state = (String) XMLUtils.xpath( currentState, XPATH_STATE_NAME, XPathConstants.STRING, ArtifactNamespaceContext.INSTANCE); logger.debug("Current state name: " + state); DataList currentData = extractCurrentData(dynamicNode, state); DataList[] old = extractOldData(staticNode); String[] states = extractReachableStates(reachable); OutputMode[] outs = extractOutputModes(outputs); Recommendation[] rec = extractRecommendedArtifacts(doc); return new DefaultArtifactDescription( old, currentData, state, states, outs, rec); } /** * This method extracts the data that the user is able to enter in the * current state of the artifact. * * @param dynamicNode The dynamic node of the DESCRIBE document. * @param state The name of the current state. * * @return A {@link Data} object that represents the data which might be * entered by the user in the current state or null, if no data might be * entered. */ protected static DataList extractCurrentData(Node dynamicNode, String state) { logger.debug("ArtifactDescriptionFactory.extractCurrentData"); NodeList data = ClientProtocolUtils.getSelectNode(dynamicNode); String uiProvider = extractUIProvider(dynamicNode); if (data == null || data.getLength() == 0) { return null; } int dataNum = data.getLength(); DataList list = new DataList(state, dataNum, uiProvider); for (int i = 0; i < dataNum; i++) { Element d = (Element) data.item(i); String label = ClientProtocolUtils.getLabel(d); String name = XMLUtils.xpathString( d, "@art:name", ArtifactNamespaceContext.INSTANCE); String type = XMLUtils.xpathString( d, "@art:type", ArtifactNamespaceContext.INSTANCE); logger.debug("Create new IntegerRangeData object for: " + name); logger.debug("New Data is from type: " + type); if (type == null || type.length() == 0) { NodeList choices = ClientProtocolUtils.getItemNodes(d); DataItem[] dataItems = extractCurrentDataItems(choices); DataItem def = extractDefaultDataItem(d); list.add(new DefaultData(name, label, null, dataItems, def)); } else if (type.equals("intrange")) { String min = ClientProtocolUtils.getMinNode(d); String max = ClientProtocolUtils.getMaxNode(d); String defMin = ClientProtocolUtils.getDefMin(d); String defMax = ClientProtocolUtils.getDefMax(d); try { int lower = Integer.parseInt(min); int upper = Integer.parseInt(max); if (defMin != null && defMax != null) { list.add(new IntegerRangeData( name, label, lower, upper, Integer.parseInt(defMin), Integer.parseInt(defMax))); } else { list.add( new IntegerRangeData(name, label, lower, upper)); } } catch (NumberFormatException nfe) { logger.warn("NumberFormatException: ", nfe); } } else if (type.equals("intarray")) { list.add(new IntegerArrayData(name, label, null)); } else if (type.equals("intoptions")) { NodeList choices = ClientProtocolUtils.getItemNodes(d); DataItem[] opts = extractCurrentDataItems(choices); list.add(new IntegerOptionsData(name, label, opts)); } } return list; } /** * This method extracts the default value of a Data object. * * @param data The data object node. * * @return the default DataItem. */ protected static DataItem extractDefaultDataItem(Node data) { logger.debug("ArtifactDescriptionFactory.extractDefaultDataItem"); String value = XMLUtils.xpathString( data, "@art:defaultValue", ArtifactNamespaceContext.INSTANCE); String label = XMLUtils.xpathString( data, "@art:defaultLabel", ArtifactNamespaceContext.INSTANCE); if (value != null && label != null) { return new DefaultDataItem(label, null, value); } return null; } /** * This method extract the {@link DataItem}s of the DESCRIBE document. * * @param items The items in the DESCRIBE document. * * @return the {@link DataItem}s. */ protected static DataItem[] extractCurrentDataItems(NodeList items) { logger.debug("ArtifactDescriptionFactory.extractCurrentDataItems"); if (items == null || items.getLength() == 0) { logger.debug("No data items found."); return null; } int count = items.getLength(); List<DataItem> dataItems = new ArrayList<DataItem>(count); for (int i = 0; i < count; i++) { Node item = items.item(i); String label = ClientProtocolUtils.getLabel(item); String value = ClientProtocolUtils.getValue(item); double[] mmQ = extractMinMaxQValues(item); double[] mmW = extractMinMaxWValues(item); if (mmQ != null || mmW != null) { dataItems.add(new WQDataItem(label, null, value, mmQ, mmW)); } else { dataItems.add(new DefaultDataItem(label, null, value)); } } return (DataItem[]) dataItems.toArray(new DataItem[count]); } protected static double[] extractMinMaxQValues(Node item) { logger.debug("ArtifactDescriptionFactory.extractMinMaxQValues"); if (item == null) { logger.debug("This node is empty - no min/max Q values."); return null; } Node node = (Node) XMLUtils.xpath( item, "art:range[@art:type='Q']", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); if (node == null) { logger.debug("No min/max Q values found."); return null; } return extractMinMaxValues(node); } protected static double[] extractMinMaxWValues(Node item) { logger.debug("ArtifactDescriptionFactory.extractMinMaxWValues"); if (item == null) { logger.debug("This node is empty - no min/max W values."); return null; } Node node = (Node) XMLUtils.xpath( item, "art:range[@art:type='W']", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); if (node == null) { logger.debug("No min/max W values found."); return null; } return extractMinMaxValues(node); } protected static double[] extractMinMaxValues(Node node) { logger.debug("ArtifactDescriptionFactory.extractMinMaxValues"); String minStr = XMLUtils.xpathString( node, "art:min/text()", ArtifactNamespaceContext.INSTANCE); String maxStr = XMLUtils.xpathString( node, "art:max/text()", ArtifactNamespaceContext.INSTANCE); if (maxStr == null || minStr == null) { logger.debug("No min/max values found."); return null; } try { double min = Double.valueOf(minStr); double max = Double.valueOf(maxStr); return new double[] { min, max }; } catch (NumberFormatException nfe) { logger.debug("Error while parsing min/max values."); } return null; } /** * This method extracts the data objects from the data node of the static ui * part of the DESCRIBE document. * * @param staticNode The static ui node of the DESCRIBE. * * @return the DataList objects. */ protected static DataList[] extractOldData(Node staticNode) { logger.debug("ArtifactDescriptionFactory.extractOldData()"); NodeList stateNodes = (NodeList) XMLUtils.xpath( staticNode, XPATH_STATIC_STATE_NODE, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); if (stateNodes == null || stateNodes.getLength() == 0) { logger.debug("No old items found."); return null; } int count = stateNodes.getLength(); DataList[] data = new DataList[count]; for (int i = 0; i < count; i++) { Node tmp = stateNodes.item(i); String name = XMLUtils.xpathString( tmp, "@art:name", ArtifactNamespaceContext.INSTANCE); String uiprovider = XMLUtils.xpathString( tmp, "@art:uiprovider", ArtifactNamespaceContext.INSTANCE); String label = XMLUtils.xpathString( tmp, "@art:label", ArtifactNamespaceContext.INSTANCE); NodeList dataNodes = (NodeList) XMLUtils.xpath( tmp, XPATH_STATIC_DATA_NODE, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); if (dataNodes == null || dataNodes.getLength() == 0) { continue; } int size = dataNodes.getLength(); DataList list = new DataList(name, size, uiprovider, label); for (int j = 0; j < size; j++) { Node dataNode = dataNodes.item(j); list.add(DataFactory.createDataFromElement((Element) dataNode)); data[i] = list; } } return data; } /** * This method extracts the UIProvider specified by the data node. * * @param data The data node. * * @return the UIProvider that is specified in the data node. */ protected static String extractUIProvider(Node ui) { return (String) XMLUtils.xpath( ui, XPATH_UIPROVIDER, XPathConstants.STRING, ArtifactNamespaceContext.INSTANCE); } /** * This method extracts the reachable states of the current artifact. * * @param reachable The reachable states node. * * @return an array with identifiers of reachable states. */ protected static String[] extractReachableStates(Node reachable) { logger.debug("ArtifactDescriptionFactory.extractReachableStates()"); NodeList list = (NodeList) XMLUtils.xpath( reachable, XPATH_REACHABLE_STATE, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); if (list == null || list.getLength() == 0) { return null; } int count = list.getLength(); String[] states = new String[count]; for (int i = 0; i < count; i++) { Node state = list.item(i); String name = XMLUtils.xpathString( state, "@art:name", ArtifactNamespaceContext.INSTANCE); states[i] = name; } return states; } /** * This method extract available output modes of the the current artifact. * * @param outputs A list of nodes that contain information about output * modes. * * @return an array of Output modes. */ protected static OutputMode[] extractOutputModes(NodeList outputs) { logger.debug("ArtifactDescriptionFactory.extractOutputModes"); if (outputs == null || outputs.getLength() == 0) { return null; } int size = outputs.getLength(); List<OutputMode> outs = new ArrayList<OutputMode>(size); for (int i = 0; i < size; i++) { Node out = outputs.item(i); String name = XMLUtils.xpathString( out, "@art:name", ArtifactNamespaceContext.INSTANCE); String desc = XMLUtils.xpathString( out, "@art:description", ArtifactNamespaceContext.INSTANCE); String mimeType = XMLUtils.xpathString( out, "@art:mime-type", ArtifactNamespaceContext.INSTANCE); if (name != null) { outs.add(new DefaultOutputMode(name, desc, mimeType)); } else { logger.debug("Found an invalid output mode."); } } return (OutputMode[]) outs.toArray(new OutputMode[size]); } protected static Recommendation[] extractRecommendedArtifacts(Document doc){ logger.debug("ArtifactDescriptionFactory.extractRecommendedArtifacts."); NodeList list = (NodeList) XMLUtils.xpath( doc, XPATH_RECOMMENDED_ARTIFACTS, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); int num = list != null ? list.getLength() : 0; Recommendation[] rec = new Recommendation[num]; for (int i = 0; i < num; i++) { Element e = (Element) list.item(i); String factory = e.getAttribute("factory"); String index = e.getAttribute("ids"); if (factory != null && factory.length() > 0) { rec[i] = new Recommendation(factory, index); } } return rec; } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :