ingo@126: package de.intevation.flys.artifacts.states;
ingo@126:
ingo@669: import java.text.NumberFormat;
ingo@669: import java.util.Locale;
ingo@126: import java.util.Map;
sascha@697: import java.util.List;
ingo@126:
ingo@126: import org.apache.log4j.Logger;
ingo@126:
ingo@126: import org.w3c.dom.Document;
ingo@126: import org.w3c.dom.Element;
ingo@126: import org.w3c.dom.Node;
ingo@126:
ingo@306: import de.intevation.artifacts.Artifact;
ingo@142: import de.intevation.artifacts.ArtifactNamespaceContext;
ingo@126: import de.intevation.artifacts.CallContext;
ingo@142: import de.intevation.artifacts.CallMeta;
ingo@126:
ingo@126: import de.intevation.artifacts.common.utils.XMLUtils;
ingo@1159: import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;
ingo@126:
ingo@126: import de.intevation.artifactdatabase.ProtocolUtils;
sascha@697:
ingo@126: import de.intevation.artifactdatabase.data.StateData;
sascha@697:
ingo@126: import de.intevation.artifactdatabase.state.AbstractState;
sascha@697: import de.intevation.artifactdatabase.state.Facet;
ingo@126:
ingo@624: import de.intevation.flys.artifacts.FLYSArtifact;
sascha@697:
ingo@126: import de.intevation.flys.artifacts.resources.Resources;
ingo@126:
ingo@126:
ingo@126: /**
ingo@126: * @author Ingo Weinzierl
ingo@126: */
ingo@126: public abstract class DefaultState extends AbstractState {
ingo@126:
felix@1029: /** The logger that is used in this class. */
ingo@126: private static Logger logger = Logger.getLogger(DefaultState.class);
ingo@126:
ingo@2015:
ingo@2015: /** Determines, if the DESCRIBE document should contain default values or
ingo@2015: * not. */
ingo@2015: public static final boolean USE_DEFAULTS =
ingo@2015: Boolean.getBoolean("flys.use.default.values");
ingo@2015:
felix@1768: /** The three possible compute types. */
sascha@697: public static enum ComputeType {
ingo@942: FEED, ADVANCE, INIT
sascha@697: }
ingo@126:
felix@1768:
ingo@624: protected StateData getData(FLYSArtifact artifact, String name) {
ingo@624: return artifact.getData(name);
ingo@624: }
ingo@624:
ingo@624:
felix@1136: /**
felix@1136: * Append to a node and return xml description relevant for gui.
felix@1136: */
ingo@134: public Element describeStatic(
ingo@624: Artifact artifact,
ingo@134: Document document,
ingo@134: Node root,
ingo@134: CallContext context,
ingo@134: String uuid)
ingo@134: {
ingo@1159: ElementCreator creator = new ElementCreator(
ingo@134: document,
ingo@134: ArtifactNamespaceContext.NAMESPACE_URI,
ingo@134: ArtifactNamespaceContext.NAMESPACE_PREFIX);
ingo@134:
ingo@142: CallMeta meta = context.getMeta();
ingo@142:
bjoern@4155: String helpText = getHelpText() != null ?
bjoern@4155: Resources.getMsg(meta, getHelpText(), getHelpText())
bjoern@4155: : null;
ingo@2661:
ingo@142: String label = Resources.getMsg(meta, getID(), getID());
ingo@136: Element ui = ProtocolUtils.createArtNode(
ingo@134: creator, "state",
ingo@2661: new String[] { "name", "uiprovider", "label", "helpText"},
ingo@2661: new String[] { getID(), getUIProvider(), label, helpText });
ingo@134:
ingo@134: Map theData = getData();
ingo@134: if (theData == null) {
ingo@134: return ui;
ingo@134: }
ingo@134:
sascha@3732: FLYSArtifact flys = (FLYSArtifact)artifact;
ingo@134:
sascha@3732: for (String name: theData.keySet()) {
ingo@1180: appendStaticData(flys, context, creator, ui, name);
ingo@134: }
ingo@134:
ingo@134: return ui;
ingo@134: }
ingo@134:
ingo@134:
ingo@1159: protected void appendStaticData(
ingo@1159: FLYSArtifact flys,
ingo@1180: CallContext context,
ingo@1180: ElementCreator cr,
ingo@1159: Element ui,
ingo@1159: String name
ingo@1159: ) {
ingo@1159: StateData data = getData(flys, name);
ingo@1159: String value = (data != null) ? (String) data.getValue() : null;
ingo@1159:
ingo@1159: if (value == null) {
ingo@1159: return;
ingo@1159: }
ingo@1159:
ingo@2205: String type = data.getType();
ingo@1159:
sascha@3732: if (logger.isDebugEnabled()) {
sascha@3732: logger.debug(
sascha@3732: "Append element " + type + "'" +
sascha@3732: name + "' (" + value + ")");
sascha@3732: }
ingo@2205:
ingo@2205: 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: /**
ingo@1180: * Creates a data element used in the static part of the DESCRIBE
ingo@1180: * document.
ingo@1180: *
ingo@1180: * @param creator The ElementCreator that is used to build new Elements.
felix@3284: * @param cc The CallContext object used for nested i18n retrieval.
ingo@1180: * @param name The name of the data item.
ingo@1180: * @param value The value as string.
ingo@1180: *
ingo@1180: * @return an Element.
ingo@1180: */
ingo@1180: protected Element createStaticData(
ingo@1743: FLYSArtifact flys,
ingo@1180: ElementCreator creator,
ingo@1180: CallContext cc,
ingo@1180: String name,
ingo@1180: String value,
ingo@1180: String type
ingo@1180: ) {
ingo@1159: Element dataElement = creator.create("data");
ingo@1159: creator.addAttr(dataElement, "name", name, true);
ingo@1180: creator.addAttr(dataElement, "type", type, true);
ingo@1159:
ingo@1159: Element itemElement = creator.create("item");
ingo@1159: creator.addAttr(itemElement, "value", value, true);
ingo@1159:
ingo@2205: creator.addAttr(
ingo@2205: itemElement,
ingo@2205: "label",
ingo@2205: getLabelFor(cc, name, value, type),
ingo@2205: true);
ingo@2205:
ingo@2205: dataElement.appendChild(itemElement);
ingo@2205:
ingo@2205: return dataElement;
ingo@2205: }
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: */
ingo@2205: protected String getLabelFor(
ingo@2205: CallContext cc,
ingo@2205: String name,
ingo@2205: String value,
ingo@2205: String type
ingo@2205: ) {
ingo@2205: 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.
sascha@3732: double doubleVal = Double.parseDouble(value);
ingo@1159: Locale l = Resources.getLocale(meta);
ingo@1159: NumberFormat nf = NumberFormat.getInstance(l);
ingo@1159:
ingo@2205: return nf.format(doubleVal);
ingo@1159: }
ingo@1159: catch (NumberFormatException nfe) {
ingo@2205: return Resources.getMsg(meta, value, value);
ingo@1159: }
ingo@1159: }
ingo@1159:
ingo@1159:
ingo@3407: /**
ingo@3407: * This method returns the default value and description for data.
ingo@3407: * Note, that this method returns the defaults only if USE_DEFAULTS
sascha@3414: * is set; otherwise, null is returned.
ingo@3407: * @param context The CallContext used for i18n.
ingo@3407: * @param data The data objects that the defaults are for.
ingo@3407: * @return a String[] with [default value, default label].
ingo@3407: */
ingo@3407: protected String[] getDefaultsFor(CallContext context, StateData data) {
ingo@3407: if (USE_DEFAULTS) {
ingo@3407: String defValue = (String) data.getValue();
ingo@3407: String defDesc = null;
ingo@3407:
ingo@3407: if (defValue != null && defValue.length() > 0) {
ingo@3407: defDesc = Resources.getMsg(
ingo@3407: context.getMeta(),
ingo@3407: defValue,
ingo@3407: defValue);
ingo@3407: }
ingo@3407:
ingo@3407: if (defValue != null && defDesc != null) {
ingo@3407: return new String[] { defValue, defDesc };
ingo@3407: }
ingo@3407: }
ingo@3407:
ingo@3407: return null;
ingo@3407: }
ingo@3407:
ingo@3407:
ingo@126: public Element describe(
ingo@306: Artifact artifact,
ingo@126: Document document,
ingo@126: Node root,
ingo@126: CallContext context,
ingo@126: String uuid)
ingo@126: {
ingo@1159: ElementCreator creator = new ElementCreator(
ingo@126: document,
ingo@126: ArtifactNamespaceContext.NAMESPACE_URI,
ingo@126: ArtifactNamespaceContext.NAMESPACE_PREFIX);
ingo@126:
ingo@2661: String helpText = Resources.getMsg(
ingo@2661: context.getMeta(), getHelpText(), getHelpText());
ingo@2661:
ingo@135: Element ui = null;
ingo@135: String uiprovider = getUIProvider();
ingo@135: if (uiprovider != null) {
felix@1136: ui = ProtocolUtils.createArtNode(
ingo@135: creator, "dynamic",
ingo@2661: new String[] { "uiprovider", "helpText" },
ingo@2661: new String[] { uiprovider, helpText });
ingo@135: }
ingo@135: else {
ingo@2661: ui = ProtocolUtils.createArtNode(
ingo@2661: creator, "dynamic",
ingo@2661: new String[] { "helpText" },
ingo@2661: new String[] { helpText });
ingo@135: }
ingo@126:
ingo@126: Map theData = getData();
ingo@126: if (theData == null) {
ingo@126: return ui;
ingo@126: }
ingo@126:
sascha@3732: FLYSArtifact flys = (FLYSArtifact)artifact;
ingo@126:
sascha@3732: for (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:
ingo@313: Element select = createData(creator, artifact, data, context);
ingo@126:
ingo@3407: 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@126: /**
ingo@2189: * @param artifact
ingo@2189: * @param creator
ingo@2189: * @param name
ingo@2189: * @param context
ingo@2189: * @param select
ingo@2189: */
ingo@2189: protected void appendItems(
ingo@2189: Artifact artifact,
ingo@2189: ElementCreator creator,
ingo@2189: String name,
ingo@2189: CallContext context,
ingo@2189: Element select
ingo@2189: ) {
ingo@2189: Element choices = ProtocolUtils.createArtNode(
ingo@2189: creator, "choices", null, null);
ingo@2189:
ingo@2189: select.appendChild(choices);
ingo@2189:
ingo@2189: Element[] items = createItems(creator, artifact, name, context);
ingo@2189: if (items != null) {
ingo@2189: for (Element item: items) {
ingo@2189: choices.appendChild(item);
ingo@2189: }
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: *
ingo@126: * @param cr The ElementCreator.
ingo@126: *
ingo@126: * @return the root node of the item list.
ingo@126: */
ingo@126: protected Element createData(
ingo@1159: ElementCreator cr,
ingo@313: Artifact artifact,
ingo@126: StateData data,
ingo@126: CallContext context)
ingo@126: {
ingo@126: Element select = ProtocolUtils.createArtNode(
ingo@126: cr, "select", null, null);
ingo@129: cr.addAttr(select, "name", data.getName(), true);
ingo@126:
ingo@126: Element label = ProtocolUtils.createArtNode(
ingo@126: cr, "label", null, null);
ingo@126:
ingo@129: select.appendChild(label);
ingo@129:
ingo@126: label.setTextContent(Resources.getMsg(
ingo@126: context.getMeta(),
ingo@126: getID(),
ingo@126: getID()));
ingo@126:
ingo@126: return select;
ingo@126: }
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: *
ingo@126: * @param cr The ElementCreator.
ingo@126: * @param name The name of the amount of data.
ingo@126: *
ingo@126: * @return a list of items.
ingo@126: */
sascha@660: protected Element[] createItems(
ingo@1159: ElementCreator cr,
ingo@313: Artifact artifact,
ingo@126: String name,
sascha@660: CallContext context
sascha@660: ) {
sascha@660: return null;
sascha@660: }
ingo@135:
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: *
ingo@1180: * @param cr The ElementCreator used to build new Elements.
ingo@1180: * @param obj This implementation awaits a String array with [0] = label and
ingo@1180: * [1] = value.
ingo@1180: *
ingo@1180: * @return an Element.
ingo@1180: */
ingo@1180: protected Element createItem(XMLUtils.ElementCreator cr, Object obj) {
ingo@1180: Element item = ProtocolUtils.createArtNode(cr, "item", null, null);
ingo@1180: Element label = ProtocolUtils.createArtNode(cr, "label", null, null);
ingo@1180: Element value = ProtocolUtils.createArtNode(cr, "value", null, null);
ingo@1180:
ingo@1180: 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:
ingo@1180:
ingo@1180: /**
ingo@1176: * This method transform a given value into a StateData object.
ingo@1176: *
ingo@1176: * @param flys The FLYSArtifact.
ingo@1176: * @param name The name of the data object.
ingo@1176: * @param val The value of the data object.
ingo@1176: *
ingo@1176: * @return a StateData object with name and value.
ingo@1176: */
ingo@1176: public StateData transform(
ingo@1176: FLYSArtifact flys,
ingo@1176: CallContext cc,
ingo@2205: StateData stateData,
ingo@1176: String name,
ingo@1176: String val
ingo@1176: ) {
sascha@3732: if (logger.isDebugEnabled()) {
sascha@3732: logger.debug("Transform data ('" + name + "','" + val + "')");
sascha@3732: }
ingo@2205:
ingo@2205: stateData.setValue(val);
ingo@2205:
ingo@2205: return stateData;
ingo@1176: }
ingo@1176:
ingo@1176:
ingo@1176: /**
ingo@322: * This method validates the inserted data and returns true, if everything
ingo@322: * was correct, otherwise an exception is thrown.
ingo@322: *
ingo@322: * @param artifact A reference to the owner artifact.
ingo@322: *
ingo@322: * @return true, if everything was fine.
ingo@322: */
sascha@1050: public boolean validate(Artifact artifact)
ingo@322: throws IllegalArgumentException
ingo@322: {
ingo@322: return true;
ingo@322: }
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:
felix@1136:
sascha@697: public Object computeAdvance(
sascha@697: FLYSArtifact artifact,
sascha@697: String hash,
sascha@742: CallContext context,
sascha@742: List facets,
sascha@697: Object old
sascha@697: ) {
sascha@697: return null;
sascha@697: }
ingo@687:
felix@1136:
sascha@697: public Object computeFeed(
sascha@697: FLYSArtifact artifact,
sascha@697: String hash,
sascha@697: CallContext context,
sascha@742: List facets,
sascha@697: Object old
sascha@697: ) {
ingo@687: return null;
ingo@687: }
ingo@941:
felix@1136:
ingo@941: public Object computeInit(
ingo@941: FLYSArtifact artifact,
ingo@941: String hash,
ingo@958: Object context,
ingo@941: CallMeta meta,
ingo@941: List facets)
ingo@941: {
ingo@941: return null;
ingo@941: }
ingo@126: }
ingo@126: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :