diff flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java @ 704:eab5e5089d77

Merged revisions 2127-2133,2136-2137,2140,2143-2144,2146,2150-2151,2153-2154 via svnmerge from svn+ssh://teichmann@thoe/home/projects/Geospatial/bsh-generischer-viewer/Material/SVN/flys-artifacts/branches/facets-slt ........ r2127 | ingo | 2011-06-16 09:50:56 +0200 (Do, 16 Jun 2011) | 1 line Added a compute() method to WINFOArtifact which acts as a dispatcher for different computations. It triggers a calculation based on ComputeCallbacks that are generated by the current states. ........ r2128 | ingo | 2011-06-16 10:25:06 +0200 (Do, 16 Jun 2011) | 1 line Moved Waterlevel state into the correct package. ........ r2129 | ingo | 2011-06-16 10:43:58 +0200 (Do, 16 Jun 2011) | 1 line Added two more compute() methods to ComputeCallback to distinguish between different phases of the artifact. ........ r2130 | ingo | 2011-06-16 10:57:05 +0200 (Do, 16 Jun 2011) | 1 line Use enums to dispatch computeFeed() and computeAdvance(). ........ r2131 | ingo | 2011-06-16 11:04:59 +0200 (Do, 16 Jun 2011) | 1 line Store facets for each state. ........ r2132 | ingo | 2011-06-16 12:05:44 +0200 (Do, 16 Jun 2011) | 1 line Generated facets for each output aspect. ........ r2133 | ingo | 2011-06-16 15:24:00 +0200 (Do, 16 Jun 2011) | 1 line Write computed facets into artifacts describe document. ........ r2136 | ingo | 2011-06-16 16:10:49 +0200 (Do, 16 Jun 2011) | 1 line Add index and description of facets to collections describe document. ........ r2137 | ingo | 2011-06-16 16:31:41 +0200 (Do, 16 Jun 2011) | 1 line OutGenerators doOut() takes a facet object now instead of just its name. ........ r2140 | ingo | 2011-06-17 11:19:43 +0200 (Fr, 17 Jun 2011) | 1 line OutGenerators use now facets to fetch necessary data. ........ r2143 | teichmann | 2011-06-17 12:40:54 +0200 (Fr, 17 Jun 2011) | 1 line Removed ComputeCallback because this was thought too complicated. Fixed issue with facets not be re-generated if same state is entered again. ........ r2144 | teichmann | 2011-06-17 13:08:31 +0200 (Fr, 17 Jun 2011) | 1 line make getGauges() more robust ........ r2146 | teichmann | 2011-06-17 13:23:57 +0200 (Fr, 17 Jun 2011) | 1 line mico opt: inter cmps are faster than str cmps. ........ r2150 | teichmann | 2011-06-17 15:10:20 +0200 (Fr, 17 Jun 2011) | 1 line call computeAdvance() if we want to advance. ........ r2151 | teichmann | 2011-06-17 15:45:50 +0200 (Fr, 17 Jun 2011) | 1 line Base WST/CSV exports on facets. TODO: generate the facets. ........ r2153 | teichmann | 2011-06-17 16:03:29 +0200 (Fr, 17 Jun 2011) | 1 line Add facet to access raw computed data. ........ r2154 | teichmann | 2011-06-17 16:37:09 +0200 (Fr, 17 Jun 2011) | 1 line Generate data facets for the computed states. ........ flys-artifacts/trunk@2156 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 17 Jun 2011 16:17:03 +0000
parents d45c3ddaed1b 94f0f91be11c
children 853dceead0f4
line wrap: on
line diff
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java	Fri Jun 17 13:00:54 2011 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/FLYSArtifact.java	Fri Jun 17 16:17:03 2011 +0000
@@ -4,6 +4,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -12,6 +13,8 @@
 
 import gnu.trove.TDoubleArrayList;
 
+import net.sf.ehcache.Cache;
+
 import org.apache.log4j.Logger;
 
 import org.w3c.dom.Document;
@@ -28,6 +31,7 @@
 import de.intevation.artifactdatabase.DefaultArtifact;
 import de.intevation.artifactdatabase.data.DefaultStateData;
 import de.intevation.artifactdatabase.data.StateData;
+import de.intevation.artifactdatabase.state.Facet;
 import de.intevation.artifactdatabase.state.State;
 import de.intevation.artifactdatabase.state.StateEngine;
 import de.intevation.artifactdatabase.transition.TransitionEngine;
@@ -40,11 +44,14 @@
 
 import de.intevation.flys.artifacts.context.FLYSContext;
 
+import de.intevation.flys.artifacts.cache.CacheFactory;
+
 import de.intevation.flys.artifacts.model.DischargeTables;
 import de.intevation.flys.artifacts.model.RiverFactory;
 import de.intevation.flys.artifacts.model.Segment;
 
 import de.intevation.flys.artifacts.states.DefaultState;
+import de.intevation.flys.artifacts.states.DefaultState.ComputeType;
 import de.intevation.flys.artifacts.states.LocationDistanceSelect;
 
 
@@ -59,6 +66,8 @@
     private static Logger logger = Logger.getLogger(FLYSArtifact.class);
 
 
+    public static final String COMPUTING_CACHE = "computed.values";
+
     /** The XPath that points to the input data elements of the FEED document.*/
     public static final String XPATH_FEED_INPUT =
         "/art:action/art:data/art:input";
@@ -93,13 +102,17 @@
     /** The data that have been inserted into this artifact.*/
     protected Map<String, StateData> data;
 
+    /** The list of facets supported by this artifact.*/
+    protected Map<String, List<Facet>> facets;
+
 
     /**
      * The default constructor that creates an empty FLYSArtifact.
      */
     public FLYSArtifact() {
-        data             = new HashMap<String, StateData>();
+        data             = new TreeMap<String, StateData>();
         previousStateIds = new ArrayList<String>();
+        facets           = new HashMap<String, List<Facet>>();
     }
 
 
@@ -182,6 +195,9 @@
 
         try {
             saveData(target, XPATH_FEED_INPUT, context);
+
+            compute(context, ComputeType.FEED);
+
             return describe(target, context);
         }
         catch (IllegalArgumentException iae) {
@@ -228,6 +244,9 @@
 
             setCurrentStateId(targetState);
 
+            logger.debug("Compute data for state: " + targetState);
+            compute(context, ComputeType.ADVANCE);
+
             return describe(target, context);
         }
         else if (isPreviousState(targetState, context)) {
@@ -241,6 +260,7 @@
                 String prev = prevs.get(i);
                 logger.debug("Remove state id '" + prev + "'");
                 prevs.remove(prev);
+                facets.remove(prev);
             }
 
             setCurrentStateId(targetState);
@@ -338,6 +358,23 @@
     }
 
 
+    public Facet getNativeFacet(Facet facet) {
+        String name  = facet.getName();
+        int    index = facet.getIndex();
+
+        for (Map.Entry<String, List<Facet>> entry: facets.entrySet()) {
+            for (Facet f: entry.getValue()) {
+                if (f.getIndex() == index && f.getName().equals(name)) {
+                    return f;
+                }
+            }
+        }
+
+        logger.warn("Could not find facet: " + name + " at " + index);
+        return null;
+    }
+
+
     /**
      * This method stores the data that is contained in the FEED document.
      *
@@ -673,8 +710,16 @@
      * @return the gauges based on the selected kilometer range.
      */
     public List<Gauge> getGauges() {
-        River    river = getRiver();
-        double[] dist  = getDistance();
+
+        River river = getRiver();
+        if (river == null) {
+            return null;
+        }
+
+        double [] dist  = getDistance();
+        if (dist == null) {
+            return null;
+        }
 
         return river.determineGauges(dist[0], dist[1]);
     }
@@ -1023,6 +1068,117 @@
     }
 
     /**
+     * Computes the hash code of the entered values.
+     *
+     * @return a hash code.
+     */
+    @Override
+    public String hash() {
+        Set<Map.Entry<String, StateData>> entries = data.entrySet();
+
+        int hash  = 0;
+        int shift = 3;
+
+        for (Map.Entry<String, StateData> entry: entries) {
+            String key   = entry.getKey();
+            Object value = entry.getValue().getValue();
+
+            hash ^= (key.hashCode() << shift) | (value.hashCode() << 2 * shift);
+            shift += 2;
+        }
+
+        return getCurrentStateId() + hash;
+    }
+
+
+    /**
+     * Dispatches the computation request to compute(CallContext context, String
+     * hash) with the current hash value of the artifact which is provided by
+     * hash().
+     *
+     * @param context The CallContext.
+     */
+    public Object compute(CallContext context, ComputeType type) {
+        return compute(context, hash(), type);
+    }
+
+
+    /**
+     * Dispatches computation requests to the current state which needs to
+     * implement a createComputeCallback(String hash, FLYSArtifact artifact)
+     * method.
+     *
+     * @param context The CallContext.
+     * @param hash The hash value which is used to fetch computed data from
+     * cache.
+     *
+     * @return the computed data.
+     */
+    public Object compute(CallContext context, String hash, ComputeType type) {
+        DefaultState current = (DefaultState) getCurrentState(context);
+
+        logger.debug("Create ComputeCallback for state: " + current.getID());
+
+        return compute(context, hash, current, type);
+    }
+
+
+    public Object compute(
+        CallContext   context,
+        String        key,
+        DefaultState  state,
+        ComputeType   type
+    ) {
+        String stateID = state.getID();
+
+        List<Facet> fs = new ArrayList<Facet>();
+
+        try {
+            Cache cache = CacheFactory.getCache(COMPUTING_CACHE);
+
+            Object old = null;
+
+            if (cache != null) {
+                net.sf.ehcache.Element element = cache.get(key);
+                if (element != null) {
+                    logger.debug("Got computation result from cache.");
+                    old = element.getValue();
+                }
+            }
+
+            Object res;
+            switch (type) {
+                case FEED:
+                    res = state.computeFeed(this, key, context, fs, old);
+                    break;
+                case ADVANCE:
+                    res = state.computeAdvance(this, key, context, fs, old);
+                    break;
+                default:
+                    res = null;
+            }
+
+            if (cache != null && old != res && res != null) {
+                logger.debug("Store computation result to cache.");
+                net.sf.ehcache.Element element =
+                    new net.sf.ehcache.Element(key, res);
+                cache.put(element);
+            }
+
+            return res;
+        }
+        finally {
+            if (fs.isEmpty()) {
+                facets.remove(stateID);
+            }
+            else {
+                facets.put(stateID, fs);
+            }
+        }
+    }
+
+
+    /**
      * Method to dump the artifacts state/data.
      */
     protected void dumpArtifact() {

http://dive4elements.wald.intevation.org