introduced AdapterEntityModel
[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 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         EntityAdapterModel aModel,
29         String aDefinition,
30         String aWhereClause,
31         String anOrderByClause,
32         int aNrEntitiesPerBatch,
33         int aMinNrEntitiesInFirstBatch,
34         int aNrEntitiesToSkip,
35         ProducerNode aBatchSubNode) {
36     this(aBatchDataKey, aBatchInfoKey, aModel, aDefinition, aWhereClause,
37         anOrderByClause, aNrEntitiesPerBatch, aMinNrEntitiesInFirstBatch, aNrEntitiesToSkip,
38         aBatchSubNode, null);
39   }
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     batchSubNode = aBatchSubNode;
56     batchListSubNode = aBatchListSubNode;
57
58     verbs = new HashMap();
59
60     batchDataKey = aBatchDataKey;
61     batchInfoKey = aBatchInfoKey;
62     model = aModel;
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 = model.getMappingForName(definition).getStorage().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       batchData.put("count", Integer.toString(batchesData.size()));
130
131       if (batchListSubNode!=null) {
132         batchListSubNode.produce(aValueMap, aVerb, aLogger);
133       }
134
135       nrBatchesToProcess = nrBatchesAfterFirst+1;
136       if (verb.nrBatchesToProcess>-1 && verb.nrBatchesToProcess<nrBatchesToProcess) {
137         nrBatchesToProcess=verb.nrBatchesToProcess;
138       }
139
140       if (batchSubNode!=null) {
141         for (i=0; i<nrBatchesToProcess; i++) {
142           location = (BatchLocation) batchLocations.get(i);
143
144           batchData.put("current", batchesData.get(i));
145           if (i>0)
146             batchData.put("previous", batchesData.get(i-1));
147           else
148             batchData.put("previous", null);
149
150           if (i<batchesData.size()-1)
151             batchData.put("next", batchesData.get(i+1));
152           else
153             batchData.put("next", null);
154
155           Iterator j = new EntityIteratorAdapter(expandedWhereClause, expandedOrderByClause,
156                     location.nrEntities, model, definition, location.nrEntities, location.firstEntity);
157           List entities = new Vector();
158
159           while (j.hasNext())
160             entities.add(0, j.next());
161
162           aValueMap.put( batchDataKey, entities );
163
164           batchSubNode.produce(aValueMap, aVerb, aLogger);
165         }
166       }
167     }
168     catch (Throwable t) {
169       throw new ProducerFailure(t.getMessage(), t);
170     }
171   };
172
173   private class BatchLocation {
174     int nrEntities;
175     int firstEntity;
176
177     public BatchLocation(int aFirstEntity, int aNrEntities) {
178       firstEntity = aFirstEntity;
179       nrEntities = aNrEntities;
180     }
181   }
182
183   public Set buildVerbSet() {
184     return verbs.keySet();
185   };
186
187   public void addVerb(String aVerb, int aNrPagesToGenerate) {
188     verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aNrPagesToGenerate));
189   }
190
191   private class EntityBatchingProducerNodeVerb {
192     int nrBatchesToProcess;
193
194     EntityBatchingProducerNodeVerb(int aNrBatchesToProcess) {
195       nrBatchesToProcess = aNrBatchesToProcess;
196     }
197   }
198 }
199