5 import mir.entity.adapter.*;
10 // abstract public int getSize(String where) throws SQLException,StorageObjectException;
12 public class EntityBatchingProducerNode implements ProducerNode {
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;
27 public EntityBatchingProducerNode(
30 StorageObject aStorage,
31 EntityAdapterDefinition aDefinition,
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,
44 public EntityBatchingProducerNode(
47 StorageObject aStorage,
48 EntityAdapterDefinition aDefinition,
50 String anOrderByClause,
51 int aNrEntitiesPerBatch,
52 int aMinNrEntitiesInFirstBatch,
53 int aNrEntitiesToSkip,
54 ProducerNode aBatchSubNode,
55 ProducerNode aBatchListSubNode) {
57 batchSubNode = aBatchSubNode;
58 batchListSubNode = aBatchListSubNode;
60 verbs = new HashMap();
62 batchDataKey = aBatchDataKey;
63 batchInfoKey = aBatchInfoKey;
65 definition = aDefinition;
66 whereClause = aWhereClause;
67 orderByClause = anOrderByClause;
68 nrEntitiesToSkip = aNrEntitiesToSkip;
69 nrEntitiesPerBatch = aNrEntitiesPerBatch;
70 minNrEntitiesInFirstBatch = aMinNrEntitiesInFirstBatch;
73 public void produce(Map aValueMap, String aVerb, PrintWriter aLogger) throws ProducerFailure {
76 int nrBatchesAfterFirst;
77 int nrEntitiesInFirstBatch;
78 int nrBatchesToProcess;
83 String expandedWhereClause;
84 String expandedOrderByClause;
85 EntityBatchingProducerNodeVerb verb = (EntityBatchingProducerNodeVerb) verbs.get(aVerb);
88 BatchLocation location;
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
95 throw new ProducerFailure("EntityBatchingProducerNode: unknown verb '"+aVerb+"'", null);
98 expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
99 expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
101 batchesData = new Vector();
102 batchLocations = new Vector();
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;
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);
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);
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));
132 if (batchListSubNode!=null) {
133 batchListSubNode.produce(aValueMap, aVerb, aLogger);
136 nrBatchesToProcess = nrBatchesAfterFirst+1;
137 if (verb.nrBatchesToProcess>-1 && verb.nrBatchesToProcess<nrBatchesToProcess) {
138 nrBatchesToProcess=verb.nrBatchesToProcess;
141 if (batchSubNode!=null) {
142 for (i=0; i<nrBatchesToProcess; i++) {
143 location = (BatchLocation) batchLocations.get(i);
145 batchData.put("current", batchesData.get(i));
147 batchData.put("previous", batchesData.get(i-1));
149 batchData.put("previous", null);
151 if (i<batchesData.size()-1)
152 batchData.put("next", batchesData.get(i+1));
154 batchData.put("next", null);
156 Iterator j = new EntityIteratorAdapter(storage, expandedWhereClause, expandedOrderByClause,
157 location.nrEntities, definition, location.nrEntities, location.firstEntity);
158 List entities = new Vector();
161 entities.add(0, j.next());
163 aValueMap.put( batchDataKey, entities );
165 batchSubNode.produce(aValueMap, aVerb, aLogger);
169 catch (Throwable t) {
170 throw new ProducerFailure(t.getMessage(), t);
174 private class BatchLocation {
178 public BatchLocation(int aFirstEntity, int aNrEntities) {
179 firstEntity = aFirstEntity;
180 nrEntities = aNrEntities;
184 public Set buildVerbSet() {
185 return verbs.keySet();
188 public void addVerb(String aVerb, int aNrPagesToGenerate) {
189 verbs.put(aVerb, new EntityBatchingProducerNodeVerb(aNrPagesToGenerate));
192 private class EntityBatchingProducerNodeVerb {
193 int nrBatchesToProcess;
195 EntityBatchingProducerNodeVerb(int aNrBatchesToProcess) {
196 nrBatchesToProcess = aNrBatchesToProcess;