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.ArrayList;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
38 import mir.entity.adapter.EntityAdapterModel;
39 import mir.entity.adapter.EntityIteratorAdapter;
40 import mir.log.LoggerWrapper;
41 import mir.util.ParameterExpander;
42 import mir.util.StringRoutines;
45 * <p>Title: EntityBatchingProducerNode</p>
47 * This producer makes it possible to show articles in batches, like on archive
50 * <emph> The order by clause should lead to a result set in <b>reverse order<b>:
51 * the first row will be the last entity in the last batch
53 * <p>Copyright: Copyright (c) 2003</p>
55 * @author not attributable
59 public class EntityBatchingProducerNode implements ProducerNode {
60 private String batchInfoKey;
61 private String batchDataKey;
62 private EntityAdapterModel model;
63 private String mainTablePrefix;
64 private String extraTables;
65 private String definition;
66 private String whereClause;
67 private String orderByClause;
68 private String nrEntitiesToSkipExpression;
69 private String nrEntitiesPerBatchExpression;
70 private String minNrEntitiesInFirstBatchExpression;
71 private String nrBatchesToProcessExpression;
72 private ProducerNode batchSubNode;
73 private ProducerNode batchListSubNode;
75 public EntityBatchingProducerNode(
78 EntityAdapterModel aModel,
79 String aMainTablePrefix,
80 String someExtraTables,
83 String anOrderByClause,
84 String anrEntitiesPerBatchExpression,
85 String aminNrEntitiesInFirstBatchExpression,
86 String anrEntitiesToSkipExpression,
87 String aNrBatchesToProcessExpression,
88 ProducerNode aBatchSubNode,
89 ProducerNode aBatchListSubNode) {
91 batchSubNode = aBatchSubNode;
92 batchListSubNode = aBatchListSubNode;
94 batchDataKey = aBatchDataKey;
95 batchInfoKey = aBatchInfoKey;
97 mainTablePrefix = aMainTablePrefix;
98 extraTables = someExtraTables;
99 definition = aDefinition;
100 whereClause = aWhereClause;
101 orderByClause = anOrderByClause;
102 nrEntitiesToSkipExpression = anrEntitiesToSkipExpression;
103 nrEntitiesPerBatchExpression = anrEntitiesPerBatchExpression;
104 minNrEntitiesInFirstBatchExpression = aminNrEntitiesInFirstBatchExpression;
105 nrBatchesToProcessExpression = aNrBatchesToProcessExpression;
108 protected boolean isAborted(Map aValueMap) {
109 Object producerValue = aValueMap.get(NodedProducer.PRODUCER_KEY);
111 (producerValue instanceof NodedProducer) &&
112 ((NodedProducer) producerValue).getIsAborted());
115 public void produce(Map aValueMap, String aVerb, LoggerWrapper aLogger) throws ProducerFailure {
117 int nrBatchesAfterFirst;
118 int nrEntitiesInFirstBatch;
119 int nrBatchesToProcess;
123 String expandedWhereClause;
124 String expandedOrderByClause;
127 BatchLocation location;
129 int nrEntitiesToSkip;
130 int nrEntitiesPerBatch;
131 int minNrEntitiesInFirstBatch;
134 nrBatchesToProcess = ParameterExpander.evaluateIntegerExpressionWithDefault( aValueMap, nrBatchesToProcessExpression, -1 );
136 expandedWhereClause = ParameterExpander.expandExpression( aValueMap, whereClause );
137 expandedOrderByClause = ParameterExpander.expandExpression( aValueMap, orderByClause );
139 nrEntitiesToSkip = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesToSkipExpression);
140 nrEntitiesPerBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, nrEntitiesPerBatchExpression);
141 minNrEntitiesInFirstBatch = ParameterExpander.evaluateIntegerExpression( aValueMap, minNrEntitiesInFirstBatchExpression);
142 List extraTableList = StringRoutines.splitString(ParameterExpander.expandExpression( aValueMap, extraTables).trim(), ",");
144 batchesData = new ArrayList();
145 batchLocations = new ArrayList();
147 nrEntities = model.getMappingForName(definition).getDatabase().getSize(
148 mainTablePrefix, extraTableList, expandedWhereClause)-nrEntitiesToSkip;
149 nrEntitiesInFirstBatch = nrEntities % nrEntitiesPerBatch;
150 while (nrEntitiesInFirstBatch<minNrEntitiesInFirstBatch && nrEntities-nrEntitiesInFirstBatch>=nrEntitiesPerBatch)
151 nrEntitiesInFirstBatch = nrEntitiesInFirstBatch + nrEntitiesPerBatch;
152 nrBatchesAfterFirst = (nrEntities-nrEntitiesInFirstBatch)/nrEntitiesPerBatch;
154 batchLocations.add(new BatchLocation(nrBatchesAfterFirst*nrEntitiesPerBatch, nrEntitiesInFirstBatch));
155 batchData = new HashMap();
156 batchData.put("identifier", "");
157 batchData.put("index", new Integer(nrBatchesAfterFirst+1));
158 batchData.put("size", new Integer(nrEntitiesInFirstBatch));
159 batchesData.add(batchData);
161 for (i=0; i<nrBatchesAfterFirst; i++) {
162 batchLocations.add(1, new BatchLocation(i*nrEntitiesPerBatch, nrEntitiesPerBatch));
163 batchData = new HashMap();
164 batchData.put("identifier", new Integer(i));
165 batchData.put("index", new Integer(i+1));
166 batchData.put("size", new Integer(nrEntitiesPerBatch));
167 batchesData.add(1, batchData);
170 batchData = new HashMap();
171 ParameterExpander.setValueForKey(aValueMap, batchInfoKey, batchData);
172 batchData.put("all", batchesData);
173 batchData.put("first", batchesData.get(0));
174 batchData.put("last", batchesData.get(batchesData.size()-1));
175 batchData.put("count", new Integer(batchesData.size()));
177 if (batchListSubNode!=null && (!isAborted(aValueMap))) {
178 batchListSubNode.produce(aValueMap, aVerb, aLogger);
181 if (nrBatchesToProcess<0 || nrBatchesToProcess>nrBatchesAfterFirst+1) {
182 nrBatchesToProcess = nrBatchesAfterFirst+1;
185 if (batchSubNode!=null) {
186 for (i=0; i<nrBatchesToProcess && !isAborted(aValueMap); i++) {
187 location = (BatchLocation) batchLocations.get(i);
189 batchData.put("current", batchesData.get(i));
191 batchData.put("previous", batchesData.get(i-1));
193 batchData.put("previous", null);
195 if (i<batchesData.size()-1)
196 batchData.put("next", batchesData.get(i+1));
198 batchData.put("next", null);
200 Iterator j = new EntityIteratorAdapter(mainTablePrefix, extraTableList, expandedWhereClause, expandedOrderByClause,
201 location.nrEntities, model, definition, location.nrEntities, location.firstEntity);
202 List entities = new ArrayList();
205 entities.add(0, j.next());
207 ParameterExpander.setValueForKey(aValueMap, batchDataKey, entities );
209 batchSubNode.produce(aValueMap, aVerb, aLogger);
213 catch (Throwable t) {
214 aLogger.error("EntityBatchingProducerNode caused an exception: " + t.getMessage());
218 private class BatchLocation {
222 public BatchLocation(int aFirstEntity, int aNrEntities) {
223 firstEntity = aFirstEntity;
224 nrEntities = aNrEntities;