raimund@2082: package de.intevation.flys.artifacts;
raimund@2082: 
raimund@2082: import org.apache.log4j.Logger;
raimund@2082: 
raimund@2082: import java.util.List;
raimund@2082: 
raimund@2082: import org.w3c.dom.Document;
raimund@2089: import org.w3c.dom.Element;
raimund@2089: import org.w3c.dom.Node;
raimund@2082: 
raimund@2082: import de.intevation.artifacts.ArtifactFactory;
raimund@2082: import de.intevation.artifacts.CallMeta;
raimund@2082: import de.intevation.artifacts.CallContext;
raimund@2082: 
raimund@2089: import de.intevation.artifacts.common.utils.XMLUtils;
raimund@2089: import de.intevation.artifacts.common.utils.XMLUtils.ElementCreator;
raimund@2089: import de.intevation.artifacts.common.ArtifactNamespaceContext;
raimund@2089: 
raimund@2089: import de.intevation.artifactdatabase.ProtocolUtils;
raimund@2082: import de.intevation.artifactdatabase.state.Facet;
raimund@2082: import de.intevation.artifactdatabase.state.State;
raimund@2089: import de.intevation.artifactdatabase.state.StateEngine;
raimund@2089: import de.intevation.artifactdatabase.state.Output;
raimund@2089: import de.intevation.artifactdatabase.transition.TransitionEngine;
raimund@2082: 
raimund@2082: import de.intevation.flys.model.River;
raimund@2089: import de.intevation.flys.utils.FLYSUtils;
raimund@2082: 
raimund@2089: import de.intevation.flys.artifacts.RiverAxisArtifact.RiverAxisState;
raimund@2089: import de.intevation.flys.artifacts.states.DefaultState;
raimund@2089: import de.intevation.flys.artifacts.context.FLYSContext;
raimund@2089: import de.intevation.flys.artifacts.model.WMSDBLayerFacet;
raimund@2082: 
raimund@2082: 
raimund@2089: public class MapArtifact extends FLYSArtifact {
raimund@2082: 
raimund@2082:     private static final Logger logger =
raimund@2082:         Logger.getLogger(MapArtifact.class);
raimund@2082: 
raimund@2082:     @Override
raimund@2082:     public void setup(
raimund@2082:         String          identifier,
raimund@2082:         ArtifactFactory factory,
raimund@2082:         Object          context,
raimund@2082:         CallMeta        callmeta,
raimund@2082:         Document        data)
raimund@2082:     {
raimund@2082:         logger.debug("MapArtifact.setup");
raimund@2082:         this.identifier = identifier;
raimund@2109:         name = "new_map";
raimund@2082: 
raimund@2089:         FLYSContext flysContext = FLYSUtils.getFlysContext(context);
raimund@2082: 
raimund@2089:         List<State> states = getStates(context);
raimund@2082: 
raimund@2089:         setCurrentState(states.get(0));
raimund@2082:     }
raimund@2082: 
raimund@2082: 
raimund@2082:     @Override
raimund@2089:     public Document describe(Document data, CallContext context) {
raimund@2089:         logger.debug("Describe: the current state is: " + getCurrentStateId());
raimund@2089: 
raimund@2089:         if (logger.isDebugEnabled()) {
raimund@2089:             dumpArtifact();
raimund@2089:         }
raimund@2089: 
raimund@2089:         FLYSContext flysContext = FLYSUtils.getFlysContext(context);
raimund@2089: 
raimund@2089:         StateEngine stateEngine = (StateEngine) flysContext.get(
raimund@2089:             FLYSContext.STATE_ENGINE_KEY);
raimund@2089: 
raimund@2089:         TransitionEngine transitionEngine = (TransitionEngine) flysContext.get(
raimund@2089:             FLYSContext.TRANSITION_ENGINE_KEY);
raimund@2089: 
raimund@2089:         List<State> reachable = transitionEngine.getReachableStates(
raimund@2089:             this, getCurrentState(context), stateEngine);
raimund@2089: 
raimund@2089:         Document description            = XMLUtils.newDocument();
raimund@2089:         XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator(
raimund@2089:             description,
raimund@2089:             ArtifactNamespaceContext.NAMESPACE_URI,
raimund@2089:             ArtifactNamespaceContext.NAMESPACE_PREFIX);
raimund@2089: 
raimund@2089:         Element root = ProtocolUtils.createRootNode(creator);
raimund@2089:         description.appendChild(root);
raimund@2089: 
raimund@2089:         State current = getCurrentState(context);
raimund@2089: 
raimund@2089:         ProtocolUtils.appendDescribeHeader(creator, root, identifier(), hash());
raimund@2089:         ProtocolUtils.appendState(creator, root, current);
raimund@2089:         ProtocolUtils.appendReachableStates(creator, root, reachable);
raimund@2089: 
raimund@2089:         appendBackgroundActivity(creator, root, context);
raimund@2089: 
raimund@2089:         Element name = ProtocolUtils.createArtNode(
raimund@2089:             creator, "name",
raimund@2089:             new String[] { "value" },
raimund@2089:             new String[] { getName() });
raimund@2089: 
raimund@2089:         Element ui = ProtocolUtils.createArtNode(
raimund@2089:             creator, "ui", null, null);
raimund@2089: 
raimund@2089:         Element staticUI  = ProtocolUtils.createArtNode(
raimund@2089:             creator, "static", null, null);
raimund@2089: 
raimund@2089:         Element outs = ProtocolUtils.createArtNode(
raimund@2089:             creator, "outputmodes", null, null);
raimund@2089:         appendOutputModes(description, outs, context, identifier());
raimund@2089: 
raimund@2089:         appendStaticUI(description, staticUI, context, identifier());
raimund@2089: 
raimund@2089:         Element dynamic = current.describe(
raimund@2089:             this,
raimund@2089:             description,
raimund@2089:             root,
raimund@2089:             context,
raimund@2089:             identifier());
raimund@2089: 
raimund@2089:         if (dynamic != null) {
raimund@2089:             ui.appendChild(dynamic);
raimund@2089:         }
raimund@2089: 
raimund@2089:         ui.appendChild(staticUI);
raimund@2089: 
raimund@2089:         root.appendChild(name);
raimund@2089:         root.appendChild(ui);
raimund@2089:         root.appendChild(outs);
raimund@2089: 
raimund@2089:         return description;
raimund@2089: 
raimund@2089:     }
raimund@2089: 
raimund@2089: 
raimund@2089:     protected static void appendBackgroundActivity(
raimund@2089:         ElementCreator cr,
raimund@2089:         Element        root,
raimund@2089:         CallContext    context
raimund@2089:     ) {
raimund@2089:         Element inBackground = cr.create("background-processing");
raimund@2089:         root.appendChild(inBackground);
raimund@2089: 
raimund@2089:         cr.addAttr(
raimund@2089:             inBackground,
raimund@2089:             "value",
raimund@2089:             String.valueOf(context.isInBackground()),
raimund@2089:             true);
raimund@2089:     }
raimund@2089: 
raimund@2089: 
raimund@2089:     /**
raimund@2089:      * Append output mode nodes to a document.
raimund@2089:      */
raimund@2089:     protected void appendOutputModes(
raimund@2089:         Document    doc,
raimund@2089:         Element     outs,
raimund@2089:         CallContext context,
raimund@2089:         String      uuid)
raimund@2089:     {
raimund@2089:         List<String> stateIds = getPreviousStateIds();
raimund@2089: 
raimund@2089:         XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator(
raimund@2089:             doc,
raimund@2089:             ArtifactNamespaceContext.NAMESPACE_URI,
raimund@2089:             ArtifactNamespaceContext.NAMESPACE_PREFIX);
raimund@2089: 
raimund@2089:         FLYSContext flysContext = FLYSUtils.getFlysContext(context);
raimund@2089:         StateEngine engine      = (StateEngine) flysContext.get(
raimund@2089:             FLYSContext.STATE_ENGINE_KEY);
raimund@2089: 
raimund@2089:         for (String stateId: stateIds) {
raimund@2089:             logger.debug("Append output modes for state: " + stateId);
raimund@2089:             DefaultState state = (DefaultState) engine.getState(stateId);
raimund@2089: 
raimund@2089:             List<Output> list = state.getOutputs();
raimund@2089:             if (list == null || list.size() == 0) {
raimund@2089:                 logger.debug("-> No output modes for this state.");
raimund@2089:                 continue;
raimund@2089:             }
raimund@2089: 
raimund@2089:             List<Facet> fs = facets.get(stateId);
raimund@2089: 
raimund@2089:             if (fs == null || fs.size() == 0) {
raimund@2089:                 logger.debug("No facets for previous state found.");
raimund@2089:                 continue;
raimund@2089:             }
raimund@2089: 
raimund@2089:             logger.debug("Found " + fs.size() + " facets in previous states.");
raimund@2089: 
raimund@2089:             List<Output> generated = generateOutputs(list, fs);
raimund@2089: 
raimund@2089:             ProtocolUtils.appendOutputModes(doc, outs, generated);
raimund@2089:         }
raimund@2089: 
raimund@2089:         try {
raimund@2089:             DefaultState cur = (DefaultState) getCurrentState(context);
raimund@2089:             if (cur.validate(this)) {
raimund@2089:                 List<Output> list = cur.getOutputs();
raimund@2089:                 if (list != null && list.size() > 0) {
raimund@2089:                     logger.debug(
raimund@2089:                         "Append output modes for current state: " + cur.getID());
raimund@2089: 
raimund@2089:                     List<Facet> fs = facets.get(cur.getID());
raimund@2089: 
raimund@2089:                     if (fs != null && fs.size() > 0) {
raimund@2089:                         List<Output> generated = generateOutputs(list, fs);
raimund@2089: 
raimund@2089:                         logger.debug("Found " + fs.size() + " current facets.");
raimund@2089:                         if (!generated.isEmpty()) {
raimund@2089:                             ProtocolUtils.appendOutputModes(
raimund@2089:                                 doc, outs, generated);
raimund@2089:                         }
raimund@2089:                     }
raimund@2089:                     else {
raimund@2089:                         logger.debug("No facets found for the current state.");
raimund@2089:                     }
raimund@2089:                 }
raimund@2089:             }
raimund@2089:         }
raimund@2089:         catch (IllegalArgumentException iae) {
raimund@2089:             // state is not valid, so we do not append its outputs.
raimund@2089:         }
raimund@2089:     }
raimund@2089: 
raimund@2089: 
raimund@2089:     /**
raimund@2089:      * This method appends the static data - that has already been inserted by
raimund@2089:      * the user - to the static node of the DESCRIBE document.
raimund@2089:      *
raimund@2089:      * @param doc The document.
raimund@2089:      * @param ui The root node.
raimund@2089:      * @param context The CallContext.
raimund@2089:      * @param uuid The identifier of the artifact.
raimund@2089:      */
raimund@2089:     protected void appendStaticUI(
raimund@2089:         Document    doc,
raimund@2089:         Node        ui,
raimund@2089:         CallContext context,
raimund@2089:         String uuid)
raimund@2089:     {
raimund@2089:         List<String> stateIds = getPreviousStateIds();
raimund@2089: 
raimund@2089:         logger.debug("previous states: " + stateIds);
raimund@2089:         FLYSContext flysContext = FLYSUtils.getFlysContext(context);
raimund@2089:         StateEngine engine      = (StateEngine) flysContext.get(
raimund@2089:             FLYSContext.STATE_ENGINE_KEY);
raimund@2089: 
raimund@2089:         for (String stateId: stateIds) {
raimund@2089:             logger.debug("Append static data for state: " + stateId);
raimund@2089:             DefaultState state = (DefaultState) engine.getState(stateId);
raimund@2089: 
raimund@2089:             ui.appendChild(state.describeStatic(this, doc, ui, context, uuid));
raimund@2089:         }
raimund@2082:     }
raimund@2082: 
raimund@2082: 
raimund@2082:     public static class MapState extends RiverAxisState {
raimund@2082: 
raimund@2082:         @Override
raimund@2089:         public Object computeAdvance(
raimund@2082:             FLYSArtifact artifact,
raimund@2082:             String       hash,
raimund@2082:             CallContext  context,
raimund@2082:             List<Facet>  facets,
raimund@2082:             Object       old)
raimund@2082:         {
raimund@2089:             logger.debug("MapState.computeAdvance");
raimund@2089: 
raimund@2089:             this.artifact = artifact;
raimund@2082: 
raimund@2082:             String type = getFacetType();
raimund@2082: 
raimund@2082:             WMSDBLayerFacet facet = new WMSDBLayerFacet(
raimund@2082:                 0,
raimund@2082:                 type,
raimund@2082:                 getTitle(context.getMeta()),
raimund@2089:                 ComputeType.ADVANCE,
raimund@2082:                 getID(), hash,
raimund@2082:                 getUrl());
raimund@2082: 
raimund@2082:             String name = type + "-" + artifact.identifier();
raimund@2082: 
raimund@2082:             facet.addLayer(name);
raimund@2082:             facet.setExtent(getExtent());
raimund@2082:             facet.setSrid(getSrid());
raimund@2082:             facet.setData(getDataString());
raimund@2082:             facet.setFilter(getFilter());
raimund@2082:             facet.setGeometryType(getGeometryType());
raimund@2082:             facet.setConnection(getConnection());
raimund@2082:             facet.setConnectionType(getConnectionType());
raimund@2082:             facet.setLabelItem(getLabelItem());
raimund@2082: 
raimund@2082:             facets.add(facet);
raimund@2082: 
raimund@2082:             return null;
raimund@2082:         }
raimund@2082: 
raimund@2082:         @Override
raimund@2082:         public int getRiverId() {
raimund@2082:             River r = FLYSUtils.getRiver(artifact);
raimund@2082:             int riverId = r.getId();
raimund@2082: 
raimund@2082:             return riverId;
raimund@2082:         }
raimund@2082:     }
raimund@2082: }