bugfixes mainly...
[mir.git] / source / mir / producer / EntityBatchingProducerNode.java
index 446404d..e12bd79 100755 (executable)
@@ -1,4 +1,4 @@
-/*package mir.producer;
+package mir.producer;
 
 import java.util.*;
 import java.io.*;
@@ -7,71 +7,198 @@ import mir.entity.*;
 import mir.storage.*;
 import mir.util.*;
 
-//     abstract public int getSize(String where) throws SQLException,StorageObjectException;
-
-
 public class EntityBatchingProducerNode implements ProducerNode {
   private Map verbs;
-  private EntityBatchingProducerNodeVerb defaultVerb;
 
-  private String key;
-  private StorageObject storage;
-  private EntityAdapterDefinition definition;
+  private String batchInfoKey;
+  private String batchDataKey;
+  private EntityAdapterModel model;
+  private String definition;
   private String whereClause;
   private String orderByClause;
-  private int nrArticlesPerBatch;
-  private int minNrArticlesInFirstBatch;
+  private String nrEntitiesToSkipExpression;
+  private String nrEntitiesPerBatchExpression;
+  private String minNrEntitiesInFirstBatchExpression;
+  private String defaultNrBatchesToProcessExpression;
   private ProducerNode batchSubNode;
   private ProducerNode batchListSubNode;
 
   public EntityBatchingProducerNode(
-        String aKey,
-        StorageObject aStorage,
-        EntityAdapterDefinition aDefinition,
+        String aBatchDataKey,
+        String aBatchInfoKey,
+        EntityAdapterModel aModel,
+        String aDefinition,
         String aWhereClause,
         String anOrderByClause,
-        int aNrArticlesPerBatch,
-        int aMinNrArticlesInFirstBatch,
+        int anrEntitiesPerBatchExpression,
+        int aminNrEntitiesInFirstBatchExpression,
+        int anrEntitiesToSkipExpression,
+        ProducerNode aBatchSubNode) {
+    this(aBatchDataKey, aBatchInfoKey, aModel, aDefinition, aWhereClause,
+        anOrderByClause, anrEntitiesPerBatchExpression, aminNrEntitiesInFirstBatchExpression, anrEntitiesToSkipExpression,
+        aBatchSubNode, null);
+  }
+
+  public EntityBatchingProducerNode(
+        String aBatchDataKey,
+        String aBatchInfoKey,
+        EntityAdapterModel aModel,
+        String aDefinition,
+        String aWhereClause,
+        String anOrderByClause,
+        int aNrEntitiesPerBatch,
+        int aMinNrEntitiesInFirstBatch,
+        int aNrEntitiesToSkip,
+        ProducerNode aBatchSubNode,
+        ProducerNode aBatchListSubNode) {
+
+    this(aBatchDataKey, aBatchInfoKey, aModel, aDefinition,
+         aWhereClause, anOrderByClause,
+        Integer.toString(aNrEntitiesPerBatch),
+        Integer.toString(aMinNrEntitiesInFirstBatch),
+        Integer.toString(aNrEntitiesToSkip),
+        "1",
+        aBatchSubNode, aBatchListSubNode);
+
+  }
+
+  public EntityBatchingProducerNode(
+        String aBatchDataKey,
+        String aBatchInfoKey,
+        EntityAdapterModel aModel,
+        String aDefinition,
+        String aWhereClause,
+        String anOrderByClause,
+        String anrEntitiesPerBatchExpression,
+        String aminNrEntitiesInFirstBatchExpression,
+        String anrEntitiesToSkipExpression,
+        String aDefaultNrBatchesToProcessExpression,
         ProducerNode aBatchSubNode,
         ProducerNode aBatchListSubNode) {
 
     batchSubNode = aBatchSubNode;
     batchListSubNode = aBatchListSubNode;
 
-    defaultVerb = null;
     verbs = new HashMap();
 
-    key = aKey;
-    storage = aStorage;
+    batchDataKey = aBatchDataKey;
+    batchInfoKey = aBatchInfoKey;
+    model = aModel;
     definition = aDefinition;
     whereClause = aWhereClause;
     orderByClause = anOrderByClause;
-    nrArticlesPerBatch = aNrArticlesPerBatch;
-    minNrArticlesInFirstBatch = aMinNrArticlesInFirstBatch;
+    nrEntitiesToSkipExpression = anrEntitiesToSkipExpression;
+    nrEntitiesPerBatchExpression = anrEntitiesPerBatchExpression;
+    minNrEntitiesInFirstBatchExpression = aminNrEntitiesInFirstBatchExpression;
+    defaultNrBatchesToProcessExpression = aDefaultNrBatchesToProcessExpression;
   }
 
   public void produce(Map aValueMap, String aVerb, PrintWriter aLogger) throws ProducerFailure {
-    EntityBatchingProducerNodeVerb verb = (EntityBatchingProducerNodeVerb) verbs.get(aVerb);
     Iterator browser;
+    int nrEntities;
+    int nrBatchesAfterFirst;
+    int nrEntitiesInFirstBatch;
+    int nrBatchesToProcess;
+    List batchesData;
+    int i;
+    int position;
+    Map batchData;
+    String expandedWhereClause;
+    String expandedOrderByClause;
+    EntityBatchingProducerNodeVerb verb = (EntityBatchingProducerNodeVerb) verbs.get(aVerb);
+
+    List batchLocations;
+    BatchLocation location;
 
-    if (verb==null)
-      verb = defaultVerb;
+    int nrEntitiesToSkip;
+    int nrEntitiesPerBatch;
+    int minNrEntitiesInFirstBatch;
+
+//  ML: The order by clause should lead to a result set in _reverse order_: the first row will be
+//      the last entity presented on the last page
 
-    if (verb==null)
-      throw new ProducerFailure("EntityBatchingProducerNode: unknown verb '"+aVerb+"'", null);
 
     try {
-      browser = new EntityIteratorAdapter(
-          storage,
-          ParameterExpander.expandExpression( aValueMap, verb.whereClause ),
-          ParameterExpander.expandExpression( aValueMap, verb.orderByClause ),
-          -1,
-          definition );
-
-      while (browser.hasNext()) {
-        aLogger.println( verb.whereClause + ": next... ");
-        aValueMap.put(key, browser.next());
-        super.produce(aValueMap, aVerb, aLogger);
+      if (verb==null) {
+        nrBatchesToProcess = ParameterExpander.evaluateIntegerExpressionWithDefault( aValueMap, defaultNrBatchesToProcessExpression, -1 );
+      }
+      else {
+        nrBatchesToProcess=verb.nrBatchesToProcess;
+      }
+
+      expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
+      expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
+
+      nrEntitiesToSkip = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesToSkipExpression);
+      nrEntitiesPerBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesPerBatchExpression);
+      minNrEntitiesInFirstBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, minNrEntitiesInFirstBatchExpression);
+
+      batchesData = new Vector();
+      batchLocations = new Vector();
+
+      nrEntities = model.getMappingForName(definition).getStorage().getSize(expandedWhereClause)-nrEntitiesToSkip;
+      nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch;
+      while (nrEntitiesInFirstBatch<minNrEntitiesInFirstBatch && nrEntities-nrEntitiesInFirstBatch>=nrEntitiesPerBatch)
+        nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch;
+      nrBatchesAfterFirst = (nrEntities-nrEntitiesInFirstBatch)/nrEntitiesPerBatch;
+
+      batchLocations.add(new BatchLocation(nrBatchesAfterFirst*nrEntitiesPerBatch, nrEntitiesInFirstBatch));
+      batchData = new HashMap();
+      batchData.put("identifier", "");
+      batchData.put("index", new Integer(nrBatchesAfterFirst+1));
+      batchData.put("size", new Integer(nrEntitiesInFirstBatch));
+      batchesData.add(batchData);
+
+      for (i=0; i<nrBatchesAfterFirst; i++) {
+        batchLocations.add(1, new BatchLocation(i*nrEntitiesPerBatch, nrEntitiesPerBatch));
+        batchData = new HashMap();
+        batchData.put("identifier", new Integer(i));
+        batchData.put("index", new Integer(i+1));
+        batchData.put("size", new Integer(nrEntitiesPerBatch));
+        batchesData.add(1, batchData);
+      }
+
+      batchData = new HashMap();
+      ParameterExpander.setValueForKey(aValueMap, batchInfoKey, batchData);
+      batchData.put("all", batchesData);
+      batchData.put("first", batchesData.get(0));
+      batchData.put("last", batchesData.get(batchesData.size()-1));
+      batchData.put("count", new Integer(batchesData.size()));
+
+      if (batchListSubNode!=null) {
+        batchListSubNode.produce(aValueMap, aVerb, aLogger);
+      }
+
+      if (nrBatchesToProcess<0 || nrBatchesToProcess>nrBatchesAfterFirst+1) {
+        nrBatchesToProcess = nrBatchesAfterFirst+1;
+      }
+
+      if (batchSubNode!=null) {
+        for (i=0; i<nrBatchesToProcess; i++) {
+          location = (BatchLocation) batchLocations.get(i);
+
+          batchData.put("current", batchesData.get(i));
+          if (i>0)
+            batchData.put("previous", batchesData.get(i-1));
+          else
+            batchData.put("previous", null);
+
+          if (i<batchesData.size()-1)
+            batchData.put("next", batchesData.get(i+1));
+          else
+            batchData.put("next", null);
+
+          Iterator j = new EntityIteratorAdapter(expandedWhereClause, expandedOrderByClause,
+                    location.nrEntities, model, definition, location.nrEntities, location.firstEntity);
+          List entities = new Vector();
+
+          while (j.hasNext())
+            entities.add(0, j.next());
+
+          ParameterExpander.setValueForKey(aValueMap, batchDataKey, entities );
+
+          batchSubNode.produce(aValueMap, aVerb, aLogger);
+        }
       }
     }
     catch (Throwable t) {
@@ -79,31 +206,30 @@ public class EntityBatchingProducerNode implements ProducerNode {
     }
   };
 
-  public Set buildVerbSet() {
-    Set set;
+  private class BatchLocation {
+    int nrEntities;
+    int firstEntity;
 
-    set = super.buildVerbSet();
-    set.addAll(verbs.keySet());
+    public BatchLocation(int aFirstEntity, int aNrEntities) {
+      firstEntity = aFirstEntity;
+      nrEntities = aNrEntities;
+    }
+  }
 
-    return set;
+  public Set buildVerbSet() {
+    return verbs.keySet();
   };
 
-  public void addVerb(String aVerb, String aWhereClause, String anOrderByClause) {
-    verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aWhereClause, anOrderByClause));
+  public void addVerb(String aVerb, int aNrPagesToGenerate) {
+    verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aNrPagesToGenerate));
   }
 
-
-// int nrPagesToGenerate
-//
-
   private class EntityBatchingProducerNodeVerb {
-    int nrPagesToGenerate;
+    int nrBatchesToProcess;
 
-    EntityBatchingProducerNodeVerb(String aWhereClause, String anOrderByClause) {
-      whereClause = aWhereClause;
-      orderByClause = anOrderByClause;
+    EntityBatchingProducerNodeVerb(int aNrBatchesToProcess) {
+      nrBatchesToProcess = aNrBatchesToProcess;
     }
   }
 }
 
-*/
\ No newline at end of file