Source Code Cross Referenced for Parser.java in  » Rule-Engine » take » nz » org » take » nscript » 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 » Rule Engine » take » nz.org.take.nscript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Copyright 2008 Jens Dietrich Licensed under the Apache License, Version 2.0 (the "License"); 
003:         * you may not use this file except in compliance with the License. 
004:         * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
005:         * Unless required by applicable law or agreed to in writing, software distributed under the 
006:         * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
007:         * either express or implied. See the License for the specific language governing permissions 
008:         * and limitations under the License.
009:         */package nz.org.take.nscript;
010:
011:        /**
012:         * Script parser. Stateful, instances should not be shared. 
013:         * @author <a href="http://www-ist.massey.ac.nz/JBDietrich/">Jens Dietrich</a>
014:         */
015:
016:        import java.beans.BeanInfo;
017:        import java.beans.Introspector;
018:        import java.beans.PropertyDescriptor;
019:        import java.io.IOException;
020:        import java.io.LineNumberReader;
021:        import java.io.Reader;
022:        import java.lang.reflect.Method;
023:        import java.lang.reflect.Modifier;
024:        import java.util.ArrayList;
025:        import java.util.BitSet;
026:        import java.util.Collection;
027:        import java.util.HashMap;
028:        import java.util.HashSet;
029:        import java.util.List;
030:        import java.util.Map;
031:        import java.util.StringTokenizer;
032:        import java.util.Map.Entry;
033:        import java.util.regex.Pattern;
034:        import nz.org.take.AbstractPredicate;
035:        import nz.org.take.AggregationFunction;
036:        import nz.org.take.Annotatable;
037:        import nz.org.take.AnnotationKeys;
038:        import nz.org.take.ComplexTerm;
039:        import nz.org.take.Constant;
040:        import nz.org.take.DefaultKnowledgeBase;
041:        import nz.org.take.DerivationRule;
042:        import nz.org.take.ExternalFactStore;
043:        import nz.org.take.Fact;
044:        import nz.org.take.JPredicate;
045:        import nz.org.take.KnowledgeBase;
046:        import nz.org.take.Predicate;
047:        import nz.org.take.Prerequisite;
048:        import nz.org.take.PropertyPredicate;
049:        import nz.org.take.Query;
050:        import nz.org.take.SimplePredicate;
051:        import nz.org.take.Term;
052:        import nz.org.take.Variable;
053:
054:        public class Parser extends ParserSupport {
055:            public static final String _NAME1 = "[a-zA-Z][a-zA-Z0-9_]*"; // names for types
056:            public static final String _NAME2 = "[a-zA-Z_][a-zA-Z0-9_]*"; // names for var and ref declarations
057:            public static final Pattern TYPE_NAME = Pattern.compile(_NAME1
058:                    + "(\\." + _NAME1 + ")*");
059:            public static final Pattern NAME = Pattern.compile(_NAME2);
060:            public static final Pattern LIST_OF_NAMES = Pattern.compile(_NAME2
061:                    + "([\\s]*\\,[\\s]*" + _NAME2 + ")*");
062:            public static final Pattern IMPORT = Pattern.compile("import[\\s]+"
063:                    + _NAME2 + "(\\." + _NAME2 + ")*(\\.\\*)*[\\s]*[;]?[\\s]*");
064:            public static final Pattern COMMENT = Pattern.compile("//(.)*");
065:            public static final Pattern GLOBAL_ANNOTATION = Pattern
066:                    .compile("@@(.)+=(.)+");
067:            public static final Pattern LOCAL_ANNOTATION = Pattern
068:                    .compile("@[^@](.)*=(.)+");
069:            public static final Pattern EXTERNAL = Pattern
070:                    .compile("external[\\s]+[a-zA-Z_][a-zA-Z0-9_]*:[\\s]+[a-zA-Z_][a-zA-Z0-9_]*\\[(.)*\\]");
071:            public static final Pattern AGGREGATION = Pattern
072:                    .compile("aggregation[\\s]+(.)*\\[(.)*\\]"); // not very precise, needs improvement
073:            public static final Pattern QUERY = Pattern
074:                    .compile("(not[\\s]+)?"
075:                            + _NAME2
076:                            + "[\\s]*\\[[\\s]*(in|out)([\\s]*,[\\s]*(in|out))*[\\s]*\\]");
077:            public static final Pattern RULE = Pattern.compile(_NAME1
078:                    + ":[\\s]+if[\\s]+(.)*");
079:            public static final Pattern FACT = Pattern
080:                    .compile(_NAME1 + ":(.)*");
081:            public static final Pattern CONDITION1 = Pattern.compile(_NAME2
082:                    + "\\[(.)*\\]");
083:            public static final Pattern STRING_LITERAL = Pattern
084:                    .compile("\'(.)*\'"); // TODO handle escaped quotes
085:            private ClassLoader classLoader = Parser.class.getClassLoader();
086:            private KnowledgeBase kb = null;
087:            private Map<String, Variable> variables = new HashMap<String, Variable>();
088:            private Map<String, Constant> constants = new HashMap<String, Constant>();
089:            private Map<String, AggregationFunction> aggregationFunctions = new HashMap<String, AggregationFunction>();
090:            private Map<String, String> localAnnotations = new HashMap<String, String>();
091:            private List<QuerySpec> querySpecs = new ArrayList<QuerySpec>();
092:            private Map<String, Predicate> predicatesByName = new HashMap<String, Predicate>();
093:            private Map<SimplePredicate, SimplePredicate> predicates = new HashMap<SimplePredicate, SimplePredicate>(); // use map for simple lookup with get
094:            private List<String> importedClasses = new ArrayList<String>();
095:            private List<String> importedPackages = new ArrayList<String>();
096:            private List<ScriptException> issues = null;
097:            private Collection<String> ids = new HashSet<String>();
098:            boolean verificationMode = false;
099:            private JSPELParser elParser = new JSPELParser(variables,
100:                    constants, aggregationFunctions);
101:            private AnnotationPropagationPolicy annotationPolicy = AnnotationPropagationPolicy.ALL;
102:
103:            public Parser() {
104:                super ();
105:                this .importedPackages.add("java.lang");
106:            }
107:
108:            public List<ScriptException> check(Reader reader)
109:                    throws ScriptException {
110:                verificationMode = true;
111:                this .issues = new ArrayList<ScriptException>();
112:                parse(reader);
113:                return this .issues;
114:            }
115:
116:            public KnowledgeBase parse(Reader reader) throws ScriptException {
117:                kb = new DefaultKnowledgeBase();
118:                LineNumberReader bufReader = new LineNumberReader(reader);
119:                String line = null;
120:                try {
121:                    while ((line = bufReader.readLine()) != null) {
122:                        int no = bufReader.getLineNumber();
123:                        line = line.trim();
124:                        if (line.length() > 0) {
125:                            try {
126:                                parseLine(line, no);
127:                            } catch (RuntimeException x) {
128:                                this .error(no, x, "Exception parsing line");
129:                            }
130:                        }
131:                    }
132:
133:                    // build queries
134:                    buildQueries();
135:
136:                } catch (IOException e) {
137:                    throw new ScriptException(e);
138:                }
139:                return kb;
140:            }
141:
142:            private void parseLine(String line, int no) throws ScriptException {
143:
144:                if (line.startsWith("//")) {
145:                    // comment, don't parse
146:                } else if (line.startsWith("@@")) {
147:                    debug("parse line ", " as global annotation: ", line);
148:                    parseGlobalAnnotation(line, no);
149:                } else if (line.startsWith("@")) {
150:                    debug("parse line ", " as local annotation: ", line);
151:                    parseLocalAnnotation(line, no);
152:                } else if (line.startsWith("import")) {
153:                    debug("parse line ", " as import: ", line);
154:                    parseImport(line, no);
155:                } else if (line.startsWith("var ")) {
156:                    debug("parse line ", " as var declaration: ", line);
157:                    parseVarDeclaration(line, no);
158:                } else if (line.startsWith("ref ")) {
159:                    debug("parse line ", " as ref declaration: ", line);
160:                    parseRefDeclaration(line, no);
161:                } else if (line.startsWith("query ")) {
162:                    debug("parse line ", " as query: ", line);
163:                    parseQuery(line, no);
164:                } else if (line.startsWith("external ")) {
165:                    debug("parse line ", " as external fact store: ", line);
166:                    parseExternalFactStore(line, no);
167:                } else if (line.startsWith("aggregation ")) {
168:                    debug("parse line ", " as external fact store: ", line);
169:                    parseAggregation(line, no);
170:                } else if (RULE.matcher(line).matches()) {
171:                    debug("parse line ", " as rule: ", line);
172:                    parseRule(line, no);
173:                } else if (FACT.matcher(line).matches()) {
174:                    debug("parse line ", " as fact: ", line);
175:                    parseFact(line, no);
176:                }
177:
178:                else {
179:                    error(
180:                            no,
181:                            "Unable to parse this line (unknown syntax type): ",
182:                            line);
183:                }
184:
185:            }
186:
187:            private void parseAggregation(String line, int no)
188:                    throws ScriptException {
189:                check(no, line, AGGREGATION,
190:                        "this is not a valid aggregation declaration");
191:                line = line.substring(12).trim(); // take off aggregation
192:
193:                // name
194:                int sep = line.indexOf('='); // separate function name
195:                String name = line.substring(0, sep).trim();
196:                line = line.substring(sep + 1).trim();
197:                AggregationFunction f = new AggregationFunction();
198:                f.setName(name);
199:
200:                // kind of aggregation 
201:                sep = line.indexOf(' '); // separate function name
202:                String aggFunction = line.substring(0, sep);
203:                line = line.substring(sep + 1).trim();
204:                if (aggFunction.equals("avg")) {
205:                    f.setAggregation(nz.org.take.Aggregations.AVG);
206:                } else if (aggFunction.equals("sum")) {
207:                    f.setAggregation(nz.org.take.Aggregations.SUM);
208:                } else if (aggFunction.equals("count")) {
209:                    f.setAggregation(nz.org.take.Aggregations.COUNT);
210:                } else if (aggFunction.equals("min")) {
211:                    f.setAggregation(nz.org.take.Aggregations.MIN);
212:                } else if (aggFunction.equals("max")) {
213:                    f.setAggregation(nz.org.take.Aggregations.MAX);
214:                } else {
215:                    error(no, "Unknown aggregation function ", aggFunction);
216:                }
217:
218:                // variable
219:                sep = line.indexOf(' ');
220:                String vname = line.substring(0, sep);
221:                line = line.substring(sep + 1).trim();
222:                Variable var = this .variables.get(vname);
223:                if (var == null)
224:                    this 
225:                            .error(
226:                                    no,
227:                                    "The variable used in an aggregation must be declared first using the statement \"var <a type> ",
228:                                    vname, "\"");
229:                f.setVariable(var);
230:
231:                Fact query = this .parseCondition(line, no, false, false);
232:                f.setQuery(query);
233:
234:                aggregationFunctions.put(f.getName(), f);
235:            }
236:
237:            private void buildQueries() throws ScriptException {
238:                for (QuerySpec spec : this .querySpecs) {
239:                    String id = this .getId(spec);
240:                    Predicate p = this .predicatesByName.get(id);
241:                    if (p == null) {
242:                        this 
243:                                .error(
244:                                        spec.getLine(),
245:                                        "There is no rule or fact supporting the query predicate ",
246:                                        spec.getPredicate(), " in the script");
247:                    } else if (p.isNegated()) {
248:                        this 
249:                                .error(
250:                                        spec.getLine(),
251:                                        "There is no rule or fact supporting the unnegated query predicate ",
252:                                        spec.getPredicate(), " in the script");
253:                    } else {
254:                        Query query = new Query();
255:                        query.setPredicate(p);
256:                        boolean[] io = new boolean[spec.getIoSpec().size()];
257:                        for (int i = 0; i < io.length; i++) {
258:                            io[i] = spec.getIoSpec().get(i);
259:                        }
260:                        query.setInputParams(io);
261:                        query.addAnnotations(spec.getAnnotations());
262:                        takeOverAnnotations(query);
263:                        this .kb.add(query);
264:                    }
265:                }
266:            }
267:
268:            private void error(int no, String line, Pattern pattern,
269:                    String... description) throws ScriptException {
270:                StringBuffer buf = new StringBuffer();
271:                buf.append("Parser exception at line ");
272:                buf.append(no);
273:                buf.append(' ');
274:                buf.append(line);
275:                buf.append(" does not match pattern ");
276:                buf.append(pattern.pattern());
277:                buf.append(' ');
278:                for (String t : description)
279:                    buf.append(t);
280:                error(no, buf.toString());
281:            }
282:
283:            private void check(int no, String txt, Pattern pattern,
284:                    String... errorMessage) throws ScriptException {
285:                if (!pattern.matcher(txt).matches())
286:                    this .error(no, txt, pattern, errorMessage);
287:            }
288:
289:            private void parseVarDeclaration(String line, int no)
290:                    throws ScriptException {
291:                line = line.substring(4).trim();
292:                int sep = line.indexOf(' ');
293:                String type = line.substring(0, sep).trim();
294:                check(no, type, TYPE_NAME, "this is not a valid type name");
295:                Class clazz = this .classForName(type, no);
296:                String names = line.substring(sep + 1).trim();
297:                String name = null;
298:                check(no, names, LIST_OF_NAMES,
299:                        "this is not a valid (list of) name(s)");
300:
301:                StringTokenizer t = new StringTokenizer(names, ",");
302:                while (t.hasMoreTokens()) {
303:                    name = t.nextToken().trim();
304:                    Variable var = new Variable();
305:                    var.setType(clazz);
306:                    var.setName(name);
307:                    this .variables.put(name, var);
308:                }
309:            }
310:
311:            private void parseRefDeclaration(String line, int no)
312:                    throws ScriptException {
313:                line = line.substring(4).trim();
314:                int sep = line.indexOf(' ');
315:                String type = line.substring(0, sep).trim();
316:                check(no, type, TYPE_NAME, "this is not a valid type name");
317:                Class clazz = this .classForName(type, no);
318:                String names = line.substring(sep + 1).trim();
319:                String name = null;
320:                check(no, names, LIST_OF_NAMES,
321:                        "this is not a valid (list of) name(s)");
322:
323:                StringTokenizer t = new StringTokenizer(names, ",");
324:                while (t.hasMoreTokens()) {
325:                    name = t.nextToken().trim();
326:                    Constant c = new Constant();
327:                    c.setType(clazz);
328:                    c.setRef(name);
329:                    this .constants.put(name, c);
330:                }
331:            }
332:
333:            private void parseQuery(String line, int no) throws ScriptException {
334:                line = line.substring(6).trim();
335:
336:                QuerySpec query = new QuerySpec();
337:                query.setLine(no);
338:                this .consumeAnnotations(query);
339:
340:                // TODO should we support explicit negation here?
341:                if (line.startsWith("not ")) {
342:                    this .error(no, "Negation is not supported here");
343:                    //query.setNegated(true);
344:                    //line = line.substring(4).trim();
345:                }
346:
347:                int sep = line.indexOf('[');
348:                String name = line.substring(0, sep).trim();
349:                String sign = line.substring(sep + 1, line.length() - 1).trim();
350:
351:                query.setPredicate(name);
352:
353:                // parse i/o
354:                StringTokenizer tok = new StringTokenizer(sign, ",");
355:                while (tok.hasMoreTokens()) {
356:                    String token = tok.nextToken().trim();
357:                    query.getIoSpec().add("in".equals(token));
358:                }
359:
360:                this .querySpecs.add(query);
361:            }
362:
363:            private void parseRule(String line, int no) throws ScriptException {
364:
365:                int sep = line.indexOf(":"); //take off label
366:                String label = line.substring(0, sep).trim();
367:                line = line.substring(sep);
368:                sep = line.indexOf("if ");
369:                line = line.substring(sep + 3).trim();
370:                List<String> unparsedConditions = new ArrayList<String>();
371:                String unparsedHead = null;
372:                BitSet neg = new BitSet();
373:
374:                StringBuffer b = new StringBuffer();
375:
376:                List<String> tokens = Tokenizer.tokenize(line, " and ",
377:                        " then ");
378:                unparsedHead = tokens.remove(tokens.size() - 1).trim();
379:                for (int i = 0; i < tokens.size(); i++) {
380:                    String token = tokens.get(i).trim();
381:                    if (token.startsWith("not ")) {
382:                        token = token.substring(3).trim();
383:                        neg.set(i);
384:                    }
385:                    unparsedConditions.add(token);
386:                }
387:
388:                DerivationRule rule = new DerivationRule();
389:                this .checkId(label, no);
390:                rule.setId(label);
391:                Fact head = this .parseCondition(unparsedHead, no, false, false);
392:                rule.setHead(head);
393:                for (int i = 0; i < unparsedConditions.size(); i++) {
394:                    Prerequisite prereq = (Prerequisite) this .parseCondition(
395:                            unparsedConditions.get(i), no, true, neg.get(i));
396:                    rule.getBody().add(prereq);
397:                }
398:                this .consumeAnnotations(rule);
399:                this .kb.add(rule);
400:
401:            }
402:
403:            private void parseFact(String line, int no) throws ScriptException {
404:
405:                int sep = line.indexOf(":"); //take off label
406:                String label = line.substring(0, sep);
407:                line = line.substring(sep + 1).trim();
408:                Fact fact = this .parseCondition(line, no, false, false);
409:                this .checkId(label, no);
410:                // if fact contains variables, it should be added as a rule
411:                // TODO: this should better be done by the compiler
412:                boolean hasVars = false;
413:                for (Term t : fact.getTerms()) {
414:                    hasVars = hasVars || (t instanceof  Variable)
415:                            || (t instanceof  ComplexTerm);
416:                }
417:
418:                if (hasVars) {
419:                    DerivationRule rule = new DerivationRule();
420:                    rule.setId(label);
421:                    rule.setHead(fact);
422:                    this .kb.add(rule);
423:                } else {
424:                    fact.setId(label);
425:                    this .kb.add(fact);
426:                }
427:
428:            }
429:
430:            private void parseImport(String line, int no)
431:                    throws ScriptException {
432:                check(no, line, IMPORT, "this is not a valid import statement");
433:                line = line.substring(7).trim();
434:
435:                // for convenience, accept ; at the end of the line
436:                if (line.endsWith(";")) {
437:                    line = line.substring(0, line.length() - 1).trim();
438:                }
439:                // for import, last import wins
440:                if (line.endsWith(".*")) {
441:                    importedPackages.add(0, line
442:                            .substring(0, line.length() - 2));
443:                } else {
444:                    importedClasses.add(0, line);
445:                }
446:
447:            }
448:
449:            private void parseGlobalAnnotation(String line, int no)
450:                    throws ScriptException {
451:                check(no, line, GLOBAL_ANNOTATION,
452:                        "this is not a valid global annotation");
453:                line = line.substring(2).trim();
454:                int sep = line.indexOf('=');
455:                String key = line.substring(0, sep).trim();
456:                String value = line.substring(sep + 1).trim();
457:                this .kb.addAnnotation(key, value);
458:            }
459:
460:            private void parseLocalAnnotation(String line, int no)
461:                    throws ScriptException {
462:                check(no, line, LOCAL_ANNOTATION,
463:                        "this is not a valid local annotation");
464:                line = line.substring(1).trim();
465:                int sep = line.indexOf('=');
466:                String key = line.substring(0, sep).trim();
467:                String value = line.substring(sep + 1).trim();
468:                this .localAnnotations.put(key, value);
469:            }
470:
471:            private void parseExternalFactStore(String line, int no)
472:                    throws ScriptException {
473:                check(no, line, EXTERNAL,
474:                        "this is not a valid external fact store");
475:                line = line.substring(9).trim(); // take off external
476:                int sep = line.indexOf(":"); //take off label
477:                String id = line.substring(0, sep);
478:                line = line.substring(sep + 1).trim();
479:
480:                sep = line.indexOf('[');
481:                String name = line.substring(0, sep).trim();
482:                String typeNames = line.substring(sep + 1, line.length() - 1)
483:                        .trim();
484:
485:                StringTokenizer tokenizer = new StringTokenizer(typeNames, ",");
486:                List<Class> types = new ArrayList<Class>();
487:                while (tokenizer.hasMoreTokens()) {
488:                    String typeName = tokenizer.nextToken().trim();
489:                    check(no, typeName, TYPE_NAME,
490:                            "this is not a valid type name");
491:                    Class clazz = this .classForName(typeName, no);
492:                    types.add(clazz);
493:                }
494:                SimplePredicate predicate = new SimplePredicate();
495:                predicate.setName(name);
496:                predicate.setSlotTypes(types.toArray(new Class[types.size()]));
497:                String pid = this .getId(predicate);
498:                Predicate existingPredicate = predicatesByName.get(pid);
499:                if (existingPredicate == null) {
500:                    predicatesByName.put(pid, predicate);
501:                } else {
502:                    predicate = (SimplePredicate) existingPredicate;
503:                }
504:                ExternalFactStore exFacts = new ExternalFactStore();
505:                exFacts.setId(id);
506:                exFacts.setPredicate(predicate);
507:                this .consumeAnnotations(exFacts);
508:
509:                this .kb.add(exFacts);
510:            }
511:
512:            private Class classForName(String type, int line)
513:                    throws ScriptException {
514:
515:                if ("char".equals(type))
516:                    return Character.TYPE;
517:                if ("byte".equals(type))
518:                    return Byte.TYPE;
519:                if ("int".equals(type))
520:                    return Integer.TYPE;
521:                if ("short".equals(type))
522:                    return Short.TYPE;
523:                if ("long".equals(type))
524:                    return Long.TYPE;
525:                if ("double".equals(type))
526:                    return Double.TYPE;
527:                if ("float".equals(type))
528:                    return Float.TYPE;
529:                if ("boolean".equals(type))
530:                    return Boolean.TYPE;
531:
532:                // try whether this is a class name
533:                try {
534:                    return this .classLoader.loadClass(type);
535:                } catch (ClassNotFoundException x) {
536:                }
537:                // try whether there is a matching imported class
538:                String xtype = "." + type;
539:                for (String c : this .importedClasses) {
540:                    if (c.endsWith(xtype)) {
541:                        try {
542:                            return this .classLoader.loadClass(c);
543:                        } catch (Exception x) {
544:                        }
545:                    }
546:                }
547:                // try whether there is a matching imported package
548:                for (String p : this .importedPackages) {
549:                    try {
550:                        return this .classLoader.loadClass(p + '.' + type);
551:                    } catch (Exception x) {
552:                    }
553:                }
554:                this .error(line, "Cannot load the type ", type);
555:                return null;
556:
557:            }
558:
559:            private Fact parseCondition(String s, int no,
560:                    boolean isPrerequisite, boolean isNegated)
561:                    throws ScriptException {
562:
563:                if (CONDITION1.matcher(s).matches()) {
564:                    int sep = -1;
565:                    Fact fact = isPrerequisite ? new Prerequisite()
566:                            : new Fact();
567:                    // type of the condition is predicate[terms]
568:                    sep = s.indexOf('[');
569:                    String p = s.substring(0, sep);
570:
571:                    String t = s.substring(sep + 1, s.length() - 1);
572:                    List<String> unparsedTerms = Tokenizer.tokenize(t, ",");
573:                    List<Term> terms = new ArrayList<Term>();
574:                    for (String ut : unparsedTerms) {
575:                        terms.add(parseTerm(ut, no));
576:                    }
577:                    Class[] types = new Class[terms.size()];
578:                    for (int i = 0; i < terms.size(); i++) {
579:                        types[i] = terms.get(i).getType();
580:                    }
581:                    Predicate predicate = this .buildPredicate(p, isNegated,
582:                            terms.toArray(new Term[terms.size()]), no);
583:                    fact.setPredicate(predicate);
584:                    fact.setTerms(terms.toArray(new Term[terms.size()]));
585:                    return fact;
586:                } else {
587:                    if (!isPrerequisite) {
588:                        throw new ScriptException(
589:                                "Error in line "
590:                                        + no
591:                                        + " - the rule head must have the following form: predicate[term_1,..,term_n]");
592:                    } else {
593:                        // parse with JUEL
594:                        return elParser.parseCondition(s, no, isNegated);
595:                    }
596:                }
597:            }
598:
599:            private Term parseTerm(String s, int line) throws ScriptException {
600:                return this .elParser.parseTerm(s, line);
601:            }
602:
603:            private void consumeAnnotations(Annotatable a) {
604:                for (String gaKey : this .kb.getAnnotations().keySet()) {
605:                    if (this .annotationPolicy.propagateAnnotation(gaKey)) {
606:                        a.addAnnotation(gaKey, this .kb.getAnnotation(gaKey));
607:                    }
608:                }
609:                a.addAnnotations(this .localAnnotations);
610:                this .localAnnotations.clear();
611:            }
612:
613:            private void checkId(String id, int line) throws ScriptException {
614:
615:                if (id == null || id.trim().length() == 0)
616:                    this .error(line, "element has no proper id");
617:                else if (ids.contains(id))
618:                    this .error(line, "duplicated id ", id);
619:                else
620:                    ids.add(id);
621:            }
622:
623:            // take over query annotations for the query predicate
624:            private void takeOverAnnotations(Query q) {
625:                Predicate p = q.getPredicate();
626:                for (Entry<String, String> e : q.getAnnotations().entrySet()) {
627:                    String key = e.getKey();
628:                    p.addAnnotation(key, e.getValue());
629:                    if (AnnotationKeys.TAKE_GENERATE_SLOTS.equals(key)) {
630:                        // set slot names from annotation
631:                        List<String> slots = new ArrayList<String>();
632:                        for (StringTokenizer tok = new StringTokenizer(e
633:                                .getValue(), ","); tok.hasMoreTokens();) {
634:                            slots.add(tok.nextToken().trim());
635:                        }
636:                        if (slots.size() != p.getSlotTypes().length) {
637:                            // TODO log warning
638:                        } else {
639:                            String[] arr = slots.toArray(new String[slots
640:                                    .size()]);
641:                            if (p instanceof  AbstractPredicate)
642:                                ((AbstractPredicate) p).setSlotNames(arr);
643:                            //else  TODO log warning
644:                        }
645:                    }
646:                }
647:            }
648:
649:            private nz.org.take.Predicate buildPredicate(String name,
650:                    boolean negated, Term[] terms, int line)
651:                    throws ScriptException {
652:                Predicate predicate = null;
653:
654:                Method m = getMethod(name, terms);
655:                PropertyDescriptor property = null;
656:                if (m == null)
657:                    property = getProperty(name, terms[0].getType());
658:
659:                if (m != null) {
660:                    debug("Interpreting predicate symbol ", name,
661:                            " as Java method ", m, " in line ", line);
662:                    JPredicate p = new JPredicate();
663:                    Class[] paramTypes = getParamTypes(terms);
664:                    p.setMethod(m);
665:                    p.setNegated(negated);
666:                    predicate = p;
667:                } else if (property != null) {
668:                    debug("Interpreting predicate symbol ", name,
669:                            " as bean property", " in line ", line);
670:                    PropertyPredicate p = new PropertyPredicate();
671:                    p.setProperty(property);
672:                    p.setOwnerType(terms[0].getType());
673:                    p.setNegated(negated);
674:                    // todo remove this line that just does lazy initialization
675:                    predicate = p;
676:                } else {
677:                    debug("Interpreting predicate symbol ", name,
678:                            " as simple predicate", " in line ", line);
679:                    SimplePredicate p = new SimplePredicate();
680:                    p.setName(name);
681:                    p.setNegated(negated);
682:                    Class[] types = new Class[terms.length];
683:                    for (int i = 0; i < terms.length; i++) {
684:                        types[i] = terms[i].getType();
685:                    }
686:                    p.setSlotTypes(types);
687:                    predicate = p;
688:                }
689:                String id = this .getId(predicate);
690:                Predicate existingPredicate = predicatesByName.get(id);
691:                if (existingPredicate == null) {
692:                    predicatesByName.put(this .getId(predicate), predicate);
693:                    return predicate;
694:                } else
695:                    return existingPredicate;
696:            }
697:
698:            private Class[] getParamTypes(nz.org.take.Term[] terms) {
699:                Class[] paramTypes = new Class[terms.length - 1];
700:                for (int i = 1; i < terms.length; i++) {
701:                    paramTypes[i - 1] = terms[i].getType();
702:                }
703:                return paramTypes;
704:            }
705:
706:            private Method getMethod(String name, nz.org.take.Term[] terms)
707:                    throws ScriptException {
708:                Class clazz = terms[0].getType();
709:                Class[] paramTypes = new Class[terms.length - 1];
710:                Method m = null;
711:                for (int i = 1; i < terms.length; i++) {
712:                    paramTypes[i - 1] = terms[i].getType();
713:                }
714:                try {
715:                    m = clazz.getMethod(name, paramTypes);
716:                } catch (Exception x) {
717:                }
718:                if (m == null) {
719:                    // start investigating supertypes
720:                    Method[] methods = clazz.getMethods();
721:                    for (Method m1 : methods) {
722:                        if (m1.getReturnType() == Boolean.TYPE
723:                                && Modifier.isPublic(m1.getModifiers())) {
724:                            if (m1.getName().equals(name)
725:                                    && m1.getParameterTypes().length == paramTypes.length) {
726:                                // check types
727:                                boolean ok = true;
728:                                for (int i = 0; i < paramTypes.length; i++) {
729:                                    ok = ok
730:                                            && m1.getParameterTypes()[i]
731:                                                    .isAssignableFrom(paramTypes[i]);
732:                                }
733:                                if (ok) {
734:                                    m = m1;
735:                                    break;
736:                                }
737:                            }
738:                        }
739:                    }
740:                }
741:                return m;
742:
743:            }
744:
745:            private PropertyDescriptor getProperty(String name, Class clazz)
746:                    throws ScriptException {
747:                try {
748:                    BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
749:                    PropertyDescriptor[] properties = beanInfo
750:                            .getPropertyDescriptors();
751:                    for (PropertyDescriptor property : properties) {
752:                        if (name.equals(property.getName())
753:                                && property.getReadMethod() != null) {
754:                            return property;
755:                        }
756:                    }
757:                } catch (Exception x) {
758:                }
759:                return null;
760:            }
761:
762:            private String getId(Predicate p) {
763:                return p.getName() + '_' + p.getSlotTypes().length
764:                        + (p.isNegated() ? "-" : "+");
765:            }
766:
767:            private String getId(QuerySpec q) {
768:                return q.getPredicate() + '_' + q.getIoSpec().size() + "+";
769:            }
770:
771:            protected void error(int no, String message) throws ScriptException {
772:                if (this .verificationMode) {
773:                    this .issues.add(new ScriptException(message, no));
774:                } else {
775:                    super .error(no, message);
776:                }
777:            }
778:
779:            protected void error(int no, Exception x, String message)
780:                    throws ScriptException {
781:                if (this .verificationMode) {
782:                    this .issues.add(new ScriptException(message, x, no));
783:                } else {
784:                    super .error(no, x, message);
785:                }
786:            }
787:
788:            public ClassLoader getClassLoader() {
789:                return classLoader;
790:            }
791:
792:            public void setClassLoader(ClassLoader classloader) {
793:                this .classLoader = classloader;
794:            }
795:
796:            public AnnotationPropagationPolicy getAnnotationPolicy() {
797:                return annotationPolicy;
798:            }
799:
800:            public void setAnnotationPolicy(
801:                    AnnotationPropagationPolicy annotationPolicy) {
802:                this.annotationPolicy = annotationPolicy;
803:            }
804:
805:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.