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 definition;
63 private String whereClause;
64 private String orderByClause;
65 private String nrEntitiesToSkipExpression;
66 private String nrEntitiesPerBatchExpression;
67 private String minNrEntitiesInFirstBatchExpression;
68 private String nrBatchesToProcessExpression;
69 private ProducerNode batchSubNode;
70 private ProducerNode batchListSubNode;
72 public EntityBatchingProducerNode(
75 EntityAdapterModel aModel,
78 String anOrderByClause,
79 String anrEntitiesPerBatchExpression,
80 String aminNrEntitiesInFirstBatchExpression,
81 String anrEntitiesToSkipExpression,
82 String aNrBatchesToProcessExpression,
83 ProducerNode aBatchSubNode,
84 ProducerNode aBatchListSubNode) {
86 batchSubNode = aBatchSubNode;
87 batchListSubNode = aBatchListSubNode;
89 batchDataKey = aBatchDataKey;
90 batchInfoKey = aBatchInfoKey;
92 definition = aDefinition;
93 whereClause = aWhereClause;
94 orderByClause = anOrderByClause;
95 nrEntitiesToSkipExpression = anrEntitiesToSkipExpression;
96 nrEntitiesPerBatchExpression = anrEntitiesPerBatchExpression;
97 minNrEntitiesInFirstBatchExpression = aminNrEntitiesInFirstBatchExpression;
98 nrBatchesToProcessExpression = aNrBatchesToProcessExpression;
101 protected boolean isAborted(Map aValueMap) {
102 Object producerValue = aValueMap.get(NodedProducer.PRODUCER_KEY);
104 (producerValue instanceof NodedProducer) &&
105 ((NodedProducer) producerValue).getIsAborted());
108 public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure {
111 int nrBatchesAfterFirst;
112 int nrEntitiesInFirstBatch;
113 int nrBatchesToProcess;
118 String expandedWhereClause;
119 String expandedOrderByClause;
122 BatchLocation location;
124 int nrEntitiesToSkip;
125 int nrEntitiesPerBatch;
126 int minNrEntitiesInFirstBatch;
129 nrBatchesToProcess = ParameterExpander.evaluateIntegerExpressionWithDefault( aValueMap, nrBatchesToProcessExpression, -1 );
131 expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
132 expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
134 nrEntitiesToSkip = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesToSkipExpression);
135 nrEntitiesPerBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesPerBatchExpression);
136 minNrEntitiesInFirstBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, minNrEntitiesInFirstBatchExpression);
138 batchesData = new Vector();
139 batchLocations = new Vector();
141 nrEntities = model.getMappingForName(definition).getStorage().getSize(expandedWhereClause)-nrEntitiesToSkip;
142 nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch;
143 while (nrEntitiesInFirstBatch<minNrEntitiesInFirstBatch && nrEntities-nrEntitiesInFirstBatch>=nrEntitiesPerBatch)
144 nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch;
145 nrBatchesAfterFirst = (nrEntities-nrEntitiesInFirstBatch)/nrEntitiesPerBatch;
147 batchLocations.add(new BatchLocation(nrBatchesAfterFirst*nrEntitiesPerBatch, nrEntitiesInFirstBatch));
148 batchData = new HashMap();
149 batchData.put("identifier", "");
150 batchData.put("index", new Integer(nrBatchesAfterFirst+1));
151 batchData.put("size", new Integer(nrEntitiesInFirstBatch));
152 batchesData.add(batchData);
154 for (i=0; i<nrBatchesAfterFirst; i++) {
155 batchLocations.add(1, new BatchLocation(i*nrEntitiesPerBatch, nrEntitiesPerBatch));
156 batchData = new HashMap();
157 batchData.put("identifier", new Integer(i));
158 batchData.put("index", new Integer(i+1));
159 batchData.put("size", new Integer(nrEntitiesPerBatch));
160 batchesData.add(1, batchData);
163 batchData = new HashMap();
164 ParameterExpander.setValueForKey(aValueMap, batchInfoKey, batchData);
165 batchData.put("all", batchesData);
166 batchData.put("first", batchesData.get(0));
167 batchData.put("last", batchesData.get(batchesData.size()-1));
168 batchData.put("count", new Integer(batchesData.size()));
170 if (batchListSubNode!=null && (!isAborted(aValueMap))) {
171 batchListSubNode.produce(aValueMap, aVerb, aLogger);
174 if (nrBatchesToProcess<0 || nrBatchesToProcess>nrBatchesAfterFirst+1) {
175 nrBatchesToProcess = nrBatchesAfterFirst+1;
178 if (batchSubNode!=null) {
179 for (i=0; i<nrBatchesToProcess && !isAborted(aValueMap); i++) {
180 location = (BatchLocation) batchLocations.get(i);
182 batchData.put("current", batchesData.get(i));
184 batchData.put("previous", batchesData.get(i-1));
186 batchData.put("previous", null);
188 if (i<batchesData.size()-1)
189 batchData.put("next", batchesData.get(i+1));
191 batchData.put("next", null);
193 Iterator j = new EntityIteratorAdapter(expandedWhereClause, expandedOrderByClause,
194 location.nrEntities, model, definition, location.nrEntities, location.firstEntity);
195 List entities = new Vector();
198 entities.add(0, j.next());
200 ParameterExpander.setValueForKey(aValueMap, batchDataKey, entities );
202 batchSubNode.produce(aValueMap, aVerb, aLogger);
206 catch (Throwable t) {
207 aLogger.error("EntityBatchingProducerNode caused an exception: " + t.getMessage());
211 private class BatchLocation {
215 public BatchLocation(int aFirstEntity, int aNrEntities) {
216 firstEntity = aFirstEntity;
217 nrEntities = aNrEntities;