Source Code Cross Referenced for SequenceBuiltins.java in  » Template-Engine » freemarker-2.3.10 » freemarker » core » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Template Engine » freemarker 2.3.10 » freemarker.core 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2003 The Visigoth Software Society. All rights
003:         * reserved.
004:         *
005:         * Redistribution and use in source and binary forms, with or without
006:         * modification, are permitted provided that the following conditions
007:         * are met:
008:         *
009:         * 1. Redistributions of source code must retain the above copyright
010:         *    notice, this list of conditions and the following disclaimer.
011:         *
012:         * 2. Redistributions in binary form must reproduce the above copyright
013:         *    notice, this list of conditions and the following disclaimer in
014:         *    the documentation and/or other materials provided with the
015:         *    distribution.
016:         *
017:         * 3. The end-user documentation included with the redistribution, if
018:         *    any, must include the following acknowledgement:
019:         *       "This product includes software developed by the
020:         *        Visigoth Software Society (http://www.visigoths.org/)."
021:         *    Alternately, this acknowledgement may appear in the software itself,
022:         *    if and wherever such third-party acknowledgements normally appear.
023:         *
024:         * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025:         *    project contributors may be used to endorse or promote products derived
026:         *    from this software without prior written permission. For written
027:         *    permission, please contact visigoths@visigoths.org.
028:         *
029:         * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030:         *    nor may "FreeMarker" or "Visigoth" appear in their names
031:         *    without prior written permission of the Visigoth Software Society.
032:         *
033:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036:         * DISCLAIMED.  IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044:         * SUCH DAMAGE.
045:         * ====================================================================
046:         *
047:         * This software consists of voluntary contributions made by many
048:         * individuals on behalf of the Visigoth Software Society. For more
049:         * information on the Visigoth Software Society, please see
050:         * http://www.visigoths.org/
051:         */
052:
053:        package freemarker.core;
054:
055:        import java.text.Collator;
056:        import java.util.ArrayList;
057:        import java.util.Collections;
058:        import java.util.Comparator;
059:        import java.util.Date;
060:        import java.util.List;
061:
062:        import freemarker.template.SimpleNumber;
063:        import freemarker.template.TemplateBooleanModel;
064:        import freemarker.template.TemplateDateModel;
065:        import freemarker.template.TemplateException;
066:        import freemarker.template.TemplateHashModel;
067:        import freemarker.template.TemplateMethodModelEx;
068:        import freemarker.template.TemplateModel;
069:        import freemarker.template.TemplateModelException;
070:        import freemarker.template.TemplateModelListSequence;
071:        import freemarker.template.TemplateNumberModel;
072:        import freemarker.template.TemplateScalarModel;
073:        import freemarker.template.TemplateSequenceModel;
074:        import freemarker.template.TemplateCollectionModel;
075:        import freemarker.template.TemplateModelIterator;
076:        import freemarker.template.utility.Constants;
077:        import freemarker.template.utility.StringUtil;
078:
079:        /**
080:         * A holder for builtins that operate exclusively on TemplateSequenceModels.
081:         */
082:
083:        abstract class SequenceBuiltins {
084:            abstract static class SequenceBuiltIn extends BuiltIn {
085:                TemplateModel _getAsTemplateModel(Environment env)
086:                        throws TemplateException {
087:                    TemplateModel model = target.getAsTemplateModel(env);
088:                    if (!(model instanceof  TemplateSequenceModel)) {
089:                        throw invalidTypeException(model, target, env,
090:                                "sequence");
091:                    }
092:                    return calculateResult((TemplateSequenceModel) model);
093:                }
094:
095:                abstract TemplateModel calculateResult(TemplateSequenceModel tsm)
096:                        throws TemplateModelException;
097:            }
098:
099:            static class firstBI extends SequenceBuiltIn {
100:                TemplateModel calculateResult(TemplateSequenceModel tsm)
101:                        throws TemplateModelException {
102:                    if (tsm.size() == 0) {
103:                        return null;
104:                    }
105:                    return tsm.get(0);
106:                }
107:            }
108:
109:            static class lastBI extends SequenceBuiltIn {
110:                TemplateModel calculateResult(TemplateSequenceModel tsm)
111:                        throws TemplateModelException {
112:                    if (tsm.size() == 0) {
113:                        return null;
114:                    }
115:                    return tsm.get(tsm.size() - 1);
116:                }
117:            }
118:
119:            static class reverseBI extends SequenceBuiltIn {
120:                TemplateModel calculateResult(TemplateSequenceModel tsm) {
121:                    if (tsm instanceof  ReverseSequence) {
122:                        return ((ReverseSequence) tsm).seq;
123:                    } else {
124:                        return new ReverseSequence(tsm);
125:                    }
126:                }
127:
128:                private static class ReverseSequence implements 
129:                        TemplateSequenceModel {
130:                    private final TemplateSequenceModel seq;
131:
132:                    ReverseSequence(TemplateSequenceModel seq) {
133:                        this .seq = seq;
134:                    }
135:
136:                    public int size() throws TemplateModelException {
137:                        return seq.size();
138:                    }
139:
140:                    public TemplateModel get(int index)
141:                            throws TemplateModelException {
142:                        return seq.get(seq.size() - 1 - index);
143:                    }
144:                }
145:            }
146:
147:            static class sortBI extends SequenceBuiltIn {
148:
149:                static final int KEY_TYPE_STRING = 1;
150:                static final int KEY_TYPE_NUMBER = 2;
151:                static final int KEY_TYPE_DATE = 3;
152:
153:                TemplateModel calculateResult(TemplateSequenceModel seq)
154:                        throws TemplateModelException {
155:                    return sort(seq, null);
156:                }
157:
158:                static String startErrorMessage(Object keys) {
159:                    return (keys == null ? "?sort" : "?sort_by(...)")
160:                            + " failed: ";
161:                }
162:
163:                /**
164:                 * Sorts a sequence for the <tt>sort</tt> and <tt>sort_by</tt>
165:                 * built-ins.
166:                 * 
167:                 * @param seq the sequence to sort.
168:                 * @param keys the name of the subvariable whose value is used for the
169:                 *     sorting. If the sorting is done by a sub-subvaruable, then this
170:                 *     will be of length 2, and so on. If the sorting is done by the
171:                 *     sequene items directly, then this argument has to be 0 length
172:                 *     array or <code>null</code>.
173:                 * @return a new sorted sequence, or the original sequence if the
174:                 *     sequence length was 0.
175:                 */
176:                static TemplateSequenceModel sort(TemplateSequenceModel seq,
177:                        String[] keys) throws TemplateModelException {
178:                    int i;
179:                    int keyCnt;
180:
181:                    int ln = seq.size();
182:                    if (ln == 0) {
183:                        return seq;
184:                    }
185:
186:                    List res = new ArrayList(ln);
187:                    Object item;
188:                    item = seq.get(0);
189:                    if (keys != null) {
190:                        keyCnt = keys.length;
191:                        if (keyCnt == 0) {
192:                            keys = null;
193:                        } else {
194:                            for (i = 0; i < keyCnt; i++) {
195:                                if (!(item instanceof  TemplateHashModel)) {
196:                                    throw new TemplateModelException(
197:                                            startErrorMessage(keys)
198:                                                    + (i == 0 ? "You can't use ?sort_by when the "
199:                                                            + "sequence items are not hashes."
200:                                                            : "The subvariable "
201:                                                                    + StringUtil
202:                                                                            .jQuote(keys[i - 1])
203:                                                                    + " is not a hash, so ?sort_by "
204:                                                                    + "can't proceed by getting the "
205:                                                                    + StringUtil
206:                                                                            .jQuote(keys[i])
207:                                                                    + " subvariable."));
208:                                }
209:
210:                                item = ((TemplateHashModel) item).get(keys[i]);
211:                                if (item == null) {
212:                                    throw new TemplateModelException(
213:                                            startErrorMessage(keys)
214:                                                    + "The "
215:                                                    + StringUtil
216:                                                            .jQuote(keys[i])
217:                                                    + " subvariable "
218:                                                    + (keyCnt == 1 ? "was not found."
219:                                                            : "(specified by ?sort_by argument number "
220:                                                                    + (i + 1)
221:                                                                    + ") was not found."));
222:                                }
223:                            }
224:                        }
225:                    } else {
226:                        keyCnt = 0;
227:                    }
228:
229:                    int keyType;
230:                    if (item instanceof  TemplateScalarModel) {
231:                        keyType = KEY_TYPE_STRING;
232:                    } else if (item instanceof  TemplateNumberModel) {
233:                        keyType = KEY_TYPE_NUMBER;
234:                    } else if (item instanceof  TemplateDateModel) {
235:                        keyType = KEY_TYPE_DATE;
236:                    } else {
237:                        throw new TemplateModelException(
238:                                startErrorMessage(keys)
239:                                        + "Values used for sorting must be numbers, strings, or date/time values.");
240:                    }
241:
242:                    if (keys == null) {
243:                        if (keyType == KEY_TYPE_STRING) {
244:                            for (i = 0; i < ln; i++) {
245:                                item = seq.get(i);
246:                                try {
247:                                    res.add(new KVP(
248:                                            ((TemplateScalarModel) item)
249:                                                    .getAsString(), item));
250:                                } catch (ClassCastException e) {
251:                                    if (!(item instanceof  TemplateScalarModel)) {
252:                                        throw new TemplateModelException(
253:                                                startErrorMessage(keys)
254:                                                        + "All values in the sequence must be "
255:                                                        + "strings, because the first value "
256:                                                        + "was a string. "
257:                                                        + "The value at index "
258:                                                        + i + " is not string.");
259:                                    } else {
260:                                        throw e;
261:                                    }
262:                                }
263:                            }
264:                        } else if (keyType == KEY_TYPE_NUMBER) {
265:                            for (i = 0; i < ln; i++) {
266:                                item = seq.get(i);
267:                                try {
268:                                    res.add(new KVP(
269:                                            ((TemplateNumberModel) item)
270:                                                    .getAsNumber(), item));
271:                                } catch (ClassCastException e) {
272:                                    if (!(item instanceof  TemplateNumberModel)) {
273:                                        throw new TemplateModelException(
274:                                                startErrorMessage(keys)
275:                                                        + "All values in the sequence must be "
276:                                                        + "numbers, because the first value "
277:                                                        + "was a number. "
278:                                                        + "The value at index "
279:                                                        + i + " is not number.");
280:                                    } else {
281:                                        throw e;
282:                                    }
283:                                }
284:                            }
285:                        } else if (keyType == KEY_TYPE_DATE) {
286:                            for (i = 0; i < ln; i++) {
287:                                item = seq.get(i);
288:                                try {
289:                                    res.add(new KVP(((TemplateDateModel) item)
290:                                            .getAsDate(), item));
291:                                } catch (ClassCastException e) {
292:                                    if (!(item instanceof  TemplateNumberModel)) {
293:                                        throw new TemplateModelException(
294:                                                startErrorMessage(keys)
295:                                                        + "All values in the sequence must be "
296:                                                        + "date/time values, because the first "
297:                                                        + "value was a date/time. "
298:                                                        + "The value at index "
299:                                                        + i
300:                                                        + " is not date/time.");
301:                                    } else {
302:                                        throw e;
303:                                    }
304:                                }
305:                            }
306:                        } else {
307:                            throw new RuntimeException(
308:                                    "FreeMarker bug: Bad key type");
309:                        }
310:                    } else {
311:                        for (i = 0; i < ln; i++) {
312:                            item = seq.get(i);
313:                            Object key = item;
314:                            for (int j = 0; j < keyCnt; j++) {
315:                                try {
316:                                    key = ((TemplateHashModel) key)
317:                                            .get(keys[j]);
318:                                } catch (ClassCastException e) {
319:                                    if (!(key instanceof  TemplateHashModel)) {
320:                                        throw new TemplateModelException(
321:                                                startErrorMessage(keys)
322:                                                        + "Problem with the sequence item at index "
323:                                                        + i
324:                                                        + ": "
325:                                                        + "Can't get the "
326:                                                        + StringUtil
327:                                                                .jQuote(keys[j])
328:                                                        + " subvariable, because the value is not a hash.");
329:                                    } else {
330:                                        throw e;
331:                                    }
332:                                }
333:                                if (key == null) {
334:                                    throw new TemplateModelException(
335:                                            startErrorMessage(keys)
336:                                                    + "Problem with the sequence item at index "
337:                                                    + i
338:                                                    + ": "
339:                                                    + "The "
340:                                                    + StringUtil
341:                                                            .jQuote(keys[j])
342:                                                    + " subvariable was not found.");
343:                                }
344:                            }
345:                            if (keyType == KEY_TYPE_STRING) {
346:                                try {
347:                                    res.add(new KVP(((TemplateScalarModel) key)
348:                                            .getAsString(), item));
349:                                } catch (ClassCastException e) {
350:                                    if (!(key instanceof  TemplateScalarModel)) {
351:                                        throw new TemplateModelException(
352:                                                startErrorMessage(keys)
353:                                                        + "All key values in the sequence must be "
354:                                                        + "date/time values, because the first key "
355:                                                        + "value was a date/time. The key value at "
356:                                                        + "index "
357:                                                        + i
358:                                                        + " is not a date/time.");
359:                                    } else {
360:                                        throw e;
361:                                    }
362:                                }
363:                            } else if (keyType == KEY_TYPE_NUMBER) {
364:                                try {
365:                                    res.add(new KVP(((TemplateNumberModel) key)
366:                                            .getAsNumber(), item));
367:                                } catch (ClassCastException e) {
368:                                    if (!(key instanceof  TemplateNumberModel)) {
369:                                        throw new TemplateModelException(
370:                                                startErrorMessage(keys)
371:                                                        + "All key values in the sequence must be "
372:                                                        + "numbers, because the first key "
373:                                                        + "value was a number. The key value at "
374:                                                        + "index " + i
375:                                                        + " is not a number.");
376:                                    }
377:                                }
378:                            } else if (keyType == KEY_TYPE_DATE) {
379:                                try {
380:                                    res.add(new KVP(((TemplateDateModel) key)
381:                                            .getAsDate(), item));
382:                                } catch (ClassCastException e) {
383:                                    if (!(key instanceof  TemplateDateModel)) {
384:                                        throw new TemplateModelException(
385:                                                startErrorMessage(keys)
386:                                                        + "All key values in the sequence must be "
387:                                                        + "dates, because the first key "
388:                                                        + "value was a date. The key value at "
389:                                                        + "index " + i
390:                                                        + " is not a date.");
391:                                    }
392:                                }
393:                            } else {
394:                                throw new RuntimeException(
395:                                        "FreeMarker bug: Bad key type");
396:                            }
397:                        }
398:                    }
399:
400:                    Comparator cmprtr;
401:                    if (keyType == KEY_TYPE_STRING) {
402:                        cmprtr = new LexicalKVPComparator(Environment
403:                                .getCurrentEnvironment().getCollator());
404:                    } else if (keyType == KEY_TYPE_NUMBER) {
405:                        cmprtr = new NumericalKVPComparator(Environment
406:                                .getCurrentEnvironment().getArithmeticEngine());
407:                    } else if (keyType == KEY_TYPE_DATE) {
408:                        cmprtr = new DateKVPComparator();
409:                    } else {
410:                        throw new RuntimeException(
411:                                "FreeMarker bug: Bad key type");
412:                    }
413:
414:                    try {
415:                        Collections.sort(res, cmprtr);
416:                    } catch (ClassCastException exc) {
417:                        throw new TemplateModelException(
418:                                startErrorMessage(keys)
419:                                        + "Unexpected error while sorting:"
420:                                        + exc, exc);
421:                    }
422:
423:                    for (i = 0; i < ln; i++) {
424:                        res.set(i, ((KVP) res.get(i)).value);
425:                    }
426:
427:                    return new TemplateModelListSequence(res);
428:                }
429:
430:                private static class KVP {
431:                    private KVP(Object key, Object value) {
432:                        this .key = key;
433:                        this .value = value;
434:                    }
435:
436:                    private Object key;
437:                    private Object value;
438:                }
439:
440:                private static class NumericalKVPComparator implements 
441:                        Comparator {
442:                    private ArithmeticEngine ae;
443:
444:                    private NumericalKVPComparator(ArithmeticEngine ae) {
445:                        this .ae = ae;
446:                    }
447:
448:                    public int compare(Object arg0, Object arg1) {
449:                        try {
450:                            return ae.compareNumbers((Number) ((KVP) arg0).key,
451:                                    (Number) ((KVP) arg1).key);
452:                        } catch (TemplateException e) {
453:                            throw new ClassCastException(
454:                                    "Failed to compare numbers: " + e);
455:                        }
456:                    }
457:                }
458:
459:                private static class LexicalKVPComparator implements  Comparator {
460:                    private Collator collator;
461:
462:                    LexicalKVPComparator(Collator collator) {
463:                        this .collator = collator;
464:                    }
465:
466:                    public int compare(Object arg0, Object arg1) {
467:                        return collator.compare(((KVP) arg0).key,
468:                                ((KVP) arg1).key);
469:                    }
470:                }
471:
472:                private static class DateKVPComparator implements  Comparator {
473:
474:                    public int compare(Object arg0, Object arg1) {
475:                        return ((Date) ((KVP) arg0).key)
476:                                .compareTo((Date) ((KVP) arg1).key);
477:                    }
478:                }
479:
480:            }
481:
482:            static class sort_byBI extends sortBI {
483:                TemplateModel calculateResult(TemplateSequenceModel seq) {
484:                    return new BIMethod(seq);
485:                }
486:
487:                static class BIMethod implements  TemplateMethodModelEx {
488:                    TemplateSequenceModel seq;
489:
490:                    BIMethod(TemplateSequenceModel seq) {
491:                        this .seq = seq;
492:                    }
493:
494:                    public Object exec(List params)
495:                            throws TemplateModelException {
496:                        if (params.size() == 0) {
497:                            throw new TemplateModelException(
498:                                    "?sort_by(key) needs exactly 1 argument.");
499:                        }
500:                        String[] subvars;
501:                        Object obj = params.get(0);
502:                        if (obj instanceof  TemplateScalarModel) {
503:                            subvars = new String[] { ((TemplateScalarModel) obj)
504:                                    .getAsString() };
505:                        } else if (obj instanceof  TemplateSequenceModel) {
506:                            TemplateSequenceModel seq = (TemplateSequenceModel) obj;
507:                            int ln = seq.size();
508:                            subvars = new String[ln];
509:                            for (int i = 0; i < ln; i++) {
510:                                Object item = seq.get(i);
511:                                try {
512:                                    subvars[i] = ((TemplateScalarModel) item)
513:                                            .getAsString();
514:                                } catch (ClassCastException e) {
515:                                    if (!(item instanceof  TemplateScalarModel)) {
516:                                        throw new TemplateModelException(
517:                                                "The argument to ?sort_by(key), when it "
518:                                                        + "is a sequence, must be a sequence of "
519:                                                        + "strings, but the item at index "
520:                                                        + i
521:                                                        + " is not a string.");
522:                                    }
523:                                }
524:                            }
525:                        } else {
526:                            throw new TemplateModelException(
527:                                    "The argument to ?sort_by(key) must be a string "
528:                                            + "(the name of the subvariable), or a sequence of "
529:                                            + "strings (the \"path\" to the subvariable).");
530:                        }
531:                        return sort(seq, subvars);
532:                    }
533:                }
534:            }
535:
536:            static class seq_containsBI extends BuiltIn {
537:                TemplateModel _getAsTemplateModel(Environment env)
538:                        throws TemplateException {
539:                    TemplateModel model = target.getAsTemplateModel(env);
540:                    if (model instanceof  TemplateSequenceModel) {
541:                        return new BIMethodForSequence(
542:                                (TemplateSequenceModel) model, env);
543:                    } else if (model instanceof  TemplateCollectionModel) {
544:                        return new BIMethodForCollection(
545:                                (TemplateCollectionModel) model, env);
546:                    } else {
547:                        throw invalidTypeException(model, target, env,
548:                                "sequence or collection");
549:                    }
550:                }
551:
552:                private class BIMethodForSequence implements 
553:                        TemplateMethodModelEx {
554:                    private TemplateSequenceModel m_seq;
555:                    private Environment m_env;
556:
557:                    private BIMethodForSequence(TemplateSequenceModel seq,
558:                            Environment env) {
559:                        m_seq = seq;
560:                        m_env = env;
561:                    }
562:
563:                    public Object exec(List args) throws TemplateModelException {
564:                        if (args.size() != 1)
565:                            throw new TemplateModelException(
566:                                    "?seq_contains(...) expects one argument.");
567:                        TemplateModel arg = (TemplateModel) args.get(0);
568:                        int size = m_seq.size();
569:                        for (int i = 0; i < size; i++) {
570:                            if (modelsEqual(m_seq.get(i), arg, m_env))
571:                                return TemplateBooleanModel.TRUE;
572:                        }
573:                        return TemplateBooleanModel.FALSE;
574:                    }
575:
576:                }
577:
578:                private class BIMethodForCollection implements 
579:                        TemplateMethodModelEx {
580:                    private TemplateCollectionModel m_coll;
581:                    private Environment m_env;
582:
583:                    private BIMethodForCollection(TemplateCollectionModel coll,
584:                            Environment env) {
585:                        m_coll = coll;
586:                        m_env = env;
587:                    }
588:
589:                    public Object exec(List args) throws TemplateModelException {
590:                        if (args.size() != 1)
591:                            throw new TemplateModelException(
592:                                    "?seq_contains(...) expects one argument.");
593:                        TemplateModel arg = (TemplateModel) args.get(0);
594:                        TemplateModelIterator it = m_coll.iterator();
595:                        while (it.hasNext()) {
596:                            if (modelsEqual(it.next(), arg, m_env))
597:                                return TemplateBooleanModel.TRUE;
598:                        }
599:                        return TemplateBooleanModel.FALSE;
600:                    }
601:
602:                }
603:
604:            }
605:
606:            static class seq_index_ofBI extends BuiltIn {
607:                private int m_dir;
608:
609:                public seq_index_ofBI(int dir) {
610:                    m_dir = dir;
611:                }
612:
613:                TemplateModel _getAsTemplateModel(Environment env)
614:                        throws TemplateException {
615:                    TemplateModel model = target.getAsTemplateModel(env);
616:                    if (!(model instanceof  TemplateSequenceModel))
617:                        throw invalidTypeException(model, target, env,
618:                                "sequence");
619:                    return new BIMethod((TemplateSequenceModel) model, env);
620:                }
621:
622:                private class BIMethod implements  TemplateMethodModelEx {
623:                    private TemplateSequenceModel m_seq;
624:                    private Environment m_env;
625:
626:                    private BIMethod(TemplateSequenceModel seq, Environment env) {
627:                        m_seq = seq;
628:                        m_env = env;
629:                    }
630:
631:                    public Object exec(List args) throws TemplateModelException {
632:                        int argcnt = args.size();
633:                        if (argcnt != 1 && argcnt != 2) {
634:                            throw new TemplateModelException(
635:                                    getBuiltinTemplate()
636:                                            + " expects 1 or 2 arguments.");
637:                        }
638:
639:                        int startIndex;
640:                        int seqSize = m_seq.size();
641:                        TemplateModel arg = (TemplateModel) args.get(0);
642:                        if (argcnt > 1) {
643:                            Object obj = args.get(1);
644:                            if (!(obj instanceof  TemplateNumberModel)) {
645:                                throw new TemplateModelException(
646:                                        getBuiltinTemplate()
647:                                                + "expects a number as its second argument.");
648:                            }
649:                            startIndex = ((TemplateNumberModel) obj)
650:                                    .getAsNumber().intValue();
651:                            if (m_dir == 1) {
652:                                if (startIndex >= seqSize) {
653:                                    return Constants.MINUS_ONE;
654:                                }
655:                                if (startIndex < 0) {
656:                                    startIndex = 0;
657:                                }
658:                            } else {
659:                                if (startIndex >= seqSize) {
660:                                    startIndex = seqSize - 1;
661:                                }
662:                                if (startIndex < 0) {
663:                                    return Constants.MINUS_ONE;
664:                                }
665:                            }
666:                        } else {
667:                            if (m_dir == 1) {
668:                                startIndex = 0;
669:                            } else {
670:                                startIndex = seqSize - 1;
671:                            }
672:                        }
673:
674:                        if (m_dir == 1) {
675:                            for (int i = startIndex; i < seqSize; i++) {
676:                                if (modelsEqual(m_seq.get(i), arg, m_env))
677:                                    return new SimpleNumber(i);
678:                            }
679:                        } else {
680:                            for (int i = startIndex; i >= 0; i--) {
681:                                if (modelsEqual(m_seq.get(i), arg, m_env))
682:                                    return new SimpleNumber(i);
683:                            }
684:                        }
685:                        return Constants.MINUS_ONE;
686:                    }
687:
688:                    private String getBuiltinTemplate() {
689:                        if (m_dir == 1)
690:                            return "?seq_indexOf(...)";
691:                        else
692:                            return "?seq_lastIndexOf(...)";
693:                    }
694:                }
695:            }
696:
697:            static class chunkBI extends SequenceBuiltIn {
698:
699:                TemplateModel calculateResult(TemplateSequenceModel tsm)
700:                        throws TemplateModelException {
701:                    return new BIMethod(tsm);
702:                }
703:
704:                private static class BIMethod implements  TemplateMethodModelEx {
705:
706:                    private final TemplateSequenceModel tsm;
707:
708:                    private BIMethod(TemplateSequenceModel tsm) {
709:                        this .tsm = tsm;
710:                    }
711:
712:                    public Object exec(List args) throws TemplateModelException {
713:                        int numArgs = args.size();
714:                        if (numArgs != 1 && numArgs != 2) {
715:                            throw new TemplateModelException(
716:                                    "?chunk(...) expects 1 or 2 arguments.");
717:                        }
718:
719:                        Object chunkSize = args.get(0);
720:                        if (!(chunkSize instanceof  TemplateNumberModel)) {
721:                            throw new TemplateModelException(
722:                                    "?chunk(...) expects a number as "
723:                                            + "its 1st argument.");
724:                        }
725:
726:                        return new ChunkedSequence(tsm,
727:                                ((TemplateNumberModel) chunkSize).getAsNumber()
728:                                        .intValue(),
729:                                numArgs > 1 ? (TemplateModel) args.get(1)
730:                                        : null);
731:                    }
732:                }
733:
734:                private static class ChunkedSequence implements 
735:                        TemplateSequenceModel {
736:
737:                    private final TemplateSequenceModel wrappedTsm;
738:
739:                    private final int chunkSize;
740:
741:                    private final TemplateModel fillerItem;
742:
743:                    private final int numberOfChunks;
744:
745:                    private ChunkedSequence(TemplateSequenceModel wrappedTsm,
746:                            int chunkSize, TemplateModel fillerItem)
747:                            throws TemplateModelException {
748:                        if (chunkSize < 1) {
749:                            throw new TemplateModelException(
750:                                    "The 1st argument to ?chunk(...) must be at least 1.");
751:                        }
752:                        this .wrappedTsm = wrappedTsm;
753:                        this .chunkSize = chunkSize;
754:                        this .fillerItem = fillerItem;
755:                        numberOfChunks = (wrappedTsm.size() + chunkSize - 1)
756:                                / chunkSize;
757:                    }
758:
759:                    public TemplateModel get(final int chunkIndex)
760:                            throws TemplateModelException {
761:                        if (chunkIndex >= numberOfChunks) {
762:                            return null;
763:                        }
764:
765:                        return new TemplateSequenceModel() {
766:
767:                            private final int baseIndex = chunkIndex
768:                                    * chunkSize;
769:
770:                            public TemplateModel get(int relIndex)
771:                                    throws TemplateModelException {
772:                                int absIndex = baseIndex + relIndex;
773:                                if (absIndex < wrappedTsm.size()) {
774:                                    return wrappedTsm.get(absIndex);
775:                                } else {
776:                                    return absIndex < numberOfChunks
777:                                            * chunkSize ? fillerItem : null;
778:                                }
779:                            }
780:
781:                            public int size() throws TemplateModelException {
782:                                return fillerItem != null
783:                                        || chunkIndex + 1 < numberOfChunks ? chunkSize
784:                                        : wrappedTsm.size() - baseIndex;
785:                            }
786:
787:                        };
788:                    }
789:
790:                    public int size() throws TemplateModelException {
791:                        return numberOfChunks;
792:                    }
793:
794:                }
795:
796:            }
797:
798:            /*
799:             * WARNING! This algorithm is duplication of ComparisonExpression.isTrue(...).
800:             * Thus, if you update this method, then you have to update that too!
801:             */
802:            public static boolean modelsEqual(TemplateModel model1,
803:                    TemplateModel model2, Environment env)
804:                    throws TemplateModelException {
805:                if (env.isClassicCompatible()) {
806:                    if (model1 == null) {
807:                        model1 = TemplateScalarModel.EMPTY_STRING;
808:                    }
809:                    if (model2 == null) {
810:                        model2 = TemplateScalarModel.EMPTY_STRING;
811:                    }
812:                }
813:
814:                int comp = -1;
815:                if (model1 instanceof  TemplateNumberModel
816:                        && model2 instanceof  TemplateNumberModel) {
817:                    Number first = ((TemplateNumberModel) model1).getAsNumber();
818:                    Number second = ((TemplateNumberModel) model2)
819:                            .getAsNumber();
820:                    ArithmeticEngine ae = env != null ? env
821:                            .getArithmeticEngine() : env.getTemplate()
822:                            .getArithmeticEngine();
823:                    try {
824:                        comp = ae.compareNumbers(first, second);
825:                    } catch (TemplateException ex) {
826:                        throw new TemplateModelException(ex);
827:                    }
828:                } else if (model1 instanceof  TemplateDateModel
829:                        && model2 instanceof  TemplateDateModel) {
830:                    TemplateDateModel ltdm = (TemplateDateModel) model1;
831:                    TemplateDateModel rtdm = (TemplateDateModel) model2;
832:                    int ltype = ltdm.getDateType();
833:                    int rtype = rtdm.getDateType();
834:                    if (ltype != rtype) {
835:                        throw new TemplateModelException(
836:                                "Can not compare dates of different type. Left date is of "
837:                                        + TemplateDateModel.TYPE_NAMES
838:                                                .get(ltype)
839:                                        + " type, right date is of "
840:                                        + TemplateDateModel.TYPE_NAMES
841:                                                .get(rtype) + " type.");
842:                    }
843:                    if (ltype == TemplateDateModel.UNKNOWN) {
844:                        throw new TemplateModelException(
845:                                "Left date is of UNKNOWN type, and can not be compared.");
846:                    }
847:                    if (rtype == TemplateDateModel.UNKNOWN) {
848:                        throw new TemplateModelException(
849:                                "Right date is of UNKNOWN type, and can not be compared.");
850:                    }
851:                    Date first = ltdm.getAsDate();
852:                    Date second = rtdm.getAsDate();
853:                    comp = first.compareTo(second);
854:                } else if (model1 instanceof  TemplateScalarModel
855:                        && model2 instanceof  TemplateScalarModel) {
856:                    String first = ((TemplateScalarModel) model1).getAsString();
857:                    String second = ((TemplateScalarModel) model2)
858:                            .getAsString();
859:                    comp = env.getCollator().compare(first, second);
860:                } else if (model1 instanceof  TemplateBooleanModel
861:                        && model2 instanceof  TemplateBooleanModel) {
862:                    boolean first = ((TemplateBooleanModel) model1)
863:                            .getAsBoolean();
864:                    boolean second = ((TemplateBooleanModel) model2)
865:                            .getAsBoolean();
866:                    comp = (first ? 1 : 0) - (second ? 1 : 0);
867:                }
868:
869:                return (comp == 0);
870:            }
871:
872:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.