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