merge of localization branch into HEAD. mh and zap
[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 public class EntityBatchingProducerNode implements ProducerNode {
11   private Map verbs;
12
13   private String batchInfoKey;
14   private String batchDataKey;
15   private EntityAdapterModel model;
16   private String definition;
17   private String whereClause;
18   private String orderByClause;
19   private String nrEntitiesToSkipExpression;
20   private String nrEntitiesPerBatchExpression;
21   private String minNrEntitiesInFirstBatchExpression;
22   private String defaultNrBatchesToProcessExpression;
23   private ProducerNode batchSubNode;
24   private ProducerNode batchListSubNode;
25
26   public EntityBatchingProducerNode(
27         String aBatchDataKey,
28         String aBatchInfoKey,
29         EntityAdapterModel aModel,
30         String aDefinition,
31         String aWhereClause,
32         String anOrderByClause,
33         int anrEntitiesPerBatchExpression,
34         int aminNrEntitiesInFirstBatchExpression,
35         int anrEntitiesToSkipExpression,
36         ProducerNode aBatchSubNode) {
37     this(aBatchDataKey, aBatchInfoKey, aModel, aDefinition, aWhereClause,
38         anOrderByClause, anrEntitiesPerBatchExpression, aminNrEntitiesInFirstBatchExpression, anrEntitiesToSkipExpression,
39         aBatchSubNode, null);
40   }
41
42   public EntityBatchingProducerNode(
43         String aBatchDataKey,
44         String aBatchInfoKey,
45         EntityAdapterModel aModel,
46         String aDefinition,
47         String aWhereClause,
48         String anOrderByClause,
49         int aNrEntitiesPerBatch,
50         int aMinNrEntitiesInFirstBatch,
51         int aNrEntitiesToSkip,
52         ProducerNode aBatchSubNode,
53         ProducerNode aBatchListSubNode) {
54
55     this(aBatchDataKey, aBatchInfoKey, aModel, aDefinition,
56          aWhereClause, anOrderByClause,
57         Integer.toString(aNrEntitiesPerBatch),
58         Integer.toString(aMinNrEntitiesInFirstBatch),
59         Integer.toString(aNrEntitiesToSkip),
60         "1",
61         aBatchSubNode, aBatchListSubNode);
62
63   }
64
65   public EntityBatchingProducerNode(
66         String aBatchDataKey,
67         String aBatchInfoKey,
68         EntityAdapterModel aModel,
69         String aDefinition,
70         String aWhereClause,
71         String anOrderByClause,
72         String anrEntitiesPerBatchExpression,
73         String aminNrEntitiesInFirstBatchExpression,
74         String anrEntitiesToSkipExpression,
75         String aDefaultNrBatchesToProcessExpression,
76         ProducerNode aBatchSubNode,
77         ProducerNode aBatchListSubNode) {
78
79     batchSubNode = aBatchSubNode;
80     batchListSubNode = aBatchListSubNode;
81
82     verbs = new HashMap();
83
84     batchDataKey = aBatchDataKey;
85     batchInfoKey = aBatchInfoKey;
86     model = aModel;
87     definition = aDefinition;
88     whereClause = aWhereClause;
89     orderByClause = anOrderByClause;
90     nrEntitiesToSkipExpression = anrEntitiesToSkipExpression;
91     nrEntitiesPerBatchExpression = anrEntitiesPerBatchExpression;
92     minNrEntitiesInFirstBatchExpression = aminNrEntitiesInFirstBatchExpression;
93     defaultNrBatchesToProcessExpression = aDefaultNrBatchesToProcessExpression;
94   }
95
96   public void produce(Map aValueMap, String aVerb, PrintWriter aLogger) throws ProducerFailure {
97     Iterator browser;
98     int nrEntities;
99     int nrBatchesAfterFirst;
100     int nrEntitiesInFirstBatch;
101     int nrBatchesToProcess;
102     List batchesData;
103     int i;
104     int position;
105     Map batchData;
106     String expandedWhereClause;
107     String expandedOrderByClause;
108     EntityBatchingProducerNodeVerb verb = (EntityBatchingProducerNodeVerb) verbs.get(aVerb);
109
110     List batchLocations;
111     BatchLocation location;
112
113     int nrEntitiesToSkip;
114     int nrEntitiesPerBatch;
115     int minNrEntitiesInFirstBatch;
116
117 //  ML: The order by clause should lead to a result set in _reverse order_: the first row will be
118 //      the last entity presented on the last page
119
120
121     try {
122       if (verb==null) {
123         nrBatchesToProcess = ParameterExpander.evaluateIntegerExpressionWithDefault( aValueMap, defaultNrBatchesToProcessExpression, -1 );
124       }
125       else {
126         nrBatchesToProcess=verb.nrBatchesToProcess;
127       }
128
129       expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
130       expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
131
132       nrEntitiesToSkip = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesToSkipExpression);
133       nrEntitiesPerBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesPerBatchExpression);
134       minNrEntitiesInFirstBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, minNrEntitiesInFirstBatchExpression);
135
136       batchesData = new Vector();
137       batchLocations = new Vector();
138
139       nrEntities = model.getMappingForName(definition).getStorage().getSize(expandedWhereClause)-nrEntitiesToSkip;
140       nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch;
141       while (nrEntitiesInFirstBatch<minNrEntitiesInFirstBatch && nrEntities-nrEntitiesInFirstBatch>=nrEntitiesPerBatch)
142         nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch;
143       nrBatchesAfterFirst = (nrEntities-nrEntitiesInFirstBatch)/nrEntitiesPerBatch;
144
145       batchLocations.add(new BatchLocation(nrBatchesAfterFirst*nrEntitiesPerBatch, nrEntitiesInFirstBatch));
146       batchData = new HashMap();
147       batchData.put("identifier", "");
148       batchData.put("index", new Integer(nrBatchesAfterFirst+1));
149       batchData.put("size", new Integer(nrEntitiesInFirstBatch));
150       batchesData.add(batchData);
151
152       for (i=0; i<nrBatchesAfterFirst; i++) {
153         batchLocations.add(1, new BatchLocation(i*nrEntitiesPerBatch, nrEntitiesPerBatch));
154         batchData = new HashMap();
155         batchData.put("identifier", new Integer(i));
156         batchData.put("index", new Integer(i+1));
157         batchData.put("size", new Integer(nrEntitiesPerBatch));
158         batchesData.add(1, batchData);
159       }
160
161       batchData = new HashMap();
162       ParameterExpander.setValueForKey(aValueMap, batchInfoKey, batchData);
163       batchData.put("all", batchesData);
164       batchData.put("first", batchesData.get(0));
165       batchData.put("last", batchesData.get(batchesData.size()-1));
166       batchData.put("count", new Integer(batchesData.size()));
167
168       if (batchListSubNode!=null) {
169         batchListSubNode.produce(aValueMap, aVerb, aLogger);
170       }
171
172       if (nrBatchesToProcess<0 || nrBatchesToProcess>nrBatchesAfterFirst+1) {
173         nrBatchesToProcess = nrBatchesAfterFirst+1;
174       }
175
176       if (batchSubNode!=null) {
177         for (i=0; i<nrBatchesToProcess; i++) {
178           location = (BatchLocation) batchLocations.get(i);
179
180           batchData.put("current", batchesData.get(i));
181           if (i>0)
182             batchData.put("previous", batchesData.get(i-1));
183           else
184             batchData.put("previous", null);
185
186           if (i<batchesData.size()-1)
187             batchData.put("next", batchesData.get(i+1));
188           else
189             batchData.put("next", null);
190
191           Iterator j = new EntityIteratorAdapter(expandedWhereClause, expandedOrderByClause,
192                     location.nrEntities, model, definition, location.nrEntities, location.firstEntity);
193           List entities = new Vector();
194
195           while (j.hasNext())
196             entities.add(0, j.next());
197
198           ParameterExpander.setValueForKey(aValueMap, batchDataKey, entities );
199
200           batchSubNode.produce(aValueMap, aVerb, aLogger);
201         }
202       }
203     }
204     catch (Throwable t) {
205       throw new ProducerFailure(t.getMessage(), t);
206     }
207   };
208
209   private class BatchLocation {
210     int nrEntities;
211     int firstEntity;
212
213     public BatchLocation(int aFirstEntity, int aNrEntities) {
214       firstEntity = aFirstEntity;
215       nrEntities = aNrEntities;
216     }
217   }
218
219   public Set buildVerbSet() {
220     return verbs.keySet();
221   };
222
223   public void addVerb(String aVerb, int aNrPagesToGenerate) {
224     verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aNrPagesToGenerate));
225   }
226
227   private class EntityBatchingProducerNodeVerb {
228     int nrBatchesToProcess;
229
230     EntityBatchingProducerNodeVerb(int aNrBatchesToProcess) {
231       nrBatchesToProcess = aNrBatchesToProcess;
232     }
233   }
234 }
235