2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
32 import java.util.HashMap;
33 import java.util.Iterator;
34 import java.util.List;
36 import java.util.Vector;
38 import mir.entity.adapter.EntityAdapterModel;
39 import mir.entity.adapter.EntityIteratorAdapter;
40 import mir.log.LoggerWrapper;
41 import mir.util.ParameterExpander;
44 * <p>Title: EntityBatchingProducerNode</p>
46 * This producer makes it possible to show articles in batches, like on archive
49 * <emph> The order by clause should lead to a result set in <b>reverse order<b>:
50 * the first row will be the last entity in the last batch
52 * <p>Copyright: Copyright (c) 2003</p>
54 * @author not attributable
58 public class EntityBatchingProducerNode implements ProducerNode {
59 private String batchInfoKey;
60 private String batchDataKey;
61 private EntityAdapterModel model;
62 private String mainTablePrefix;
63 private List extraTables;
64 private String definition;
65 private String whereClause;
66 private String orderByClause;
67 private String nrEntitiesToSkipExpression;
68 private String nrEntitiesPerBatchExpression;
69 private String minNrEntitiesInFirstBatchExpression;
70 private String nrBatchesToProcessExpression;
71 private ProducerNode batchSubNode;
72 private ProducerNode batchListSubNode;
74 public EntityBatchingProducerNode(
77 EntityAdapterModel aModel,
78 String aMainTablePrefix,
82 String anOrderByClause,
83 String anrEntitiesPerBatchExpression,
84 String aminNrEntitiesInFirstBatchExpression,
85 String anrEntitiesToSkipExpression,
86 String aNrBatchesToProcessExpression,
87 ProducerNode aBatchSubNode,
88 ProducerNode aBatchListSubNode) {
90 batchSubNode = aBatchSubNode;
91 batchListSubNode = aBatchListSubNode;
93 batchDataKey = aBatchDataKey;
94 batchInfoKey = aBatchInfoKey;
96 mainTablePrefix = aMainTablePrefix;
97 extraTables = someExtraTables;
98 definition = aDefinition;
99 whereClause = aWhereClause;
100 orderByClause = anOrderByClause;
101 nrEntitiesToSkipExpression = anrEntitiesToSkipExpression;
102 nrEntitiesPerBatchExpression = anrEntitiesPerBatchExpression;
103 minNrEntitiesInFirstBatchExpression = aminNrEntitiesInFirstBatchExpression;
104 nrBatchesToProcessExpression = aNrBatchesToProcessExpression;
107 protected boolean isAborted(Map aValueMap) {
108 Object producerValue = aValueMap.get(NodedProducer.PRODUCER_KEY);
110 (producerValue instanceof NodedProducer) &&
111 ((NodedProducer) producerValue).getIsAborted());
114 public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure {
117 int nrBatchesAfterFirst;
118 int nrEntitiesInFirstBatch;
119 int nrBatchesToProcess;
124 String expandedWhereClause;
125 String expandedOrderByClause;
128 BatchLocation location;
130 int nrEntitiesToSkip;
131 int nrEntitiesPerBatch;
132 int minNrEntitiesInFirstBatch;
135 nrBatchesToProcess = ParameterExpander.evaluateIntegerExpressionWithDefault( aValueMap, nrBatchesToProcessExpression, -1 );
137 expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
138 expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
140 nrEntitiesToSkip = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesToSkipExpression);
141 nrEntitiesPerBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesPerBatchExpression);
142 minNrEntitiesInFirstBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, minNrEntitiesInFirstBatchExpression);
144 batchesData = new Vector();
145 batchLocations = new Vector();
147 nrEntities = model.getMappingForName(definition).getStorage().getSize(expandedWhereClause)-nrEntitiesToSkip;
148 nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch;
149 while (nrEntitiesInFirstBatch<minNrEntitiesInFirstBatch && nrEntities-nrEntitiesInFirstBatch>=nrEntitiesPerBatch)
150 nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch;
151 nrBatchesAfterFirst = (nrEntities-nrEntitiesInFirstBatch)/nrEntitiesPerBatch;
153 batchLocations.add(new BatchLocation(nrBatchesAfterFirst*nrEntitiesPerBatch, nrEntitiesInFirstBatch));
154 batchData = new HashMap();
155 batchData.put("identifier", "");
156 batchData.put("index", new Integer(nrBatchesAfterFirst+1));
157 batchData.put("size", new Integer(nrEntitiesInFirstBatch));
158 batchesData.add(batchData);
160 for (i=0; i<nrBatchesAfterFirst; i++) {
161 batchLocations.add(1, new BatchLocation(i*nrEntitiesPerBatch, nrEntitiesPerBatch));
162 batchData = new HashMap();
163 batchData.put("identifier", new Integer(i));
164 batchData.put("index", new Integer(i+1));
165 batchData.put("size", new Integer(nrEntitiesPerBatch));
166 batchesData.add(1, batchData);
169 batchData = new HashMap();
170 ParameterExpander.setValueForKey(aValueMap, batchInfoKey, batchData);
171 batchData.put("all", batchesData);
172 batchData.put("first", batchesData.get(0));
173 batchData.put("last", batchesData.get(batchesData.size()-1));
174 batchData.put("count", new Integer(batchesData.size()));
176 if (batchListSubNode!=null && (!isAborted(aValueMap))) {
177 batchListSubNode.produce(aValueMap, aVerb, aLogger);
180 if (nrBatchesToProcess<0 || nrBatchesToProcess>nrBatchesAfterFirst+1) {
181 nrBatchesToProcess = nrBatchesAfterFirst+1;
184 if (batchSubNode!=null) {
185 for (i=0; i<nrBatchesToProcess && !isAborted(aValueMap); i++) {
186 location = (BatchLocation) batchLocations.get(i);
188 batchData.put("current", batchesData.get(i));
190 batchData.put("previous", batchesData.get(i-1));
192 batchData.put("previous", null);
194 if (i<batchesData.size()-1)
195 batchData.put("next", batchesData.get(i+1));
197 batchData.put("next", null);
199 Iterator j = new EntityIteratorAdapter(mainTablePrefix, extraTables, expandedWhereClause, expandedOrderByClause,
200 location.nrEntities, model, definition, location.nrEntities, location.firstEntity);
201 List entities = new Vector();
204 entities.add(0, j.next());
206 ParameterExpander.setValueForKey(aValueMap, batchDataKey, entities );
208 batchSubNode.produce(aValueMap, aVerb, aLogger);
212 catch (Throwable t) {
213 aLogger.error("EntityBatchingProducerNode caused an exception: " + t.getMessage());
217 private class BatchLocation {
221 public BatchLocation(int aFirstEntity, int aNrEntities) {
222 firstEntity = aFirstEntity;
223 nrEntities = aNrEntities;