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 :