At last the EntityBatchingProducerNode is working. This will replace the old
[mir.git] / source / mir / producer / EntityBatchingProducerNode.java
1 package mir.producer;
2
3 import java.util.*;
4 import java.io.*;
5 import mir.entity.adapter.*;
6 import mir.entity.*;
7 import mir.storage.*;
8 import mir.util.*;
9
10 //      abstract public int getSize(String where) throws SQLException,StorageObjectException;
11
12 public class EntityBatchingProducerNode implements ProducerNode {
13   private Map verbs;
14
15   private String batchInfoKey;
16   private String batchDataKey;
17   private StorageObject storage;
18   private EntityAdapterDefinition definition;
19   private String whereClause;
20   private String orderByClause;
21   private int nrEntitiesToSkip;
22   private int nrEntitiesPerBatch;
23   private int minNrEntitiesInFirstBatch;
24   private ProducerNode batchSubNode;
25   private ProducerNode batchListSubNode;
26
27   public EntityBatchingProducerNode(
28         String aBatchDataKey,
29         String aBatchInfoKey,
30         StorageObject aStorage,
31         EntityAdapterDefinition aDefinition,
32         String aWhereClause,
33         String anOrderByClause,
34         int aNrEntitiesPerBatch,
35         int aMinNrEntitiesInFirstBatch,
36         int aNrEntitiesToSkip,
37         ProducerNode aBatchSubNode) {
38     this(aBatchDataKey, aBatchInfoKey, aStorage, aDefinition, aWhereClause,
39         anOrderByClause, aNrEntitiesPerBatch, aMinNrEntitiesInFirstBatch, aNrEntitiesToSkip,
40         aBatchSubNode, null);
41   }
42
43
44   public EntityBatchingProducerNode(
45         String aBatchDataKey,
46         String aBatchInfoKey,
47         StorageObject aStorage,
48         EntityAdapterDefinition aDefinition,
49         String aWhereClause,
50         String anOrderByClause,
51         int aNrEntitiesPerBatch,
52         int aMinNrEntitiesInFirstBatch,
53         int aNrEntitiesToSkip,
54         ProducerNode aBatchSubNode,
55         ProducerNode aBatchListSubNode) {
56
57     batchSubNode = aBatchSubNode;
58     batchListSubNode = aBatchListSubNode;
59
60     verbs = new HashMap();
61
62     batchDataKey = aBatchDataKey;
63     batchInfoKey = aBatchInfoKey;
64     storage = aStorage;
65     definition = aDefinition;
66     whereClause = aWhereClause;
67     orderByClause = anOrderByClause;
68     nrEntitiesToSkip = aNrEntitiesToSkip;
69     nrEntitiesPerBatch = aNrEntitiesPerBatch;
70     minNrEntitiesInFirstBatch = aMinNrEntitiesInFirstBatch;
71   }
72
73   public void produce(Map aValueMap, String aVerb, PrintWriter aLogger) throws ProducerFailure {
74     Iterator browser;
75     int nrEntities;
76     int nrBatchesAfterFirst;
77     int nrEntitiesInFirstBatch;
78     int nrBatchesToProcess;
79     List batchesData;
80     int i;
81     int position;
82     Map batchData;
83     String expandedWhereClause;
84     String expandedOrderByClause;
85     EntityBatchingProducerNodeVerb verb = (EntityBatchingProducerNodeVerb) verbs.get(aVerb);
86
87     List batchLocations;
88     BatchLocation location;
89
90 //  ML: The order by clause should lead to a result set in _reverse order_: the first row will be
91 //      the last entity presented on the last page
92
93
94     if (verb==null)
95       throw new ProducerFailure("EntityBatchingProducerNode: unknown verb '"+aVerb+"'", null);
96
97     try {
98       expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
99       expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
100
101       batchesData = new Vector();
102       batchLocations = new Vector();
103
104       nrEntities = storage.getSize(expandedWhereClause)-nrEntitiesToSkip;
105       nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch;
106       while (nrEntitiesInFirstBatch<minNrEntitiesInFirstBatch && nrEntities-nrEntitiesInFirstBatch>=nrEntitiesPerBatch)
107         nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch;
108       nrBatchesAfterFirst = (nrEntities-nrEntitiesInFirstBatch)/nrEntitiesPerBatch;
109
110       batchLocations.add(new BatchLocation(nrBatchesAfterFirst*nrEntitiesPerBatch, nrEntitiesInFirstBatch));
111       batchData = new HashMap();
112       batchData.put("identifier", "");
113       batchData.put("index", Integer.toString(1));
114       batchData.put("size", Integer.toString(nrEntitiesInFirstBatch));
115       batchesData.add(batchData);
116
117       for (i=0; i<nrBatchesAfterFirst; i++) {
118         batchLocations.add(1, new BatchLocation(i*nrEntitiesPerBatch, nrEntitiesPerBatch));
119         batchData = new HashMap();
120         batchData.put("identifier", Integer.toString(i));
121         batchData.put("index", Integer.toString(nrBatchesAfterFirst-i+1));
122         batchData.put("size", Integer.toString(nrEntitiesPerBatch));
123         batchesData.add(1, batchData);
124       }
125
126       batchData = new HashMap();
127       aValueMap.put(batchInfoKey, batchData);
128       batchData.put("all", batchesData);
129       batchData.put("first", batchesData.get(0));
130       batchData.put("last", batchesData.get(batchesData.size()-1));
131
132       if (batchListSubNode!=null) {
133         batchListSubNode.produce(aValueMap, aVerb, aLogger);
134       }
135
136       nrBatchesToProcess = nrBatchesAfterFirst+1;
137       if (verb.nrBatchesToProcess>-1 && verb.nrBatchesToProcess<nrBatchesToProcess) {
138         nrBatchesToProcess=verb.nrBatchesToProcess;
139       }
140
141       if (batchSubNode!=null) {
142         for (i=0; i<nrBatchesToProcess; i++) {
143           location = (BatchLocation) batchLocations.get(i);
144
145           batchData.put("current", batchesData.get(i));
146           if (i>0)
147             batchData.put("previous", batchesData.get(i-1));
148           else
149             batchData.put("previous", null);
150
151           if (i<batchesData.size()-1)
152             batchData.put("next", batchesData.get(i+1));
153           else
154             batchData.put("next", null);
155
156           Iterator j = new EntityIteratorAdapter(storage, expandedWhereClause, expandedOrderByClause,
157                     location.nrEntities, definition, location.nrEntities, location.firstEntity);
158           List entities = new Vector();
159
160           while (j.hasNext())
161             entities.add(0, j.next());
162
163           aValueMap.put( batchDataKey, entities );
164
165           batchSubNode.produce(aValueMap, aVerb, aLogger);
166         }
167       }
168     }
169     catch (Throwable t) {
170       throw new ProducerFailure(t.getMessage(), t);
171     }
172   };
173
174   private class BatchLocation {
175     int nrEntities;
176     int firstEntity;
177
178     public BatchLocation(int aFirstEntity, int aNrEntities) {
179       firstEntity = aFirstEntity;
180       nrEntities = aNrEntities;
181     }
182   }
183
184   public Set buildVerbSet() {
185     return verbs.keySet();
186   };
187
188   public void addVerb(String aVerb, int aNrPagesToGenerate) {
189     verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aNrPagesToGenerate));
190   }
191
192   private class EntityBatchingProducerNodeVerb {
193     int nrBatchesToProcess;
194
195     EntityBatchingProducerNodeVerb(int aNrBatchesToProcess) {
196       nrBatchesToProcess = aNrBatchesToProcess;
197     }
198   }
199 }
200