5 import mir.entity.adapter.*;
10 public class EntityBatchingProducerNode implements ProducerNode {
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;
25 public EntityBatchingProducerNode(
28 StorageObject aStorage,
29 EntityAdapterDefinition aDefinition,
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,
42 public EntityBatchingProducerNode(
45 StorageObject aStorage,
46 EntityAdapterDefinition aDefinition,
48 String anOrderByClause,
49 int aNrEntitiesPerBatch,
50 int aMinNrEntitiesInFirstBatch,
51 int aNrEntitiesToSkip,
52 ProducerNode aBatchSubNode,
53 ProducerNode aBatchListSubNode) {
55 batchSubNode = aBatchSubNode;
56 batchListSubNode = aBatchListSubNode;
58 verbs = new HashMap();
60 batchDataKey = aBatchDataKey;
61 batchInfoKey = aBatchInfoKey;
63 definition = aDefinition;
64 whereClause = aWhereClause;
65 orderByClause = anOrderByClause;
66 nrEntitiesToSkip = aNrEntitiesToSkip;
67 nrEntitiesPerBatch = aNrEntitiesPerBatch;
68 minNrEntitiesInFirstBatch = aMinNrEntitiesInFirstBatch;
71 public void produce(Map aValueMap, String aVerb, PrintWriter aLogger) throws ProducerFailure {
74 int nrBatchesAfterFirst;
75 int nrEntitiesInFirstBatch;
76 int nrBatchesToProcess;
81 String expandedWhereClause;
82 String expandedOrderByClause;
83 EntityBatchingProducerNodeVerb verb = (EntityBatchingProducerNodeVerb) verbs.get(aVerb);
86 BatchLocation location;
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
93 throw new ProducerFailure("EntityBatchingProducerNode: unknown verb '"+aVerb+"'", null);
96 expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
97 expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
99 batchesData = new Vector();
100 batchLocations = new Vector();
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;
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);
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);
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));
130 if (batchListSubNode!=null) {
131 batchListSubNode.produce(aValueMap, aVerb, aLogger);
134 nrBatchesToProcess = nrBatchesAfterFirst+1;
135 if (verb.nrBatchesToProcess>-1 && verb.nrBatchesToProcess<nrBatchesToProcess) {
136 nrBatchesToProcess=verb.nrBatchesToProcess;
139 if (batchSubNode!=null) {
140 for (i=0; i<nrBatchesToProcess; i++) {
141 location = (BatchLocation) batchLocations.get(i);
143 batchData.put("current", batchesData.get(i));
145 batchData.put("previous", batchesData.get(i-1));
147 batchData.put("previous", null);
149 if (i<batchesData.size()-1)
150 batchData.put("next", batchesData.get(i+1));
152 batchData.put("next", null);
154 Iterator j = new EntityIteratorAdapter(storage, expandedWhereClause, expandedOrderByClause,
155 location.nrEntities, definition, location.nrEntities, location.firstEntity);
156 List entities = new Vector();
159 entities.add(0, j.next());
161 aValueMap.put( batchDataKey, entities );
163 batchSubNode.produce(aValueMap, aVerb, aLogger);
167 catch (Throwable t) {
168 throw new ProducerFailure(t.getMessage(), t);
172 private class BatchLocation {
176 public BatchLocation(int aFirstEntity, int aNrEntities) {
177 firstEntity = aFirstEntity;
178 nrEntities = aNrEntities;
182 public Set buildVerbSet() {
183 return verbs.keySet();
186 public void addVerb(String aVerb, int aNrPagesToGenerate) {
187 verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aNrPagesToGenerate));
190 private class EntityBatchingProducerNodeVerb {
191 int nrBatchesToProcess;
193 EntityBatchingProducerNodeVerb(int aNrBatchesToProcess) {
194 nrBatchesToProcess = aNrBatchesToProcess;