teichmann@5863: /* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde teichmann@5863: * Software engineering by Intevation GmbH teichmann@5863: * teichmann@5994: * This file is Free Software under the GNU AGPL (>=v3) teichmann@5863: * and comes with ABSOLUTELY NO WARRANTY! Check out the teichmann@5994: * documentation coming with Dive4Elements River for details. teichmann@5863: */ teichmann@5863: teichmann@5831: package org.dive4elements.river.artifacts.states; ingo@126: ingo@669: import java.text.NumberFormat; gernotbelger@9277: import java.util.List; ingo@669: import java.util.Locale; ingo@126: import java.util.Map; ingo@126: ingo@126: import org.apache.log4j.Logger; gernotbelger@9277: import org.dive4elements.artifactdatabase.ProtocolUtils; gernotbelger@9277: import org.dive4elements.artifactdatabase.data.StateData; gernotbelger@9277: import org.dive4elements.artifactdatabase.state.AbstractState; gernotbelger@9277: import org.dive4elements.artifactdatabase.state.Facet; teichmann@5831: import org.dive4elements.artifacts.Artifact; teichmann@5831: import org.dive4elements.artifacts.ArtifactNamespaceContext; teichmann@5831: import org.dive4elements.artifacts.CallContext; teichmann@5831: import org.dive4elements.artifacts.CallMeta; teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils; teichmann@5831: import org.dive4elements.artifacts.common.utils.XMLUtils.ElementCreator; teichmann@5867: import org.dive4elements.river.artifacts.D4EArtifact; teichmann@5831: import org.dive4elements.river.artifacts.resources.Resources; gernotbelger@9277: import org.w3c.dom.Document; gernotbelger@9277: import org.w3c.dom.Element; gernotbelger@9277: import org.w3c.dom.Node; ingo@126: ingo@126: /** ingo@126: * @author Ingo Weinzierl ingo@126: */ rrenkert@8275: public class DefaultState extends AbstractState { ingo@126: teichmann@8202: /** The log that is used in this class. */ teichmann@8202: private static Logger log = Logger.getLogger(DefaultState.class); ingo@126: felix@1768: /** The three possible compute types. */ sascha@697: public static enum ComputeType { ingo@942: FEED, ADVANCE, INIT sascha@697: } ingo@126: gernotbelger@9277: protected StateData getData(final D4EArtifact artifact, final String name) { ingo@624: return artifact.getData(name); ingo@624: } ingo@624: felix@1136: /** felix@1136: * Append to a node and return xml description relevant for gui. felix@1136: */ gernotbelger@9277: public Element describeStatic(final Artifact artifact, final Document document, final Node root, final CallContext context, final String uuid) { gernotbelger@9277: final ElementCreator creator = new ElementCreator(document, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX); ingo@134: gernotbelger@9277: final CallMeta meta = context.getMeta(); ingo@142: teichmann@5909: String helpText = getHelpText(); teichmann@5909: if (helpText != null) { gernotbelger@9277: helpText = replaceHelpUrl(Resources.getMsg(meta, helpText, helpText)); teichmann@5909: } ingo@2661: gernotbelger@9277: final String label = Resources.getMsg(meta, getID(), getID()); gernotbelger@9277: final Element ui = ProtocolUtils.createArtNode(creator, "state", new String[] { "name", "uiprovider", "label", "helpText" }, gernotbelger@9277: new String[] { getID(), getUIProvider(), label, helpText }); ingo@134: gernotbelger@9277: final Map theData = getData(); ingo@134: if (theData == null) { ingo@134: return ui; ingo@134: } ingo@134: gernotbelger@9277: final D4EArtifact flys = (D4EArtifact) artifact; ingo@134: gernotbelger@9277: for (final String name : theData.keySet()) { ingo@1180: appendStaticData(flys, context, creator, ui, name); ingo@134: } ingo@134: ingo@134: return ui; ingo@134: } ingo@134: gernotbelger@9277: protected void appendStaticData(final D4EArtifact flys, final CallContext context, final ElementCreator cr, final Element ui, final String name) { gernotbelger@9277: final StateData data = getData(flys, name); gernotbelger@9277: final String value = (data != null) ? (String) data.getValue() : null; ingo@1159: ingo@1159: if (value == null) { ingo@1159: return; ingo@1159: } ingo@1159: gernotbelger@9277: final String type = data.getType(); ingo@1159: teichmann@8202: if (log.isDebugEnabled()) { gernotbelger@9277: log.debug("Append element " + type + "'" + name + "' (" + value + ")"); sascha@3732: } ingo@2205: gernotbelger@9277: final Element e = createStaticData(flys, cr, context, name, value, type); ingo@1180: ingo@1180: ui.appendChild(e); ingo@1180: ingo@1180: } ingo@1180: ingo@1180: /** ingo@1180: * Creates a data element used in the static part of the DESCRIBE ingo@1180: * document. ingo@1180: * gernotbelger@9277: * @param creator gernotbelger@9277: * The ElementCreator that is used to build new Elements. gernotbelger@9277: * @param cc gernotbelger@9277: * The CallContext object used for nested i18n retrieval. gernotbelger@9277: * @param name gernotbelger@9277: * The name of the data item. gernotbelger@9277: * @param value gernotbelger@9277: * The value as string. ingo@1180: * ingo@1180: * @return an Element. ingo@1180: */ gernotbelger@9277: protected Element createStaticData(final D4EArtifact flys, final ElementCreator creator, final CallContext cc, final String name, final String value, gernotbelger@9277: final String type) { gernotbelger@9277: final Element dataElement = creator.create("data"); ingo@1159: creator.addAttr(dataElement, "name", name, true); ingo@1180: creator.addAttr(dataElement, "type", type, true); ingo@1159: gernotbelger@9277: final Element itemElement = creator.create("item"); ingo@1159: creator.addAttr(itemElement, "value", value, true); ingo@1159: gernotbelger@9277: creator.addAttr(itemElement, "label", getLabelFor(cc, name, value, type), true); ingo@2205: ingo@2205: dataElement.appendChild(itemElement); ingo@2205: ingo@2205: return dataElement; ingo@2205: } ingo@2205: ingo@2205: /** ingo@2205: * @param cc ingo@2205: * @param name ingo@2205: * @param value ingo@2205: * @param type ingo@2205: * ingo@2205: * @return ingo@2205: */ gernotbelger@9277: protected String getLabelFor(final CallContext cc, final String name, final String value, final String type) { gernotbelger@9277: final CallMeta meta = cc.getMeta(); ingo@2205: ingo@1159: try { ingo@1159: // XXX A better way to format the output would be to use the ingo@1159: // 'type' value of the data objects. gernotbelger@9277: final double doubleVal = Double.parseDouble(value); gernotbelger@9277: final Locale l = Resources.getLocale(meta); gernotbelger@9277: final NumberFormat nf = NumberFormat.getInstance(l); ingo@1159: ingo@2205: return nf.format(doubleVal); ingo@1159: } gernotbelger@9277: catch (final NumberFormatException nfe) { ingo@2205: return Resources.getMsg(meta, value, value); ingo@1159: } ingo@1159: } ingo@1159: ingo@3407: /** andre@8615: * This method returns the default value and label for data. andre@8615: * andre@8615: * Override this method in a subclass to set an appropiate default andre@8615: * value. andre@8615: * The default label can be ignored by the client (e.g. the gwt-client). andre@8615: * but shall not be null. andre@8615: * andre@8615: * Example implementation: gernotbelger@9277: * if (data != null && data.getName().equals("the_answer")) { gernotbelger@9277: * return new String[] {"42", "the_answer"}; gernotbelger@9277: * } andre@8615: * gernotbelger@9277: * @param context gernotbelger@9277: * The CallContext used for i18n. gernotbelger@9277: * @param data gernotbelger@9277: * The data objects that the defaults are for. ingo@3407: * @return a String[] with [default value, default label]. ingo@3407: */ gernotbelger@9277: protected String[] getDefaultsFor(final CallContext context, final StateData data) { ingo@3407: return null; ingo@3407: } ingo@3407: gernotbelger@9277: @Override gernotbelger@9277: public Element describe(final Artifact artifact, final Document document, final Node root, final CallContext context, final String uuid) { gernotbelger@9277: final ElementCreator creator = new ElementCreator(document, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX); ingo@126: aheinecke@6052: String helpText = getHelpText(); aheinecke@6052: if (helpText != null) { gernotbelger@9277: helpText = replaceHelpUrl(Resources.getMsg(context.getMeta(), helpText, helpText)); aheinecke@6052: } ingo@2661: gernotbelger@9277: Element ui = null; gernotbelger@9277: final String uiprovider = getUIProvider(); ingo@135: if (uiprovider != null) { gernotbelger@9277: ui = ProtocolUtils.createArtNode(creator, "dynamic", new String[] { "uiprovider", "helpText" }, new String[] { uiprovider, helpText }); gernotbelger@9277: } else { gernotbelger@9277: ui = ProtocolUtils.createArtNode(creator, "dynamic", new String[] { "helpText" }, new String[] { helpText }); ingo@135: } ingo@126: gernotbelger@9277: final Map theData = getData(); ingo@126: if (theData == null) { ingo@126: return ui; ingo@126: } ingo@126: gernotbelger@9277: final D4EArtifact flys = (D4EArtifact) artifact; ingo@126: gernotbelger@9277: for (final String name : theData.keySet()) { ingo@624: StateData data = getData(flys, name); ingo@624: sascha@3732: if (data == null) { sascha@3732: data = getData(name); sascha@3732: } ingo@624: gernotbelger@9277: final Element select = createData(creator, artifact, data, context); ingo@126: gernotbelger@9277: final String[] defaults = getDefaultsFor(context, data); ingo@3407: if (defaults != null && defaults.length > 1) { ingo@3407: creator.addAttr(select, "defaultValue", defaults[0], true); ingo@3407: creator.addAttr(select, "defaultLabel", defaults[1], true); ingo@630: } ingo@630: ingo@2189: appendItems(artifact, creator, name, context, select); ingo@126: ui.appendChild(select); ingo@126: } ingo@126: ingo@126: return ui; ingo@126: } ingo@126: ingo@126: /** ingo@2189: * @param artifact ingo@2189: * @param creator ingo@2189: * @param name ingo@2189: * @param context ingo@2189: * @param select ingo@2189: */ gernotbelger@9277: protected void appendItems(final Artifact artifact, final ElementCreator creator, final String name, final CallContext context, final Element select) { gernotbelger@9277: final Element choices = ProtocolUtils.createArtNode(creator, "choices", null, null); ingo@2189: ingo@2189: select.appendChild(choices); ingo@2189: gernotbelger@9277: final Element[] items = createItems(creator, artifact, name, context); ingo@2189: if (items != null) { gernotbelger@9277: for (final Element item : items) { ingo@2189: choices.appendChild(item); ingo@2189: } ingo@2189: } ingo@2189: } ingo@2189: ingo@2189: /** ingo@126: * This method creates the root node that contains the list of selectable ingo@126: * items. ingo@126: * gernotbelger@9277: * @param cr gernotbelger@9277: * The ElementCreator. ingo@126: * ingo@126: * @return the root node of the item list. ingo@126: */ gernotbelger@9277: protected Element createData(final ElementCreator cr, final Artifact artifact, final StateData data, final CallContext context) { gernotbelger@9277: final Element select = ProtocolUtils.createArtNode(cr, "select", null, null); ingo@129: cr.addAttr(select, "name", data.getName(), true); ingo@126: gernotbelger@9277: final Element label = ProtocolUtils.createArtNode(cr, "label", null, null); ingo@126: ingo@129: select.appendChild(label); ingo@129: gernotbelger@9277: label.setTextContent(Resources.getMsg(context.getMeta(), getID(), getID())); ingo@126: ingo@126: return select; ingo@126: } ingo@126: ingo@126: /** ingo@126: * This method creates a list of items. These items represent the amount of ingo@126: * input data that is possible for this state. ingo@126: * gernotbelger@9277: * @param cr gernotbelger@9277: * The ElementCreator. gernotbelger@9277: * @param name gernotbelger@9277: * The name of the amount of data. ingo@126: * ingo@126: * @return a list of items. ingo@126: */ gernotbelger@9277: protected Element[] createItems(final ElementCreator cr, final Artifact artifact, final String name, final CallContext context) { sascha@660: return null; sascha@660: } ingo@135: ingo@322: /** ingo@1180: * This method is used to create an item Element that contains two ingo@1180: * further elements label and value. The label and value ingo@1180: * elements both have text nodes. ingo@1180: * gernotbelger@9277: * @param cr gernotbelger@9277: * The ElementCreator used to build new Elements. gernotbelger@9277: * @param obj gernotbelger@9277: * This implementation awaits a String array with [0] = label and gernotbelger@9277: * [1] = value. ingo@1180: * ingo@1180: * @return an Element. ingo@1180: */ gernotbelger@9277: protected static Element createItem(final XMLUtils.ElementCreator cr, final Object obj) { gernotbelger@9277: final Element item = ProtocolUtils.createArtNode(cr, "item", null, null); gernotbelger@9277: final Element label = ProtocolUtils.createArtNode(cr, "label", null, null); gernotbelger@9277: final Element value = ProtocolUtils.createArtNode(cr, "value", null, null); ingo@1180: gernotbelger@9277: final String[] arr = (String[]) obj; ingo@1180: ingo@1180: label.setTextContent(arr[0]); ingo@1180: value.setTextContent(arr[1]); ingo@1180: ingo@1180: item.appendChild(label); ingo@1180: item.appendChild(value); ingo@1180: ingo@1180: return item; ingo@1180: } ingo@1180: gernotbelger@9277: // protected static Element createItem(final XMLUtils.ElementCreator cr, final Object obj) { gernotbelger@9277: // final Element item = ProtocolUtils.createArtNode(cr, "item", null, null); gernotbelger@9277: // final Element label = ProtocolUtils.createArtNode(cr, "label", null, null); gernotbelger@9277: // final Element value = ProtocolUtils.createArtNode(cr, "value", null, null); gernotbelger@9277: // gernotbelger@9277: // final String[] arr = (String[]) obj; gernotbelger@9277: // gernotbelger@9277: // label.setTextContent(arr[0]); gernotbelger@9277: // value.setTextContent(arr[1]); gernotbelger@9277: // gernotbelger@9277: // item.appendChild(label); gernotbelger@9277: // item.appendChild(value); gernotbelger@9277: // gernotbelger@9277: // return item; gernotbelger@9277: // } ingo@1180: ingo@1180: /** ingo@1176: * This method transform a given value into a StateData object. ingo@1176: * gernotbelger@9277: * @param flys gernotbelger@9277: * The D4EArtifact. gernotbelger@9277: * @param name gernotbelger@9277: * The name of the data object. gernotbelger@9277: * @param val gernotbelger@9277: * The value of the data object. ingo@1176: * ingo@1176: * @return a StateData object with name and value. ingo@1176: */ gernotbelger@9277: public StateData transform(final D4EArtifact flys, final CallContext cc, final StateData stateData, final String name, final String val) { teichmann@8202: if (log.isDebugEnabled()) { teichmann@8202: log.debug("Transform data ('" + name + "','" + val + "')"); sascha@3732: } ingo@2205: ingo@2205: stateData.setValue(val); ingo@2205: ingo@2205: return stateData; ingo@1176: } ingo@1176: gernotbelger@9277: /** gernotbelger@9277: * Override this to do validation. andre@8636: * andre@8636: * Throw an IllegalArgumentException with a localized andre@8636: * error message that should be presented to the user in case gernotbelger@9277: * the date provided is invalid. gernotbelger@9277: */ gernotbelger@9277: public void validate(final Artifact artifact, final CallContext context) throws IllegalArgumentException { gernotbelger@9277: validate(artifact); /* gernotbelger@9277: * For compatibility so that classes that gernotbelger@9277: * override this method still work. gernotbelger@9277: */ andre@8636: } gernotbelger@9277: ingo@1176: /** andre@8636: * This method is deprecated. andre@8636: * Override the function with the callcontext instead to do andre@8636: * localization of error.s ingo@322: */ gernotbelger@9277: public boolean validate(final Artifact artifact) throws IllegalArgumentException { ingo@322: return true; ingo@322: } ingo@322: felix@1691: /** felix@1691: * Returns which UIProvider shall be used to aid user input. felix@1691: */ ingo@135: protected String getUIProvider() { ingo@135: return null; ingo@135: } ingo@687: gernotbelger@9277: public Object computeAdvance(final D4EArtifact artifact, final String hash, final CallContext context, final List facets, final Object old) { sascha@697: return null; sascha@697: } ingo@687: gernotbelger@9277: public Object computeFeed(final D4EArtifact artifact, final String hash, final CallContext context, final List facets, final Object old) { ingo@687: return null; ingo@687: } ingo@941: gernotbelger@9277: public Object computeInit(final D4EArtifact artifact, final String hash, final Object context, final CallMeta meta, final List facets) { ingo@941: return null; ingo@941: } ingo@126: } ingo@126: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :