changeset 9232:5030c46d8cb4

Implemented xpath function that selectes the 'mean year' of a fixation-artifact. Needs to provide the ArtifactDatabase to the builder implementation.
author gernotbelger
date Fri, 06 Jul 2018 13:09:54 +0200
parents 082e8e808902
children 03427b89ba62
files artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FixAnalysisYearXPathFunction.java artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java
diffstat 8 files changed, 135 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/CollectionMonitor.java	Fri Jul 06 13:09:54 2018 +0200
@@ -89,9 +89,7 @@
             } else { // Not found in cache -> generate it.
                 Element r = createElement(XMLUtils.newDocument());
 
-                Recommendations.getInstance().recommend(
-                    artifact, null, outs,
-                    getNoneUserSpecificParameters(artifact, context), r);
+                Recommendations.getInstance().recommend( artifact, null, outs, getNoneUserSpecificParameters(artifact, context), r, context);
 
                 recommendations = (Element)doc.importNode(r, true);
 
@@ -101,10 +99,7 @@
 
             recommendations = createElement(doc);
 
-            Recommendations.getInstance().recommend(
-                artifact, null, outs,
-                getNoneUserSpecificParameters(artifact, context),
-                recommendations);
+            Recommendations.getInstance().recommend( artifact, null, outs, getNoneUserSpecificParameters(artifact, context), recommendations, context);
         }
 
         return recommendations;
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/Recommendations.java	Fri Jul 06 13:09:54 2018 +0200
@@ -31,7 +31,7 @@
 import org.hibernate.SessionFactory;
 
 import org.hibernate.jdbc.Work;
-
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.Config;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.common.utils.StringUtils;
@@ -175,13 +175,15 @@
     /**
      * Append recommendations to \param result.
      * @param extraParameters parameters (typical example: 'recommended')
+     * @param context 
      */
     public void  recommend(
         D4EArtifact         artifact,
         String              userId,
         String []           outs,
         Map<String, Object> extraParameters,
-        Node                result
+        Node                result, 
+        final CallContext   context
     ) {
         Map<String, Object> parameters = new HashMap<String, Object>();
 
@@ -201,27 +203,19 @@
 
         parameters.put("PARAMETERS", parameters);
 
-        recommend(parameters, userId, result);
+        recommend(parameters, userId, result, context);
     }
 
 
     /**
      * Append recommendations to \param result.
+     * @param context 
      */
-    public void recommend(
-        Map<String, Object> parameters,
-        String              userId,
-        Node                result
-    ) {
-        recommend(parameters, userId, result, SessionHolder.HOLDER.get());
+    public void recommend( final Map<String, Object> parameters, final String userId, final Node result, final CallContext context ) {
+        recommend(parameters, userId, result, SessionHolder.HOLDER.get(), context);
     }
 
-    public void recommend(
-        final Map<String, Object> parameters,
-        final String              userId,
-        final Node                result,
-        Session                   systemSession
-    ) {
+    public void recommend( final Map<String, Object> parameters, final String userId, final Node result, final Session systemSession, final CallContext context ) {
         systemSession.doWork(new Work() {
             @Override
             public void execute(final Connection systemConnection)
@@ -237,10 +231,7 @@
                         public void execute(Connection sedDBConnection)
                         throws SQLException
                         {
-                            recommend(
-                                parameters, userId, result,
-                                systemConnection,
-                                sedDBConnection);
+                            recommend( parameters, userId, result, systemConnection, sedDBConnection, context);
                         }
                     });
                 }
@@ -252,11 +243,12 @@
     }
 
     public void recommend(
-        Map<String, Object> parameters,
-        String              userId,
-        Node                result,
-        Connection          systemConnection,
-        Connection          seddbConnection
+        final Map<String, Object> parameters,
+        final String              userId,
+        final Node                result,
+        final Connection          systemConnection,
+        final Connection          seddbConnection, 
+        final CallContext         context
     ) throws SQLException
     {
         List<Builder.NamedConnection> connections =
@@ -285,7 +277,7 @@
                     CONNECTION_USER, userConnection, false));
             }
 
-            getBuilderPool().build(connections, result, parameters);
+            getBuilderPool().build(connections, result, parameters, context);
         }
         finally {
             if (userConnection != null) {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/App.java	Fri Jul 06 13:09:54 2018 +0200
@@ -18,6 +18,7 @@
 
 import org.apache.log4j.Logger;
 import org.apache.log4j.PropertyConfigurator;
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.Config;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.river.artifacts.datacage.Recommendations;
@@ -97,7 +98,8 @@
         final Session session = SessionFactoryProvider.createSessionFactory().openSession();
 
         try {
-            rec.recommend(parameters, userId, result, session);
+            final CallContext context = null;
+            rec.recommend(parameters, userId, result, session, context);
         } finally {
             session.close();
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/Builder.java	Fri Jul 06 13:09:54 2018 +0200
@@ -8,6 +8,7 @@
 
 package org.dive4elements.river.artifacts.datacage.templating;
 
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 
 import org.dive4elements.river.utils.Pair;
@@ -138,31 +139,34 @@
         protected Deque<Object>                            groupExprStack;
         protected FunctionResolver                         functionResolver;
         protected Map<String, XPathExpression>             expressions;
+        private final CallContext context;
 
 
-        public BuildHelper(
-            Node                  output,
-            List<NamedConnection> connections,
-            Map<String, Object>   parameters
-        ) {
+        public BuildHelper( final Node output, final List<NamedConnection> connections, final Map<String, Object> parameters, CallContext context ) {
             if (connections.isEmpty()) {
                 throw new IllegalArgumentException("no connections given.");
             }
 
-            this.connections = connections;
-            connectionsStack =
-                new ArrayDeque<Pair<NamedConnection, ResultData>>();
-            this.output      = output;
+            connectionsStack = new ArrayDeque<Pair<NamedConnection, ResultData>>();
             frames           = new StackFrames(parameters);
             owner            = getOwnerDocument(output);
             macroBodies      = new ArrayDeque<NodeList>();
             groupExprStack   = new ArrayDeque<Object>();
-            functionResolver = new FunctionResolver(this);
             expressions      = new HashMap<String, XPathExpression>();
-            statements       =
-                new HashMap<String, CompiledStatement.Instance>();
+            statements       = new HashMap<String, CompiledStatement.Instance>();
+
+            this.connections = connections;
+            this.output      = output;
+            this.context = context;
+
+            // Important call this at the end of constructor, it might call back
+            functionResolver = new FunctionResolver(this);
         }
-
+        
+        public final CallContext getContext() {
+            return this.context;
+        }
+        
         public void build() throws SQLException {
             try {
                 // XXX: Thread safety is now established by the builder pool.
@@ -1407,17 +1411,11 @@
         return document != null ? document : (Document)node;
     }
 
-    public void build(
-        List<NamedConnection> connections,
-        Node                  output,
-        Map<String, Object>   parameters
-    )
-    throws SQLException
+    public void build( final List<NamedConnection> connections, final Node output, final Map<String, Object> parameters, final CallContext context ) throws SQLException
     {
         long startTime = System.currentTimeMillis();
         try {
-            BuildHelper helper =
-                new BuildHelper(output, connections, parameters);
+            BuildHelper helper = new BuildHelper(output, connections, parameters, context);
             helper.build();
         }
         finally {
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/BuilderPool.java	Fri Jul 06 13:09:54 2018 +0200
@@ -20,7 +20,7 @@
 import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.artifacts.CallContext;
 import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 
@@ -78,12 +78,7 @@
         return document;
     }
 
-    public void build(
-        List<Builder.NamedConnection> connections,
-        Node                          output,
-        Map<String, Object>           parameters
-    )
-    throws SQLException
+    public void build( final List<Builder.NamedConnection> connections, final Node output, final Map<String, Object> parameters, final CallContext context ) throws SQLException
     {
         Builder builder;
         synchronized (pool) {
@@ -93,12 +88,12 @@
                 }
             }
             catch (InterruptedException ie) {
-                log.debug("Waiting for builder interrupted. Build canceled.");
+                log.debug("Waiting for builder interrupted. Build canceled.", ie);
                 return;
             }
         }
         try {
-            builder.build(connections, output, parameters);
+            builder.build(connections, output, parameters, context);
         }
         finally {
             synchronized (pool) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FixAnalysisYearXPathFunction.java	Fri Jul 06 13:09:54 2018 +0200
@@ -0,0 +1,66 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.artifacts.datacage.templating;
+
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.xpath.XPathFunction;
+import javax.xml.xpath.XPathFunctionException;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifacts.CallContext;
+import org.dive4elements.river.artifacts.FixationArtifact;
+import org.dive4elements.river.artifacts.access.FixRealizingAccess;
+import org.dive4elements.river.artifacts.model.fixings.FixRealizingCalculationExtended;
+import org.dive4elements.river.utils.RiverUtils;
+
+/**
+ * Very specialized function the resolves the 'year' (als middle of all used events) from a fix-analysis-vollmer
+ * artifact).
+ *
+ * @author Gernot Belger
+ */
+public class FixAnalysisYearXPathFunction implements XPathFunction {
+
+    public static final String ID = "fix_analysis_year";
+
+    public static final int ARITY = 1;
+
+    private static Logger log = Logger.getLogger(FixAnalysisYearXPathFunction.class);
+
+    private final CallContext context;
+
+    public FixAnalysisYearXPathFunction(final CallContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public Object evaluate(final List args) throws XPathFunctionException {
+
+        // FIXME: get artifact id
+        final UUID uuid = (UUID) args.get(0);
+
+        final FixationArtifact fixation = (FixationArtifact) RiverUtils.getArtifact(uuid.toString(), this.context);
+
+        // FIXME: fetch year
+        // final CalculationResult r = (CalculationResult) fixation.compute(this.context, ComputeType.ADVANCE, false);
+        // final FixRealizingResult frR = (FixRealizingResult) r.getData();
+
+        // Get W/Q input per gauge for this case.
+        final FixRealizingAccess fixAccess = new FixRealizingAccess(fixation);
+        // final List<Segment> segments = fixAccess.getSegments();
+        // final boolean isFixRealize = (segments != null && !segments.isEmpty());
+
+        /* ugly but necessary to keep this logic at least a bit inside the FixRealizing stuff */
+        final FixRealizingCalculationExtended calculation = new FixRealizingCalculationExtended(fixAccess);
+        return calculation.determineMeanYear();
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/datacage/templating/FunctionResolver.java	Fri Jul 06 13:09:54 2018 +0200
@@ -227,6 +227,8 @@
                 return column(args.get(0));
             }
         });
+
+        addFunction(FixAnalysisYearXPathFunction.ID, FixAnalysisYearXPathFunction.ARITY, new FixAnalysisYearXPathFunction(buildHelper.getContext()));
     }
 
     /**
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java	Fri Jul 06 13:09:25 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/services/MetaDataService.java	Fri Jul 06 13:09:54 2018 +0200
@@ -15,12 +15,14 @@
 import java.util.Map;
 import java.util.HashMap;
 
+import org.dive4elements.artifactdatabase.ArtifactCallContext;
+import org.dive4elements.artifactdatabase.ArtifactDatabaseImpl;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.artifacts.GlobalContext;
 import org.dive4elements.artifacts.ArtifactDatabase;
 import org.dive4elements.artifacts.ArtifactDatabaseException;
-
+import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.artifacts.common.utils.XMLUtils;
 import org.dive4elements.artifacts.common.utils.StringUtils;
 
@@ -97,8 +99,7 @@
         String parameters = XMLUtils.xpathString(
             data, XPATH_PARAMETERS, ArtifactNamespaceContext.INSTANCE);
 
-        return doService(
-            artifactId, userId, outs, parameters, globalContext);
+        return doService( artifactId, userId, outs, parameters, globalContext, callMeta);
     }
 
 
@@ -133,7 +134,8 @@
         String        userId,
         String        outsString,
         String        parameters,
-        GlobalContext globalContext
+        GlobalContext globalContext, 
+        CallMeta callMeta
     ) {
         Document result = XMLUtils.newDocument();
 
@@ -151,22 +153,19 @@
             return result;
         }
 
+        Object dbObject = (ArtifactDatabase)globalContext.get(ARTIFACT_DATA_BASE_KEY);
+        if (!(dbObject instanceof ArtifactDatabase)) {
+            log.error("Cannot find artifact database");
+            return result;
+        }
+        ArtifactDatabaseImpl db = (ArtifactDatabaseImpl)dbObject;
+        
         if (artifactId != null) {
             if (!StringUtils.checkUUID(artifactId)) {
                 log.warn("'" + artifactId + "' is not a UUID");
                 return result;
             }
 
-            Object dbObject =
-                (ArtifactDatabase)globalContext.get(ARTIFACT_DATA_BASE_KEY);
-
-            if (!(dbObject instanceof ArtifactDatabase)) {
-                log.error("Cannot find artifact database");
-                return result;
-            }
-
-            ArtifactDatabase db = (ArtifactDatabase)dbObject;
-
             Artifact artifact;
 
             try {
@@ -196,10 +195,16 @@
             ? new String [0]
             : outsString.split("\\s*,\\s*");
 
-        Recommendations rec = Recommendations.getInstance();
-        rec.recommend(
-            flysArtifact, userId, outs, data, result);
 
+        // REMARK: this is an ugly place to do it and should rather be done inside the ArtifactDatabase, from where this service is called.
+        // REMARK: at the moment we know that this is currently only used to transport the ArtifactDatabase
+        final ArtifactCallContext callContext = new ArtifactCallContext(db, CallContext.NOTHING, callMeta, null);
+            
+        final Recommendations rec = Recommendations.getInstance();
+        rec.recommend( flysArtifact, userId, outs, data, result, callContext );
+
+        callContext.postCall();
+        
         return result;
     }
 }

http://dive4elements.wald.intevation.org