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@16: ingo@16: import java.util.ArrayList; ingo@16: import java.util.List; ingo@16: ingo@16: import javax.xml.xpath.XPathConstants; ingo@16: ingo@1367: import org.apache.log4j.Logger; teichmann@5835: import org.dive4elements.artifacts.common.ArtifactNamespaceContext; teichmann@5835: import org.dive4elements.artifacts.common.utils.ClientProtocolUtils; teichmann@5835: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@5835: import org.dive4elements.river.client.shared.model.ArtifactDescription; teichmann@5835: import org.dive4elements.river.client.shared.model.DataItem; teichmann@5835: import org.dive4elements.river.client.shared.model.DataList; teichmann@5835: import org.dive4elements.river.client.shared.model.DefaultArtifactDescription; 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.DefaultOutputMode; teichmann@5835: import org.dive4elements.river.client.shared.model.DoubleArrayData; teichmann@5835: import org.dive4elements.river.client.shared.model.DoubleRangeData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntegerArrayData; gernotbelger@9390: import org.dive4elements.river.client.shared.model.IntegerOptionsData; teichmann@5835: import org.dive4elements.river.client.shared.model.IntegerRangeData; teichmann@5835: import org.dive4elements.river.client.shared.model.LongRangeData; teichmann@5835: import org.dive4elements.river.client.shared.model.OutputMode; teichmann@5835: import org.dive4elements.river.client.shared.model.Recommendation; teichmann@5835: import org.dive4elements.river.client.shared.model.WQDataItem; gernotbelger@9390: import org.w3c.dom.Document; gernotbelger@9390: import org.w3c.dom.Element; gernotbelger@9390: import org.w3c.dom.Node; gernotbelger@9390: import org.w3c.dom.NodeList; ingo@16: ingo@16: /** ingo@16: * This factory class helps creating an {@link ArtifactDescription} based on the ingo@16: * DESCRIBE document of an artifact returned by the artifact server. Use the ingo@16: * {@link createArtifactDescription(org.w3c.dom.Document)} method with the ingo@16: * DESCRIBE document to create such an {@link ArtifactDescription}. ingo@16: * ingo@16: * @author Ingo Weinzierl ingo@16: */ ingo@16: public class ArtifactDescriptionFactory { ingo@16: gernotbelger@9390: private static final Logger log = Logger.getLogger(ArtifactDescriptionFactory.class); ingo@1367: ingo@16: public static final String XPATH_STATE_NAME = "@art:name"; ingo@16: ingo@22: public static final String XPATH_UIPROVIDER = "@art:uiprovider"; ingo@22: ingo@2500: public static final String XPATH_HELP_TEXT = "@art:helpText"; ingo@2500: ingo@32: public static final String XPATH_REACHABLE_STATE = "art:state"; ingo@32: ingo@51: public static final String XPATH_STATIC_STATE_NODE = "art:state"; ingo@51: ingo@34: public static final String XPATH_STATIC_DATA_NODE = "art:data"; ingo@34: ingo@34: public static final String XPATH_STATIC_ITEM_NODE = "art:item"; ingo@34: gernotbelger@9390: public static final String XPATH_RECOMMENDED_ARTIFACTS = "/art:result/art:recommended-artifacts//*[@factory]"; ingo@803: ingo@16: /** ingo@16: * This method creates the {@link ArtifactDescription} of the DESCRIBE ingo@16: * document doc. ingo@16: * gernotbelger@9390: * @param doc gernotbelger@9390: * A DESCRIBE document. ingo@16: * ingo@16: * @return the {@link ArtifactDescription}. ingo@16: */ gernotbelger@9390: public static ArtifactDescription createArtifactDescription(final Document doc) { teichmann@8203: log.debug("ArtifactDescriptionFactory.createArtifactDescription"); ingo@16: gernotbelger@9390: final Node currentState = ClientProtocolUtils.getCurrentState(doc); gernotbelger@9390: final Node staticNode = ClientProtocolUtils.getStaticUI(doc); gernotbelger@9390: final Node dynamicNode = ClientProtocolUtils.getDynamicUI(doc); gernotbelger@9390: final Node reachable = ClientProtocolUtils.getReachableStates(doc); gernotbelger@9390: final NodeList outputs = ClientProtocolUtils.getOutputModes(doc); ingo@16: gernotbelger@9390: final String state = (String) XMLUtils.xpath(currentState, XPATH_STATE_NAME, XPathConstants.STRING, ArtifactNamespaceContext.INSTANCE); ingo@1367: teichmann@8203: log.debug("Current state name: " + state); ingo@16: gernotbelger@9390: final DataList currentData = extractCurrentData(dynamicNode, state); gernotbelger@9390: final DataList[] old = extractOldData(staticNode); gernotbelger@9390: final String[] states = extractReachableStates(reachable); gernotbelger@9390: final OutputMode[] outs = extractOutputModes(outputs); gernotbelger@9390: final Recommendation[] rec = extractRecommendedArtifacts(doc); ingo@16: gernotbelger@9390: return new DefaultArtifactDescription(old, currentData, state, states, outs, rec); ingo@16: } ingo@16: ingo@16: /** ingo@16: * This method extracts the data that the user is able to enter in the ingo@16: * current state of the artifact. ingo@16: * gernotbelger@9390: * @param dynamicNode gernotbelger@9390: * The dynamic node of the DESCRIBE document. gernotbelger@9390: * @param state gernotbelger@9390: * The name of the current state. ingo@16: * ingo@16: * @return A {@link Data} object that represents the data which might be gernotbelger@9390: * entered by the user in the current state or null, if no data might be gernotbelger@9390: * entered. ingo@16: */ gernotbelger@9390: protected static DataList extractCurrentData(final Node dynamicNode, final String state) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractCurrentData"); ingo@16: gernotbelger@9390: final NodeList data = ClientProtocolUtils.getSelectNode(dynamicNode); gernotbelger@9390: final String help = extractHelpText(dynamicNode); gernotbelger@9390: final String uiProvider = extractUIProvider(dynamicNode); ingo@16: ingo@51: if (data == null || data.getLength() == 0) { ingo@51: return null; ingo@51: } ingo@16: gernotbelger@9390: final int dataNum = data.getLength(); gernotbelger@9390: final DataList list = new DataList(state, dataNum, uiProvider, null, help); ingo@51: ingo@51: for (int i = 0; i < dataNum; i++) { gernotbelger@9390: final Element d = (Element) data.item(i); gernotbelger@9390: final String label = ClientProtocolUtils.getLabel(d); gernotbelger@9390: final String name = XMLUtils.xpathString(d, "@art:name", ArtifactNamespaceContext.INSTANCE); gernotbelger@9390: final String type = XMLUtils.xpathString(d, "@art:type", ArtifactNamespaceContext.INSTANCE); ingo@51: teichmann@8203: log.debug("Create new IntegerRangeData object for: " + name); teichmann@8203: log.debug("New Data is from type: " + type); ingo@51: felix@1592: // TODO replace with DataFactory. felix@1592: ingo@1522: if (type == null || type.length() == 0) { gernotbelger@9390: final NodeList choices = ClientProtocolUtils.getItemNodes(d); gernotbelger@9390: final DataItem[] dataItems = extractCurrentDataItems(choices); gernotbelger@9390: final DataItem def = extractDefaultDataItem(d); ingo@51: ingo@1522: list.add(new DefaultData(name, label, null, dataItems, def)); gernotbelger@9390: } else if (type.equals("intrange")) { gernotbelger@9390: final String min = ClientProtocolUtils.getMinNode(d); gernotbelger@9390: final String max = ClientProtocolUtils.getMaxNode(d); ingo@1566: gernotbelger@9390: final String defMin = ClientProtocolUtils.getDefMin(d); gernotbelger@9390: final String defMax = ClientProtocolUtils.getDefMax(d); ingo@1522: ingo@1522: try { gernotbelger@9390: final int lower = Integer.parseInt(min); gernotbelger@9390: final int upper = Integer.parseInt(max); ingo@4132: ingo@4132: if (defMin != null && defMax != null) { gernotbelger@9390: list.add(new IntegerRangeData(name, label, lower, upper, Integer.parseInt(defMin), Integer.parseInt(defMax))); gernotbelger@9390: } else { gernotbelger@9390: list.add(new IntegerRangeData(name, label, lower, upper)); ingo@4132: } ingo@4132: } gernotbelger@9390: catch (final NumberFormatException nfe) { teichmann@8203: log.warn("NumberFormatException: ", nfe); ingo@4132: } gernotbelger@9390: } else if (type.equals("longrange")) { gernotbelger@9390: final String min = ClientProtocolUtils.getMinNode(d); gernotbelger@9390: final String max = ClientProtocolUtils.getMaxNode(d); gernotbelger@9390: gernotbelger@9390: final String defMin = ClientProtocolUtils.getDefMin(d); gernotbelger@9390: final String defMax = ClientProtocolUtils.getDefMax(d); gernotbelger@9390: gernotbelger@9390: try { gernotbelger@9390: final long lower = Long.valueOf(min); gernotbelger@9390: final long upper = Long.valueOf(max); gernotbelger@9390: gernotbelger@9390: if (defMin != null && defMax != null) { gernotbelger@9390: list.add(new LongRangeData(name, label, lower, upper, Long.valueOf(defMin), Long.valueOf(defMax))); gernotbelger@9390: } gernotbelger@9390: } gernotbelger@9390: catch (final NumberFormatException nfe) { gernotbelger@9390: log.warn("NumberFormatException: ", nfe); gernotbelger@9390: } gernotbelger@9390: } else if (type.equals("intarray")) { ingo@1527: list.add(new IntegerArrayData(name, label, null)); gernotbelger@9390: } else if (type.equals("intoptions") && uiProvider.startsWith("parameter-matrix")// uiProvider.equals("parameter-matrix") // what the...? used to be gernotbelger@9390: // "equals", but column-name for "itemname" refactoring created new gernotbelger@9390: // UIProviderFactory-Names starting with "parameter-matrix" tom@8856: ) { ingo@2532: list.add(DataFactory.createIntegerOptionsData(d, name, label)); gernotbelger@9390: } else if (type.equals("options")) { ingo@2532: list.add(DataFactory.createStringOptionsData(d, name, label)); gernotbelger@9390: } else if (type.equals("intoptions")) { gernotbelger@9390: final NodeList choices = ClientProtocolUtils.getItemNodes(d); gernotbelger@9390: final DataItem[] opts = extractCurrentDataItems(choices); ingo@1527: ingo@1527: list.add(new IntegerOptionsData(name, label, opts)); gernotbelger@9390: } else if (type.equals("doublearray")) { ingo@1595: list.add(new DoubleArrayData(name, label, null)); gernotbelger@9390: } else if (type.equals("multiattribute")) { rrenkert@7825: list.add(DataFactory.createMultiAttributeData(d, name, label)); gernotbelger@9390: } else { teichmann@8203: log.warn("Unrecognized Dynamic data type."); gernotbelger@9390: final NodeList choices = ClientProtocolUtils.getItemNodes(d); gernotbelger@9390: final DataItem[] dataItems = extractCurrentDataItems(choices); gernotbelger@9390: final DataItem def = extractDefaultDataItem(d); felix@1592: gernotbelger@9390: final String min = ClientProtocolUtils.getMinNode(d); gernotbelger@9390: final String max = ClientProtocolUtils.getMaxNode(d); felix@1593: if (min != null && max != null) { gernotbelger@9390: list.add(new DoubleRangeData(name, label, Double.valueOf(min), Double.valueOf(max), Double.valueOf(min), Double.valueOf(max))); felix@1593: } felix@1593: felix@1592: list.add(new DefaultData(name, label, null, dataItems, def)); felix@1592: } felix@1592: ingo@51: } ingo@51: ingo@51: return list; ingo@16: } ingo@16: ingo@16: /** ingo@515: * This method extracts the default value of a Data object. ingo@515: * gernotbelger@9390: * @param data gernotbelger@9390: * The data object node. ingo@515: * ingo@515: * @return the default DataItem. ingo@515: */ gernotbelger@9390: protected static DataItem extractDefaultDataItem(final Node data) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractDefaultDataItem"); ingo@515: gernotbelger@9390: final String value = XMLUtils.xpathString(data, "@art:defaultValue", ArtifactNamespaceContext.INSTANCE); ingo@515: gernotbelger@9390: final String label = XMLUtils.xpathString(data, "@art:defaultLabel", ArtifactNamespaceContext.INSTANCE); ingo@515: ingo@515: if (value != null && label != null) { ingo@515: return new DefaultDataItem(label, null, value); ingo@515: } ingo@515: ingo@515: return null; ingo@515: } ingo@515: ingo@515: /** ingo@16: * This method extract the {@link DataItem}s of the DESCRIBE document. ingo@16: * gernotbelger@9390: * @param items gernotbelger@9390: * The items in the DESCRIBE document. ingo@16: * ingo@16: * @return the {@link DataItem}s. ingo@16: */ gernotbelger@9390: protected static DataItem[] extractCurrentDataItems(final NodeList items) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractCurrentDataItems"); ingo@16: ingo@16: if (items == null || items.getLength() == 0) { teichmann@8203: log.debug("No data items found."); ingo@16: return null; ingo@16: } ingo@16: gernotbelger@9390: final int count = items.getLength(); ingo@16: gernotbelger@9390: final List dataItems = new ArrayList(count); ingo@16: ingo@16: for (int i = 0; i < count; i++) { gernotbelger@9390: final Node item = items.item(i); gernotbelger@9390: final String label = ClientProtocolUtils.getLabel(item); gernotbelger@9390: final String value = ClientProtocolUtils.getValue(item); ingo@16: gernotbelger@9390: final double[] mmQ = extractMinMaxQValues(item); gernotbelger@9390: final double[] mmW = extractMinMaxWValues(item); ingo@565: ingo@565: if (mmQ != null || mmW != null) { ingo@565: dataItems.add(new WQDataItem(label, null, value, mmQ, mmW)); gernotbelger@9390: } else { ingo@565: dataItems.add(new DefaultDataItem(label, null, value)); ingo@565: } ingo@16: } ingo@16: sascha@3379: return dataItems.toArray(new DataItem[count]); ingo@16: } ingo@22: gernotbelger@9390: protected static double[] extractMinMaxQValues(final Node item) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractMinMaxQValues"); ingo@565: ingo@565: if (item == null) { teichmann@8203: log.debug("This node is empty - no min/max Q values."); ingo@565: return null; ingo@565: } ingo@565: gernotbelger@9390: final Node node = (Node) XMLUtils.xpath(item, "art:range[@art:type='Q']", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); ingo@565: ingo@565: if (node == null) { teichmann@8203: log.debug("No min/max Q values found."); ingo@565: return null; ingo@565: } ingo@565: ingo@565: return extractMinMaxValues(node); ingo@565: } ingo@565: gernotbelger@9390: protected static double[] extractMinMaxWValues(final Node item) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractMinMaxWValues"); ingo@565: ingo@565: if (item == null) { teichmann@8203: log.debug("This node is empty - no min/max W values."); ingo@565: return null; ingo@565: } ingo@565: gernotbelger@9390: final Node node = (Node) XMLUtils.xpath(item, "art:range[@art:type='W']", XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE); ingo@565: ingo@565: if (node == null) { teichmann@8203: log.debug("No min/max W values found."); ingo@565: return null; ingo@565: } ingo@565: ingo@565: return extractMinMaxValues(node); ingo@565: } ingo@565: gernotbelger@9390: protected static double[] extractMinMaxValues(final Node node) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractMinMaxValues"); ingo@565: gernotbelger@9390: final String minStr = XMLUtils.xpathString(node, "art:min/text()", ArtifactNamespaceContext.INSTANCE); ingo@565: gernotbelger@9390: final String maxStr = XMLUtils.xpathString(node, "art:max/text()", ArtifactNamespaceContext.INSTANCE); ingo@565: ingo@565: if (maxStr == null || minStr == null) { teichmann@8203: log.debug("No min/max values found."); ingo@565: return null; ingo@565: } ingo@565: ingo@565: try { gernotbelger@9390: final double min = Double.valueOf(minStr); gernotbelger@9390: final double max = Double.valueOf(maxStr); ingo@565: ingo@565: return new double[] { min, max }; ingo@565: } gernotbelger@9390: catch (final NumberFormatException nfe) { teichmann@8203: log.debug("Error while parsing min/max values."); ingo@565: } ingo@565: ingo@565: return null; ingo@565: } ingo@565: ingo@22: /** ingo@34: * This method extracts the data objects from the data node of the static ui ingo@34: * part of the DESCRIBE document. ingo@34: * gernotbelger@9390: * @param staticNode gernotbelger@9390: * The static ui node of the DESCRIBE. ingo@34: * ingo@51: * @return the DataList objects. ingo@34: */ gernotbelger@9390: protected static DataList[] extractOldData(final Node staticNode) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractOldData()"); ingo@34: gernotbelger@9390: final NodeList stateNodes = (NodeList) XMLUtils.xpath(staticNode, XPATH_STATIC_STATE_NODE, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); ingo@34: ingo@51: if (stateNodes == null || stateNodes.getLength() == 0) { teichmann@8203: log.debug("No old items found."); ingo@34: return null; ingo@34: } ingo@34: gernotbelger@9390: final int count = stateNodes.getLength(); gernotbelger@9390: final DataList[] data = new DataList[count]; ingo@34: ingo@34: for (int i = 0; i < count; i++) { gernotbelger@9390: final Node tmp = stateNodes.item(i); ingo@34: gernotbelger@9390: final String name = XMLUtils.xpathString(tmp, "@art:name", ArtifactNamespaceContext.INSTANCE); gernotbelger@9390: final String uiprovider = XMLUtils.xpathString(tmp, "@art:uiprovider", ArtifactNamespaceContext.INSTANCE); gernotbelger@9390: final String label = XMLUtils.xpathString(tmp, "@art:label", ArtifactNamespaceContext.INSTANCE); gernotbelger@9390: final String help = XMLUtils.xpathString(tmp, "@art:helpText", ArtifactNamespaceContext.INSTANCE); ingo@34: gernotbelger@9390: final NodeList dataNodes = (NodeList) XMLUtils.xpath(tmp, XPATH_STATIC_DATA_NODE, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); ingo@34: ingo@51: if (dataNodes == null || dataNodes.getLength() == 0) { ingo@51: continue; ingo@51: } ingo@51: gernotbelger@9390: final int size = dataNodes.getLength(); gernotbelger@9390: final DataList list = new DataList(name, size, uiprovider, label, help); ingo@51: ingo@51: for (int j = 0; j < size; j++) { gernotbelger@9390: final Node dataNode = dataNodes.item(j); ingo@51: ingo@1571: list.add(DataFactory.createDataFromElement((Element) dataNode)); ingo@51: ingo@51: data[i] = list; ingo@51: } ingo@34: } ingo@34: ingo@34: return data; ingo@34: } ingo@34: ingo@34: /** ingo@22: * This method extracts the UIProvider specified by the data node. ingo@22: * gernotbelger@9390: * @param data gernotbelger@9390: * The data node. ingo@22: * ingo@22: * @return the UIProvider that is specified in the data node. ingo@22: */ gernotbelger@9390: protected static String extractUIProvider(final Node ui) { gernotbelger@9390: return (String) XMLUtils.xpath(ui, XPATH_UIPROVIDER, XPathConstants.STRING, ArtifactNamespaceContext.INSTANCE); ingo@22: } ingo@32: ingo@32: /** ingo@2500: * This method extracts the help text specified by the data node. ingo@2500: * gernotbelger@9390: * @param ui gernotbelger@9390: * The data node. ingo@2500: * ingo@2500: * @return the help text. ingo@2500: */ gernotbelger@9390: protected static String extractHelpText(final Node ui) { gernotbelger@9390: return (String) XMLUtils.xpath(ui, XPATH_HELP_TEXT, XPathConstants.STRING, ArtifactNamespaceContext.INSTANCE); ingo@2500: } ingo@2500: ingo@2500: /** ingo@32: * This method extracts the reachable states of the current artifact. ingo@32: * gernotbelger@9390: * @param reachable gernotbelger@9390: * The reachable states node. ingo@32: * ingo@32: * @return an array with identifiers of reachable states. ingo@32: */ gernotbelger@9390: protected static String[] extractReachableStates(final Node reachable) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractReachableStates()"); ingo@32: gernotbelger@9390: final NodeList list = (NodeList) XMLUtils.xpath(reachable, XPATH_REACHABLE_STATE, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); ingo@32: ingo@32: if (list == null || list.getLength() == 0) { ingo@32: return null; ingo@32: } ingo@32: gernotbelger@9390: final int count = list.getLength(); ingo@32: gernotbelger@9390: final String[] states = new String[count]; ingo@32: ingo@32: for (int i = 0; i < count; i++) { gernotbelger@9390: final Node state = list.item(i); ingo@32: gernotbelger@9390: final String name = XMLUtils.xpathString(state, "@art:name", ArtifactNamespaceContext.INSTANCE); ingo@32: ingo@32: states[i] = name; ingo@32: } ingo@32: ingo@32: return states; ingo@32: } ingo@65: ingo@65: /** ingo@65: * This method extract available output modes of the the current artifact. ingo@65: * gernotbelger@9390: * @param outputs gernotbelger@9390: * A list of nodes that contain information about output gernotbelger@9390: * modes. ingo@65: * ingo@65: * @return an array of Output modes. ingo@65: */ gernotbelger@9390: protected static OutputMode[] extractOutputModes(final NodeList outputs) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractOutputModes"); ingo@65: ingo@65: if (outputs == null || outputs.getLength() == 0) { ingo@65: return null; ingo@65: } ingo@65: gernotbelger@9390: final int size = outputs.getLength(); ingo@65: gernotbelger@9390: final List outs = new ArrayList(size); ingo@65: ingo@65: for (int i = 0; i < size; i++) { gernotbelger@9390: final Node out = outputs.item(i); ingo@65: gernotbelger@9390: final String name = XMLUtils.xpathString(out, "@art:name", ArtifactNamespaceContext.INSTANCE); gernotbelger@9390: final String desc = XMLUtils.xpathString(out, "@art:description", ArtifactNamespaceContext.INSTANCE); gernotbelger@9390: final String mimeType = XMLUtils.xpathString(out, "@art:mime-type", ArtifactNamespaceContext.INSTANCE); ingo@65: ingo@65: if (name != null) { ingo@65: outs.add(new DefaultOutputMode(name, desc, mimeType)); gernotbelger@9390: } else { teichmann@8203: log.debug("Found an invalid output mode."); ingo@65: } ingo@65: } ingo@65: gernotbelger@9390: return outs.toArray(new OutputMode[size]); ingo@65: } ingo@803: gernotbelger@9390: protected static Recommendation[] extractRecommendedArtifacts(final Document doc) { teichmann@8203: log.debug("ArtifactDescriptionFactory.extractRecommendedArtifacts."); ingo@803: gernotbelger@9390: final NodeList list = (NodeList) XMLUtils.xpath(doc, XPATH_RECOMMENDED_ARTIFACTS, XPathConstants.NODESET, ArtifactNamespaceContext.INSTANCE); ingo@803: gernotbelger@9390: final int num = list != null ? list.getLength() : 0; ingo@803: gernotbelger@9390: final Recommendation[] rec = new Recommendation[num]; ingo@803: ingo@803: for (int i = 0; i < num; i++) { gernotbelger@9390: final Element e = (Element) list.item(i); gernotbelger@9390: final String factory = e.getAttribute("factory"); gernotbelger@9390: final String index = e.getAttribute("ids"); gernotbelger@9390: final String targetOut = e.getAttribute("target_out"); ingo@803: ingo@807: if (factory != null && factory.length() > 0) { gernotbelger@9390: log.debug("Adding Recommendation. Factory: " + factory + " IDs: " + index + " target out " + targetOut); gernotbelger@9390: rec[i] = new Recommendation(factory, index, null, null, targetOut); ingo@803: } ingo@803: } ingo@803: ingo@807: return rec; ingo@803: } ingo@16: } ingo@16: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :