KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > webharvest > runtime > processors > LoopProcessor


1 /* Copyright (c) 2006-2007, Vladimir Nikic
2     All rights reserved.
3
4     Redistribution and use of this software in source and binary forms,
5     with or without modification, are permitted provided that the following
6     conditions are met:
7
8     * Redistributions of source code must retain the above
9       copyright notice, this list of conditions and the
10       following disclaimer.
11
12     * Redistributions in binary form must reproduce the above
13       copyright notice, this list of conditions and the
14       following disclaimer in the documentation and/or other
15       materials provided with the distribution.
16
17     * The name of Web-Harvest may not be used to endorse or promote
18       products derived from this software without specific prior
19       written permission.
20
21     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24     ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31     POSSIBILITY OF SUCH DAMAGE.
32
33     You can contact Vladimir Nikic by sending e-mail to
34     nikic_vladimir@yahoo.com. Please include the word "Web-Harvest" in the
35     subject line.
36 */

37 package org.webharvest.runtime.processors;
38
39 import org.webharvest.definition.BaseElementDef;
40 import org.webharvest.definition.LoopDef;
41 import org.webharvest.runtime.Scraper;
42 import org.webharvest.runtime.ScraperContext;
43 import org.webharvest.runtime.scripting.ScriptEngine;
44 import org.webharvest.runtime.templaters.BaseTemplater;
45 import org.webharvest.runtime.variables.*;
46 import org.webharvest.utils.CommonUtil;
47 import org.webharvest.utils.Constants;
48
49 import java.util.*;
50 import java.util.regex.Matcher JavaDoc;
51 import java.util.regex.Pattern JavaDoc;
52
53 /**
54  * Loop list processor.
55  */

56 public class LoopProcessor extends BaseProcessor {
57
58     private LoopDef loopDef;
59
60     public LoopProcessor(LoopDef loopDef) {
61         super(loopDef);
62         this.loopDef = loopDef;
63     }
64
65     public IVariable execute(Scraper scraper, ScraperContext context) {
66         ScriptEngine scriptEngine = scraper.getScriptEngine();
67         String JavaDoc item = BaseTemplater.execute( loopDef.getItem(), scriptEngine);
68         String JavaDoc index = BaseTemplater.execute( loopDef.getIndex(), scriptEngine);
69         String JavaDoc maxLoopsString = BaseTemplater.execute( loopDef.getMaxloops(), scriptEngine);
70         String JavaDoc filter = BaseTemplater.execute( loopDef.getFilter(), scriptEngine);
71
72         double maxLoops = Constants.DEFAULT_MAX_LOOPS;
73         if (maxLoopsString != null && !"".equals(maxLoopsString.trim())) {
74             maxLoops = Double.parseDouble(maxLoopsString);
75         }
76
77         BaseElementDef loopValueDef = loopDef.getLoopValueDef();
78         IVariable loopValue = getBodyListContent(loopValueDef, scraper, context);
79         debug(loopValueDef, scraper, loopValue);
80
81         List resultList = new ArrayList();
82
83         List list = loopValue != null ? loopValue.toList() : null;
84         if (list != null) {
85             IVariable itemBeforeLoop = (IVariable) context.get(item);
86             IVariable indexBeforeLoop = (IVariable) context.get(index);
87
88             List filteredList = filter != null ? createFilteredList(list, filter) : list;
89             Iterator it = filteredList.iterator();
90
91             for (int i = 1; it.hasNext() && i <= maxLoops; i++) {
92                 IVariable currElement = (IVariable) it.next();
93
94                 // define current value of item variable
95
if ( item != null && !"".equals(item) ) {
96                     context.put(item, currElement);
97                 }
98
99                 // define current value of index variable
100
if ( index != null && !"".equals(index) ) {
101                     context.put( index, new NodeVariable(String.valueOf(i)) );
102                 }
103
104                 // execute the loop body
105
BaseElementDef bodyDef = loopDef.getLoopBodyDef();
106                 IVariable loopResult = bodyDef != null ? getBodyListContent(bodyDef, scraper, context) : new EmptyVariable();
107                 debug(bodyDef, scraper, loopResult);
108                 resultList.addAll( loopResult.toList() );
109             }
110
111             // restores previous value of item variable
112
if (item != null && itemBeforeLoop != null) {
113                 context.put(item, itemBeforeLoop);
114             }
115
116             // restores previous value of index variable
117
if (index != null && indexBeforeLoop != null) {
118                 context.put(index, indexBeforeLoop);
119             }
120         }
121
122         return new ListVariable(resultList);
123     }
124
125     /**
126      * Create filtered list based on specified list and filterStr
127      * @param list
128      * @param filterStr
129      * @return Filtered list
130      */

131     private List createFilteredList(List list, String JavaDoc filterStr) {
132         List result = new ArrayList();
133         Set stringSet = new HashSet();
134
135         Filter filter = new Filter(filterStr, list.size());
136
137         Iterator it = list.iterator();
138         int index = 1;
139         while (it.hasNext()) {
140             IVariable curr = (IVariable) it.next();
141
142             if (filter.isInFilter(index)) {
143                 if (filter.isUnique) {
144                     String JavaDoc currStr = curr.toString();
145                     if (!stringSet.contains(curr.toString())) {
146                         result.add(curr);
147                         stringSet.add(currStr);
148                     }
149                 } else {
150                     result.add(curr);
151                 }
152             }
153
154             index++;
155         }
156
157         return result;
158     }
159
160     /**
161      * x - starting index in range
162      * y - ending index in range
163      */

164     private static class IntRange extends CommonUtil.IntPair {
165
166         // checks if strins is in form [n][-][m]
167
static boolean isValid(String JavaDoc s) {
168             Pattern JavaDoc pattern = Pattern.compile("(\\d*)(-?)(\\d*?)");
169             Matcher JavaDoc matcher = pattern.matcher(s);
170             return matcher.matches();
171         }
172
173         private IntRange(int x, int y) {
174             super(x, y);
175         }
176
177         public IntRange(String JavaDoc s, int size) {
178             defineFromString(s, '-', size);
179         }
180
181         public boolean isInRange(int index) {
182             return index >= x && index <= y;
183         }
184
185     }
186
187     /**
188      * x - starting index
189      * y - index skip - x is first, x+y second, x+2y third, end so on.
190      */

191     private static class IntSublist extends CommonUtil.IntPair {
192
193         // checks if strins is in form [n][:][m]
194
static boolean isValid(String JavaDoc s) {
195             Pattern JavaDoc pattern = Pattern.compile("(\\d*)(:?)(\\d*?)");
196             Matcher JavaDoc matcher = pattern.matcher(s);
197             return matcher.matches();
198         }
199
200         private IntSublist(int x, int y) {
201             super(x, y);
202         }
203
204         public IntSublist(String JavaDoc s, int size) {
205             defineFromString(s, ':', size);
206         }
207
208
209         public boolean isInSublist(int index) {
210             return (index - x) % y == 0;
211         }
212
213     }
214
215    /**
216      * Class that represents filter for list filtering. It is created based on filter string.
217      * Filter string is comma separated list of filter tokens. Valid filter tokens are:
218      * m - specific integer m
219      * m-n - integers in specified range, if m is ommited it's vaue is 1, if n is
220      * ommited it's value is specified size of list to be filtered
221      * m:n - all integerers starting from m and all subsequent with step n,
222      * m, m+1*n , m+2*n, ...
223      * odd - the same as 1:2
224      * even - the same as 2:2
225      * unique - tells that list must contain unique values (no duplicates)
226      */

227     private static class Filter {
228
229         private boolean isUnique = false;
230         private List filterList;
231
232         private Filter(String JavaDoc filterStr, int size) {
233             StringTokenizer tokenizer = new StringTokenizer(filterStr, ",");
234             filterList = new ArrayList();
235             
236             while (tokenizer.hasMoreTokens()) {
237                 String JavaDoc token = tokenizer.nextToken().trim();
238
239                 if ("unique".equals(token)) {
240                     isUnique = true;
241                 } else if ("odd".equals(token)) {
242                     filterList.add(new IntSublist(1, 2));
243                 } else if ("even".equals(token)) {
244                     filterList.add( new IntSublist(2, 2));
245                 } else if (IntRange.isValid(token)) {
246                     filterList.add(new IntRange(token, size));
247                 } else if (IntSublist.isValid(token)) {
248                     filterList.add(new IntSublist(token, size));
249                 }
250             }
251         }
252
253         /**
254          * Checks if specified integer passes the filter
255          */

256         private boolean isInFilter(int num) {
257             int listSize = filterList.size();
258             
259             if (listSize == 0) {
260                 return true;
261             }
262             
263             for (int i = 0; i < listSize; i++) {
264                 CommonUtil.IntPair curr = (CommonUtil.IntPair) filterList.get(i);
265                 if ( curr instanceof IntRange && ((IntRange)curr).isInRange(num) ) {
266                     return true;
267                 } else if ( curr instanceof IntSublist && ((IntSublist)curr).isInSublist(num) ) {
268                     return true;
269                 }
270             }
271
272             return false;
273         }
274
275     }
276
277 }
Popular Tags