Source Code Cross Referenced for EvaluationStrategyImpl.java in  » RSS-RDF » sesame » org » openrdf » query » algebra » evaluation » impl » 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 » RSS RDF » sesame » org.openrdf.query.algebra.evaluation.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
0003:         *
0004:         * Licensed under the Aduna BSD-style license.
0005:         */
0006:        package org.openrdf.query.algebra.evaluation.impl;
0007:
0008:        import java.math.BigDecimal;
0009:        import java.math.BigInteger;
0010:        import java.math.RoundingMode;
0011:        import java.util.HashSet;
0012:        import java.util.List;
0013:        import java.util.Set;
0014:        import java.util.regex.Pattern;
0015:
0016:        import info.aduna.iteration.CloseableIteration;
0017:        import info.aduna.iteration.ConvertingIteration;
0018:        import info.aduna.iteration.DelayedIteration;
0019:        import info.aduna.iteration.DistinctIteration;
0020:        import info.aduna.iteration.EmptyIteration;
0021:        import info.aduna.iteration.FilterIteration;
0022:        import info.aduna.iteration.IntersectIteration;
0023:        import info.aduna.iteration.Iteration;
0024:        import info.aduna.iteration.LimitIteration;
0025:        import info.aduna.iteration.MinusIteration;
0026:        import info.aduna.iteration.OffsetIteration;
0027:        import info.aduna.iteration.SingletonIteration;
0028:        import info.aduna.iteration.UnionIteration;
0029:
0030:        import org.openrdf.model.BNode;
0031:        import org.openrdf.model.Literal;
0032:        import org.openrdf.model.Resource;
0033:        import org.openrdf.model.Statement;
0034:        import org.openrdf.model.URI;
0035:        import org.openrdf.model.Value;
0036:        import org.openrdf.model.datatypes.XMLDatatypeUtil;
0037:        import org.openrdf.model.impl.BooleanLiteralImpl;
0038:        import org.openrdf.model.impl.DecimalLiteralImpl;
0039:        import org.openrdf.model.impl.IntegerLiteralImpl;
0040:        import org.openrdf.model.impl.NumericLiteralImpl;
0041:        import org.openrdf.model.vocabulary.XMLSchema;
0042:        import org.openrdf.query.BindingSet;
0043:        import org.openrdf.query.Dataset;
0044:        import org.openrdf.query.QueryEvaluationException;
0045:        import org.openrdf.query.algebra.And;
0046:        import org.openrdf.query.algebra.BNodeGenerator;
0047:        import org.openrdf.query.algebra.BinaryTupleOperator;
0048:        import org.openrdf.query.algebra.Bound;
0049:        import org.openrdf.query.algebra.Compare;
0050:        import org.openrdf.query.algebra.CompareAll;
0051:        import org.openrdf.query.algebra.CompareAny;
0052:        import org.openrdf.query.algebra.Datatype;
0053:        import org.openrdf.query.algebra.Difference;
0054:        import org.openrdf.query.algebra.Distinct;
0055:        import org.openrdf.query.algebra.EmptySet;
0056:        import org.openrdf.query.algebra.Exists;
0057:        import org.openrdf.query.algebra.Extension;
0058:        import org.openrdf.query.algebra.Filter;
0059:        import org.openrdf.query.algebra.FunctionCall;
0060:        import org.openrdf.query.algebra.Group;
0061:        import org.openrdf.query.algebra.In;
0062:        import org.openrdf.query.algebra.Intersection;
0063:        import org.openrdf.query.algebra.IsBNode;
0064:        import org.openrdf.query.algebra.IsLiteral;
0065:        import org.openrdf.query.algebra.IsResource;
0066:        import org.openrdf.query.algebra.IsURI;
0067:        import org.openrdf.query.algebra.Join;
0068:        import org.openrdf.query.algebra.Label;
0069:        import org.openrdf.query.algebra.Lang;
0070:        import org.openrdf.query.algebra.LangMatches;
0071:        import org.openrdf.query.algebra.LeftJoin;
0072:        import org.openrdf.query.algebra.Like;
0073:        import org.openrdf.query.algebra.LocalName;
0074:        import org.openrdf.query.algebra.MathExpr;
0075:        import org.openrdf.query.algebra.MultiProjection;
0076:        import org.openrdf.query.algebra.Namespace;
0077:        import org.openrdf.query.algebra.Not;
0078:        import org.openrdf.query.algebra.Or;
0079:        import org.openrdf.query.algebra.Order;
0080:        import org.openrdf.query.algebra.Projection;
0081:        import org.openrdf.query.algebra.QueryRoot;
0082:        import org.openrdf.query.algebra.Regex;
0083:        import org.openrdf.query.algebra.SameTerm;
0084:        import org.openrdf.query.algebra.SingletonSet;
0085:        import org.openrdf.query.algebra.Slice;
0086:        import org.openrdf.query.algebra.StatementPattern;
0087:        import org.openrdf.query.algebra.Str;
0088:        import org.openrdf.query.algebra.TupleExpr;
0089:        import org.openrdf.query.algebra.UnaryTupleOperator;
0090:        import org.openrdf.query.algebra.Union;
0091:        import org.openrdf.query.algebra.ValueConstant;
0092:        import org.openrdf.query.algebra.ValueExpr;
0093:        import org.openrdf.query.algebra.Var;
0094:        import org.openrdf.query.algebra.MathExpr.MathOp;
0095:        import org.openrdf.query.algebra.StatementPattern.Scope;
0096:        import org.openrdf.query.algebra.evaluation.EvaluationStrategy;
0097:        import org.openrdf.query.algebra.evaluation.QueryBindingSet;
0098:        import org.openrdf.query.algebra.evaluation.TripleSource;
0099:        import org.openrdf.query.algebra.evaluation.ValueExprEvaluationException;
0100:        import org.openrdf.query.algebra.evaluation.function.Function;
0101:        import org.openrdf.query.algebra.evaluation.function.FunctionRegistry;
0102:        import org.openrdf.query.algebra.evaluation.iterator.CompatibleBindingSetFilter;
0103:        import org.openrdf.query.algebra.evaluation.iterator.ExtensionIterator;
0104:        import org.openrdf.query.algebra.evaluation.iterator.FilterIterator;
0105:        import org.openrdf.query.algebra.evaluation.iterator.GroupIterator;
0106:        import org.openrdf.query.algebra.evaluation.iterator.JoinIterator;
0107:        import org.openrdf.query.algebra.evaluation.iterator.LeftJoinIterator;
0108:        import org.openrdf.query.algebra.evaluation.iterator.MultiProjectionIterator;
0109:        import org.openrdf.query.algebra.evaluation.iterator.OrderIterator;
0110:        import org.openrdf.query.algebra.evaluation.iterator.ProjectionIterator;
0111:        import org.openrdf.query.algebra.evaluation.util.OrderComparator;
0112:        import org.openrdf.query.algebra.evaluation.util.QueryEvaluationUtil;
0113:        import org.openrdf.query.algebra.evaluation.util.ValueComparator;
0114:
0115:        /**
0116:         * Evaluates the TupleExpr and ValueExpr using Iterators and common tripleSource
0117:         * API.
0118:         * 
0119:         * @author James Leigh
0120:         * @author Arjohn Kampman
0121:         * @author David Huynh
0122:         */
0123:        public class EvaluationStrategyImpl implements  EvaluationStrategy {
0124:
0125:            /*-----------*
0126:             * Constants *
0127:             *-----------*/
0128:
0129:            private final TripleSource tripleSource;
0130:
0131:            private final Dataset dataset;
0132:
0133:            /*--------------*
0134:             * Constructors *
0135:             *--------------*/
0136:
0137:            public EvaluationStrategyImpl(TripleSource tripleSource) {
0138:                this (tripleSource, null);
0139:            }
0140:
0141:            public EvaluationStrategyImpl(TripleSource tripleSource,
0142:                    Dataset dataset) {
0143:                this .tripleSource = tripleSource;
0144:                this .dataset = dataset;
0145:            }
0146:
0147:            /*---------*
0148:             * Methods *
0149:             *---------*/
0150:
0151:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0152:                    TupleExpr expr, BindingSet bindings)
0153:                    throws QueryEvaluationException {
0154:                if (expr instanceof  StatementPattern) {
0155:                    return evaluate((StatementPattern) expr, bindings);
0156:                } else if (expr instanceof  UnaryTupleOperator) {
0157:                    return evaluate((UnaryTupleOperator) expr, bindings);
0158:                } else if (expr instanceof  BinaryTupleOperator) {
0159:                    return evaluate((BinaryTupleOperator) expr, bindings);
0160:                } else if (expr instanceof  SingletonSet) {
0161:                    return evaluate((SingletonSet) expr, bindings);
0162:                } else if (expr instanceof  EmptySet) {
0163:                    return evaluate((EmptySet) expr, bindings);
0164:                } else if (expr == null) {
0165:                    throw new IllegalArgumentException("expr must not be null");
0166:                } else {
0167:                    throw new QueryEvaluationException(
0168:                            "Unsupported tuple expr type: " + expr.getClass());
0169:                }
0170:            }
0171:
0172:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0173:                    StatementPattern sp, final BindingSet bindings)
0174:                    throws QueryEvaluationException {
0175:                final Var subjVar = sp.getSubjectVar();
0176:                final Var predVar = sp.getPredicateVar();
0177:                final Var objVar = sp.getObjectVar();
0178:                final Var conVar = sp.getContextVar();
0179:
0180:                Value subjValue = getVarValue(subjVar, bindings);
0181:                Value predValue = getVarValue(predVar, bindings);
0182:                Value objValue = getVarValue(objVar, bindings);
0183:                Value contextValue = getVarValue(conVar, bindings);
0184:
0185:                CloseableIteration<? extends Statement, QueryEvaluationException> stIter = null;
0186:
0187:                try {
0188:                    Resource[] contexts;
0189:
0190:                    if (dataset != null) {
0191:                        Set<URI> graphs;
0192:                        if (sp.getScope() == Scope.DEFAULT_CONTEXTS) {
0193:                            graphs = dataset.getDefaultGraphs();
0194:                        } else {
0195:                            graphs = dataset.getNamedGraphs();
0196:                        }
0197:
0198:                        if (graphs.isEmpty()) {
0199:                            // Search zero contexts
0200:                            return new EmptyIteration<BindingSet, QueryEvaluationException>();
0201:                        } else if (contextValue != null) {
0202:                            if (graphs.contains(contextValue)) {
0203:                                contexts = new Resource[] { (Resource) contextValue };
0204:                            } else {
0205:                                // Statement pattern specifies a context that is not part of
0206:                                // the dataset
0207:                                return new EmptyIteration<BindingSet, QueryEvaluationException>();
0208:                            }
0209:                        } else {
0210:                            contexts = graphs.toArray(new Resource[graphs
0211:                                    .size()]);
0212:                        }
0213:                    } else if (contextValue != null) {
0214:                        contexts = new Resource[] { (Resource) contextValue };
0215:                    } else {
0216:                        contexts = new Resource[0];
0217:                    }
0218:
0219:                    stIter = tripleSource.getStatements((Resource) subjValue,
0220:                            (URI) predValue, objValue, contexts);
0221:
0222:                    if (contexts.length == 0
0223:                            && sp.getScope() == Scope.NAMED_CONTEXTS) {
0224:                        // Named contexts are matched by retrieving all statements from
0225:                        // the store and filtering out the statements that do not have a
0226:                        // context.
0227:                        stIter = new FilterIteration<Statement, QueryEvaluationException>(
0228:                                stIter) {
0229:
0230:                            @Override
0231:                            protected boolean accept(Statement st) {
0232:                                return st.getContext() != null;
0233:                            }
0234:
0235:                        }; // end anonymous class
0236:                    }
0237:                } catch (ClassCastException e) {
0238:                    // Invalid value type for subject, predicate and/or context
0239:                    return new EmptyIteration<BindingSet, QueryEvaluationException>();
0240:                }
0241:
0242:                // The same variable might have been used multiple times in this
0243:                // StatementPattern, verify value equality in those cases.
0244:                stIter = new FilterIteration<Statement, QueryEvaluationException>(
0245:                        stIter) {
0246:
0247:                    @Override
0248:                    protected boolean accept(Statement st) {
0249:                        Resource subj = st.getSubject();
0250:                        URI pred = st.getPredicate();
0251:                        Value obj = st.getObject();
0252:                        Resource context = st.getContext();
0253:
0254:                        if (subjVar != null) {
0255:                            if (subjVar.equals(predVar) && !subj.equals(pred)) {
0256:                                return false;
0257:                            }
0258:                            if (subjVar.equals(objVar) && !subj.equals(obj)) {
0259:                                return false;
0260:                            }
0261:                            if (subjVar.equals(conVar) && !subj.equals(context)) {
0262:                                return false;
0263:                            }
0264:                        }
0265:
0266:                        if (predVar != null) {
0267:                            if (predVar.equals(objVar) && !pred.equals(obj)) {
0268:                                return false;
0269:                            }
0270:                            if (predVar.equals(conVar) && !pred.equals(context)) {
0271:                                return false;
0272:                            }
0273:                        }
0274:
0275:                        if (objVar != null) {
0276:                            if (objVar.equals(conVar) && !obj.equals(context)) {
0277:                                return false;
0278:                            }
0279:                        }
0280:
0281:                        return true;
0282:                    }
0283:                };
0284:
0285:                // Return an iterator that converts the statements to var bindings
0286:                return new ConvertingIteration<Statement, BindingSet, QueryEvaluationException>(
0287:                        stIter) {
0288:
0289:                    @Override
0290:                    protected BindingSet convert(Statement st) {
0291:                        QueryBindingSet result = new QueryBindingSet(bindings);
0292:
0293:                        if (subjVar != null
0294:                                && !result.hasBinding(subjVar.getName())) {
0295:                            result.addBinding(subjVar.getName(), st
0296:                                    .getSubject());
0297:                        }
0298:                        if (predVar != null
0299:                                && !result.hasBinding(predVar.getName())) {
0300:                            result.addBinding(predVar.getName(), st
0301:                                    .getPredicate());
0302:                        }
0303:                        if (objVar != null
0304:                                && !result.hasBinding(objVar.getName())) {
0305:                            result.addBinding(objVar.getName(), st.getObject());
0306:                        }
0307:                        if (conVar != null
0308:                                && !result.hasBinding(conVar.getName())
0309:                                && st.getContext() != null) {
0310:                            result
0311:                                    .addBinding(conVar.getName(), st
0312:                                            .getContext());
0313:                        }
0314:
0315:                        return result;
0316:                    }
0317:                };
0318:            }
0319:
0320:            private Value getVarValue(Var var, BindingSet bindings) {
0321:                if (var == null) {
0322:                    return null;
0323:                } else if (var.hasValue()) {
0324:                    return var.getValue();
0325:                } else {
0326:                    return bindings.getValue(var.getName());
0327:                }
0328:            }
0329:
0330:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0331:                    UnaryTupleOperator expr, BindingSet bindings)
0332:                    throws QueryEvaluationException {
0333:                if (expr instanceof  Projection) {
0334:                    return evaluate((Projection) expr, bindings);
0335:                } else if (expr instanceof  MultiProjection) {
0336:                    return evaluate((MultiProjection) expr, bindings);
0337:                } else if (expr instanceof  Filter) {
0338:                    return evaluate((Filter) expr, bindings);
0339:                } else if (expr instanceof  Slice) {
0340:                    return evaluate((Slice) expr, bindings);
0341:                } else if (expr instanceof  Extension) {
0342:                    return evaluate((Extension) expr, bindings);
0343:                } else if (expr instanceof  Distinct) {
0344:                    return evaluate((Distinct) expr, bindings);
0345:                } else if (expr instanceof  Group) {
0346:                    return evaluate((Group) expr, bindings);
0347:                } else if (expr instanceof  Order) {
0348:                    return evaluate((Order) expr, bindings);
0349:                } else if (expr instanceof  QueryRoot) {
0350:                    return evaluate(((QueryRoot) expr).getArg(), bindings);
0351:                } else if (expr == null) {
0352:                    throw new IllegalArgumentException("expr must not be null");
0353:                } else {
0354:                    throw new QueryEvaluationException(
0355:                            "Unknown unary tuple operator type: "
0356:                                    + expr.getClass());
0357:                }
0358:            }
0359:
0360:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0361:                    Projection projection, BindingSet bindings)
0362:                    throws QueryEvaluationException {
0363:                CloseableIteration<BindingSet, QueryEvaluationException> result;
0364:                result = this .evaluate(projection.getArg(), bindings);
0365:                result = new ProjectionIterator(projection, result, bindings);
0366:                return result;
0367:            }
0368:
0369:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0370:                    MultiProjection multiProjection, BindingSet bindings)
0371:                    throws QueryEvaluationException {
0372:                CloseableIteration<BindingSet, QueryEvaluationException> result;
0373:                result = this .evaluate(multiProjection.getArg(), bindings);
0374:                result = new MultiProjectionIterator(multiProjection, result,
0375:                        bindings);
0376:                return result;
0377:            }
0378:
0379:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0380:                    Filter filter, BindingSet bindings)
0381:                    throws QueryEvaluationException {
0382:                CloseableIteration<BindingSet, QueryEvaluationException> result;
0383:                result = this .evaluate(filter.getArg(), bindings);
0384:                result = new FilterIterator(filter, result, this );
0385:                return result;
0386:            }
0387:
0388:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0389:                    Slice slice, BindingSet bindings)
0390:                    throws QueryEvaluationException {
0391:                CloseableIteration<BindingSet, QueryEvaluationException> result = evaluate(
0392:                        slice.getArg(), bindings);
0393:
0394:                if (slice.hasOffset()) {
0395:                    result = new OffsetIteration<BindingSet, QueryEvaluationException>(
0396:                            result, slice.getOffset());
0397:                }
0398:
0399:                if (slice.hasLimit()) {
0400:                    result = new LimitIteration<BindingSet, QueryEvaluationException>(
0401:                            result, slice.getLimit());
0402:                }
0403:
0404:                return result;
0405:            }
0406:
0407:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0408:                    Extension extension, BindingSet bindings)
0409:                    throws QueryEvaluationException {
0410:                CloseableIteration<BindingSet, QueryEvaluationException> result;
0411:                result = this .evaluate(extension.getArg(), bindings);
0412:                result = new ExtensionIterator(extension, result, this );
0413:                return result;
0414:            }
0415:
0416:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0417:                    Distinct distinct, BindingSet bindings)
0418:                    throws QueryEvaluationException {
0419:                return new DistinctIteration<BindingSet, QueryEvaluationException>(
0420:                        evaluate(distinct.getArg(), bindings));
0421:            }
0422:
0423:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0424:                    Group node, BindingSet bindings)
0425:                    throws QueryEvaluationException {
0426:                return new GroupIterator(this , node, bindings);
0427:            }
0428:
0429:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0430:                    Order node, BindingSet bindings)
0431:                    throws QueryEvaluationException {
0432:                ValueComparator vcmp = new ValueComparator();
0433:                OrderComparator cmp = new OrderComparator(this , node, vcmp);
0434:                return new OrderIterator(evaluate(node.getArg(), bindings), cmp);
0435:            }
0436:
0437:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0438:                    BinaryTupleOperator expr, BindingSet bindings)
0439:                    throws QueryEvaluationException {
0440:                if (expr instanceof  Join) {
0441:                    return evaluate((Join) expr, bindings);
0442:                } else if (expr instanceof  LeftJoin) {
0443:                    return evaluate((LeftJoin) expr, bindings);
0444:                } else if (expr instanceof  Union) {
0445:                    return evaluate((Union) expr, bindings);
0446:                } else if (expr instanceof  Intersection) {
0447:                    return evaluate((Intersection) expr, bindings);
0448:                } else if (expr instanceof  Difference) {
0449:                    return evaluate((Difference) expr, bindings);
0450:                } else if (expr == null) {
0451:                    throw new IllegalArgumentException("expr must not be null");
0452:                } else {
0453:                    throw new QueryEvaluationException(
0454:                            "Unsupported binary tuple operator type: "
0455:                                    + expr.getClass());
0456:                }
0457:            }
0458:
0459:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0460:                    Join join, BindingSet bindings)
0461:                    throws QueryEvaluationException {
0462:                return new JoinIterator(this , join, bindings);
0463:            }
0464:
0465:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0466:                    LeftJoin leftJoin, BindingSet bindings)
0467:                    throws QueryEvaluationException {
0468:                // Check whether optional join is "well designed" as defined in section
0469:                // 4.2 of "Semantics and Complexity of SPARQL", 2006, Jorge Pérez et al.
0470:                Set<String> boundVars = bindings.getBindingNames();
0471:                Set<String> leftVars = leftJoin.getLeftArg().getBindingNames();
0472:                Set<String> optionalVars = leftJoin.getRightArg()
0473:                        .getBindingNames();
0474:
0475:                Set<String> problemVars = new HashSet<String>(boundVars);
0476:                problemVars.retainAll(optionalVars);
0477:                problemVars.removeAll(leftVars);
0478:
0479:                if (problemVars.isEmpty()) {
0480:                    // left join is "well designed"
0481:                    return new LeftJoinIterator(this , leftJoin, bindings);
0482:                } else {
0483:                    QueryBindingSet filteredBindings = new QueryBindingSet(
0484:                            bindings);
0485:                    filteredBindings.removeAll(problemVars);
0486:                    CloseableIteration<BindingSet, QueryEvaluationException> iter;
0487:
0488:                    iter = new LeftJoinIterator(this , leftJoin,
0489:                            filteredBindings);
0490:                    iter = new CompatibleBindingSetFilter(iter, bindings);
0491:
0492:                    return iter;
0493:                }
0494:            }
0495:
0496:            @SuppressWarnings("unchecked")
0497:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0498:                    final Union union, final BindingSet bindings)
0499:                    throws QueryEvaluationException {
0500:                Iteration<BindingSet, QueryEvaluationException> leftArg, rightArg;
0501:
0502:                leftArg = new DelayedIteration<BindingSet, QueryEvaluationException>() {
0503:
0504:                    @Override
0505:                    protected Iteration<BindingSet, QueryEvaluationException> createIteration()
0506:                            throws QueryEvaluationException {
0507:                        return evaluate(union.getLeftArg(), bindings);
0508:                    }
0509:                };
0510:
0511:                rightArg = new DelayedIteration<BindingSet, QueryEvaluationException>() {
0512:
0513:                    @Override
0514:                    protected Iteration<BindingSet, QueryEvaluationException> createIteration()
0515:                            throws QueryEvaluationException {
0516:                        return evaluate(union.getRightArg(), bindings);
0517:                    }
0518:                };
0519:
0520:                return new UnionIteration<BindingSet, QueryEvaluationException>(
0521:                        leftArg, rightArg);
0522:            }
0523:
0524:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0525:                    final Intersection intersection, final BindingSet bindings)
0526:                    throws QueryEvaluationException {
0527:                Iteration<BindingSet, QueryEvaluationException> leftArg, rightArg;
0528:
0529:                leftArg = new DelayedIteration<BindingSet, QueryEvaluationException>() {
0530:
0531:                    @Override
0532:                    protected Iteration<BindingSet, QueryEvaluationException> createIteration()
0533:                            throws QueryEvaluationException {
0534:                        return evaluate(intersection.getLeftArg(), bindings);
0535:                    }
0536:                };
0537:
0538:                rightArg = new DelayedIteration<BindingSet, QueryEvaluationException>() {
0539:
0540:                    @Override
0541:                    protected Iteration<BindingSet, QueryEvaluationException> createIteration()
0542:                            throws QueryEvaluationException {
0543:                        return evaluate(intersection.getRightArg(), bindings);
0544:                    }
0545:                };
0546:
0547:                return new IntersectIteration<BindingSet, QueryEvaluationException>(
0548:                        leftArg, rightArg);
0549:            }
0550:
0551:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0552:                    final Difference difference, final BindingSet bindings)
0553:                    throws QueryEvaluationException {
0554:                Iteration<BindingSet, QueryEvaluationException> leftArg, rightArg;
0555:
0556:                leftArg = new DelayedIteration<BindingSet, QueryEvaluationException>() {
0557:
0558:                    @Override
0559:                    protected Iteration<BindingSet, QueryEvaluationException> createIteration()
0560:                            throws QueryEvaluationException {
0561:                        return evaluate(difference.getLeftArg(), bindings);
0562:                    }
0563:                };
0564:
0565:                rightArg = new DelayedIteration<BindingSet, QueryEvaluationException>() {
0566:
0567:                    @Override
0568:                    protected Iteration<BindingSet, QueryEvaluationException> createIteration()
0569:                            throws QueryEvaluationException {
0570:                        return evaluate(difference.getRightArg(), bindings);
0571:                    }
0572:                };
0573:
0574:                return new MinusIteration<BindingSet, QueryEvaluationException>(
0575:                        leftArg, rightArg);
0576:            }
0577:
0578:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0579:                    SingletonSet singletonSet, BindingSet bindings)
0580:                    throws QueryEvaluationException {
0581:                return new SingletonIteration<BindingSet, QueryEvaluationException>(
0582:                        bindings);
0583:            }
0584:
0585:            public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(
0586:                    EmptySet emptySet, BindingSet bindings)
0587:                    throws QueryEvaluationException {
0588:                return new EmptyIteration<BindingSet, QueryEvaluationException>();
0589:            }
0590:
0591:            public Value evaluate(ValueExpr expr, BindingSet bindings)
0592:                    throws ValueExprEvaluationException,
0593:                    QueryEvaluationException {
0594:                if (expr instanceof  Var) {
0595:                    return evaluate((Var) expr, bindings);
0596:                } else if (expr instanceof  ValueConstant) {
0597:                    return evaluate((ValueConstant) expr, bindings);
0598:                } else if (expr instanceof  BNodeGenerator) {
0599:                    return evaluate((BNodeGenerator) expr, bindings);
0600:                } else if (expr instanceof  Bound) {
0601:                    return evaluate((Bound) expr, bindings);
0602:                } else if (expr instanceof  Str) {
0603:                    return evaluate((Str) expr, bindings);
0604:                } else if (expr instanceof  Label) {
0605:                    return evaluate((Label) expr, bindings);
0606:                } else if (expr instanceof  Lang) {
0607:                    return evaluate((Lang) expr, bindings);
0608:                } else if (expr instanceof  LangMatches) {
0609:                    return evaluate((LangMatches) expr, bindings);
0610:                } else if (expr instanceof  Datatype) {
0611:                    return evaluate((Datatype) expr, bindings);
0612:                } else if (expr instanceof  Namespace) {
0613:                    return evaluate((Namespace) expr, bindings);
0614:                } else if (expr instanceof  LocalName) {
0615:                    return evaluate((LocalName) expr, bindings);
0616:                } else if (expr instanceof  IsResource) {
0617:                    return evaluate((IsResource) expr, bindings);
0618:                } else if (expr instanceof  IsURI) {
0619:                    return evaluate((IsURI) expr, bindings);
0620:                } else if (expr instanceof  IsBNode) {
0621:                    return evaluate((IsBNode) expr, bindings);
0622:                } else if (expr instanceof  IsLiteral) {
0623:                    return evaluate((IsLiteral) expr, bindings);
0624:                } else if (expr instanceof  Regex) {
0625:                    return evaluate((Regex) expr, bindings);
0626:                } else if (expr instanceof  Like) {
0627:                    return evaluate((Like) expr, bindings);
0628:                } else if (expr instanceof  FunctionCall) {
0629:                    return evaluate((FunctionCall) expr, bindings);
0630:                } else if (expr instanceof  And) {
0631:                    return evaluate((And) expr, bindings);
0632:                } else if (expr instanceof  Or) {
0633:                    return evaluate((Or) expr, bindings);
0634:                } else if (expr instanceof  Not) {
0635:                    return evaluate((Not) expr, bindings);
0636:                } else if (expr instanceof  SameTerm) {
0637:                    return evaluate((SameTerm) expr, bindings);
0638:                } else if (expr instanceof  Compare) {
0639:                    return evaluate((Compare) expr, bindings);
0640:                } else if (expr instanceof  MathExpr) {
0641:                    return evaluate((MathExpr) expr, bindings);
0642:                } else if (expr instanceof  In) {
0643:                    return evaluate((In) expr, bindings);
0644:                } else if (expr instanceof  CompareAny) {
0645:                    return evaluate((CompareAny) expr, bindings);
0646:                } else if (expr instanceof  CompareAll) {
0647:                    return evaluate((CompareAll) expr, bindings);
0648:                } else if (expr instanceof  Exists) {
0649:                    return evaluate((Exists) expr, bindings);
0650:                } else if (expr == null) {
0651:                    throw new IllegalArgumentException("expr must not be null");
0652:                } else {
0653:                    throw new QueryEvaluationException(
0654:                            "Unsupported value expr type: " + expr.getClass());
0655:                }
0656:            }
0657:
0658:            public Value evaluate(Var var, BindingSet bindings)
0659:                    throws ValueExprEvaluationException,
0660:                    QueryEvaluationException {
0661:                Value value = var.getValue();
0662:
0663:                if (value == null) {
0664:                    value = bindings.getValue(var.getName());
0665:                }
0666:
0667:                if (value == null) {
0668:                    throw new ValueExprEvaluationException();
0669:                }
0670:
0671:                return value;
0672:            }
0673:
0674:            public Value evaluate(ValueConstant valueConstant,
0675:                    BindingSet bindings) throws ValueExprEvaluationException,
0676:                    QueryEvaluationException {
0677:                return valueConstant.getValue();
0678:            }
0679:
0680:            public Value evaluate(BNodeGenerator node, BindingSet bindings)
0681:                    throws ValueExprEvaluationException,
0682:                    QueryEvaluationException {
0683:                return tripleSource.getValueFactory().createBNode();
0684:            }
0685:
0686:            public Value evaluate(Bound node, BindingSet bindings)
0687:                    throws QueryEvaluationException {
0688:                try {
0689:                    Value argValue = evaluate(node.getArg(), bindings);
0690:                    return BooleanLiteralImpl.valueOf(argValue != null);
0691:                } catch (ValueExprEvaluationException e) {
0692:                    return BooleanLiteralImpl.FALSE;
0693:                }
0694:            }
0695:
0696:            public Value evaluate(Str node, BindingSet bindings)
0697:                    throws ValueExprEvaluationException,
0698:                    QueryEvaluationException {
0699:                Value argValue = evaluate(node.getArg(), bindings);
0700:
0701:                if (argValue instanceof  URI) {
0702:                    return tripleSource.getValueFactory().createLiteral(
0703:                            argValue.toString());
0704:                } else if (argValue instanceof  Literal) {
0705:                    Literal literal = (Literal) argValue;
0706:
0707:                    if (QueryEvaluationUtil.isSimpleLiteral(literal)) {
0708:                        return literal;
0709:                    } else {
0710:                        return tripleSource.getValueFactory().createLiteral(
0711:                                literal.getLabel());
0712:                    }
0713:                } else {
0714:                    throw new ValueExprEvaluationException();
0715:                }
0716:            }
0717:
0718:            public Value evaluate(Label node, BindingSet bindings)
0719:                    throws ValueExprEvaluationException,
0720:                    QueryEvaluationException {
0721:                // FIXME: deprecate Label in favour of Str(?)
0722:                Value argValue = evaluate(node.getArg(), bindings);
0723:
0724:                if (argValue instanceof  Literal) {
0725:                    Literal literal = (Literal) argValue;
0726:
0727:                    if (QueryEvaluationUtil.isSimpleLiteral(literal)) {
0728:                        return literal;
0729:                    } else {
0730:                        return tripleSource.getValueFactory().createLiteral(
0731:                                literal.getLabel());
0732:                    }
0733:                } else {
0734:                    throw new ValueExprEvaluationException();
0735:                }
0736:            }
0737:
0738:            public Value evaluate(Lang node, BindingSet bindings)
0739:                    throws ValueExprEvaluationException,
0740:                    QueryEvaluationException {
0741:                Value argValue = evaluate(node.getArg(), bindings);
0742:
0743:                if (argValue instanceof  Literal) {
0744:                    Literal literal = (Literal) argValue;
0745:
0746:                    String langTag = literal.getLanguage();
0747:                    if (langTag == null) {
0748:                        langTag = "";
0749:                    }
0750:
0751:                    return tripleSource.getValueFactory()
0752:                            .createLiteral(langTag);
0753:                }
0754:
0755:                throw new ValueExprEvaluationException();
0756:            }
0757:
0758:            public Value evaluate(Datatype node, BindingSet bindings)
0759:                    throws ValueExprEvaluationException,
0760:                    QueryEvaluationException {
0761:                Value v = evaluate(node.getArg(), bindings);
0762:
0763:                if (v instanceof  Literal) {
0764:                    Literal literal = (Literal) v;
0765:
0766:                    if (literal.getDatatype() != null) {
0767:                        // literal with datatype
0768:                        return literal.getDatatype();
0769:                    } else if (literal.getLanguage() == null) {
0770:                        // simple literal
0771:                        return XMLSchema.STRING;
0772:                    }
0773:                }
0774:
0775:                throw new ValueExprEvaluationException();
0776:            }
0777:
0778:            public Value evaluate(Namespace node, BindingSet bindings)
0779:                    throws ValueExprEvaluationException,
0780:                    QueryEvaluationException {
0781:                Value argValue = evaluate(node.getArg(), bindings);
0782:
0783:                if (argValue instanceof  URI) {
0784:                    URI uri = (URI) argValue;
0785:                    return tripleSource.getValueFactory().createURI(
0786:                            uri.getNamespace());
0787:                } else {
0788:                    throw new ValueExprEvaluationException();
0789:                }
0790:            }
0791:
0792:            public Value evaluate(LocalName node, BindingSet bindings)
0793:                    throws ValueExprEvaluationException,
0794:                    QueryEvaluationException {
0795:                Value argValue = evaluate(node.getArg(), bindings);
0796:
0797:                if (argValue instanceof  URI) {
0798:                    URI uri = (URI) argValue;
0799:                    return tripleSource.getValueFactory().createLiteral(
0800:                            uri.getLocalName());
0801:                } else {
0802:                    throw new ValueExprEvaluationException();
0803:                }
0804:            }
0805:
0806:            /**
0807:             * Determines whether the operand (a variable) contains a Resource.
0808:             * 
0809:             * @return <tt>true</tt> if the operand contains a Resource, <tt>false</tt>
0810:             *         otherwise.
0811:             */
0812:            public Value evaluate(IsResource node, BindingSet bindings)
0813:                    throws ValueExprEvaluationException,
0814:                    QueryEvaluationException {
0815:                Value argValue = evaluate(node.getArg(), bindings);
0816:                return BooleanLiteralImpl.valueOf(argValue instanceof  Resource);
0817:            }
0818:
0819:            /**
0820:             * Determines whether the operand (a variable) contains a URI.
0821:             * 
0822:             * @return <tt>true</tt> if the operand contains a URI, <tt>false</tt>
0823:             *         otherwise.
0824:             */
0825:            public Value evaluate(IsURI node, BindingSet bindings)
0826:                    throws ValueExprEvaluationException,
0827:                    QueryEvaluationException {
0828:                Value argValue = evaluate(node.getArg(), bindings);
0829:                return BooleanLiteralImpl.valueOf(argValue instanceof  URI);
0830:            }
0831:
0832:            /**
0833:             * Determines whether the operand (a variable) contains a BNode.
0834:             * 
0835:             * @return <tt>true</tt> if the operand contains a BNode, <tt>false</tt>
0836:             *         otherwise.
0837:             */
0838:            public Value evaluate(IsBNode node, BindingSet bindings)
0839:                    throws ValueExprEvaluationException,
0840:                    QueryEvaluationException {
0841:                Value argValue = evaluate(node.getArg(), bindings);
0842:                return BooleanLiteralImpl.valueOf(argValue instanceof  BNode);
0843:            }
0844:
0845:            /**
0846:             * Determines whether the operand (a variable) contains a Literal.
0847:             * 
0848:             * @return <tt>true</tt> if the operand contains a Literal, <tt>false</tt>
0849:             *         otherwise.
0850:             */
0851:            public Value evaluate(IsLiteral node, BindingSet bindings)
0852:                    throws ValueExprEvaluationException,
0853:                    QueryEvaluationException {
0854:                Value argValue = evaluate(node.getArg(), bindings);
0855:                return BooleanLiteralImpl.valueOf(argValue instanceof  Literal);
0856:            }
0857:
0858:            /**
0859:             * Determines whether the two operands match according to the
0860:             * <code>regex</code> operator.
0861:             * 
0862:             * @return <tt>true</tt> if the operands match according to the
0863:             *         <tt>regex</tt> operator, <tt>false</tt> otherwise.
0864:             */
0865:            public Value evaluate(Regex node, BindingSet bindings)
0866:                    throws ValueExprEvaluationException,
0867:                    QueryEvaluationException {
0868:                Value arg = evaluate(node.getArg(), bindings);
0869:                Value parg = evaluate(node.getPatternArg(), bindings);
0870:                Value farg = null;
0871:                ValueExpr flagsArg = node.getFlagsArg();
0872:                if (flagsArg != null) {
0873:                    farg = evaluate(flagsArg, bindings);
0874:                }
0875:
0876:                if (QueryEvaluationUtil.isSimpleLiteral(arg)
0877:                        && QueryEvaluationUtil.isSimpleLiteral(parg)
0878:                        && (farg == null || QueryEvaluationUtil
0879:                                .isSimpleLiteral(farg))) {
0880:                    String text = ((Literal) arg).getLabel();
0881:                    String ptn = ((Literal) parg).getLabel();
0882:                    String flags = "";
0883:                    if (farg != null) {
0884:                        flags = ((Literal) farg).getLabel();
0885:                    }
0886:                    // TODO should this Pattern be cached?
0887:                    int f = 0;
0888:                    for (char c : flags.toCharArray()) {
0889:                        switch (c) {
0890:                        case 's':
0891:                            f |= Pattern.DOTALL;
0892:                            break;
0893:                        case 'm':
0894:                            f |= Pattern.MULTILINE;
0895:                            break;
0896:                        case 'i':
0897:                            f |= Pattern.CASE_INSENSITIVE;
0898:                            break;
0899:                        case 'x':
0900:                            f |= Pattern.COMMENTS;
0901:                            break;
0902:                        case 'd':
0903:                            f |= Pattern.UNIX_LINES;
0904:                            break;
0905:                        case 'u':
0906:                            f |= Pattern.UNICODE_CASE;
0907:                            break;
0908:                        default:
0909:                            throw new ValueExprEvaluationException(flags);
0910:                        }
0911:                    }
0912:                    Pattern pattern = Pattern.compile(ptn, f);
0913:                    boolean result = pattern.matcher(text).find();
0914:                    return BooleanLiteralImpl.valueOf(result);
0915:                }
0916:
0917:                throw new ValueExprEvaluationException();
0918:            }
0919:
0920:            public Value evaluate(LangMatches node, BindingSet bindings)
0921:                    throws ValueExprEvaluationException,
0922:                    QueryEvaluationException {
0923:                Value langTagValue = evaluate(node.getLeftArg(), bindings);
0924:                Value langRangeValue = evaluate(node.getRightArg(), bindings);
0925:
0926:                if (QueryEvaluationUtil.isSimpleLiteral(langTagValue)
0927:                        && QueryEvaluationUtil.isSimpleLiteral(langRangeValue)) {
0928:                    String langTag = ((Literal) langTagValue).getLabel();
0929:                    String langRange = ((Literal) langRangeValue).getLabel();
0930:
0931:                    boolean result = false;
0932:                    if (langRange.equals("*")) {
0933:                        result = langTag.length() > 0;
0934:                    } else if (langTag.length() == langRange.length()) {
0935:                        result = langTag.equalsIgnoreCase(langRange);
0936:                    } else if (langTag.length() > langRange.length()) {
0937:                        // check if the range is a prefix of the tag
0938:                        String prefix = langTag
0939:                                .substring(0, langRange.length());
0940:                        result = prefix.equalsIgnoreCase(langRange)
0941:                                && langTag.charAt(langRange.length()) == '-';
0942:                    }
0943:
0944:                    return BooleanLiteralImpl.valueOf(result);
0945:                }
0946:
0947:                throw new ValueExprEvaluationException();
0948:
0949:            }
0950:
0951:            /**
0952:             * Determines whether the two operands match according to the
0953:             * <code>like</code> operator. The operator is defined as a string
0954:             * comparison with the possible use of an asterisk (*) at the end and/or the
0955:             * start of the second operand to indicate substring matching.
0956:             * 
0957:             * @return <tt>true</tt> if the operands match according to the
0958:             *         <tt>like</tt> operator, <tt>false</tt> otherwise.
0959:             */
0960:            public Value evaluate(Like node, BindingSet bindings)
0961:                    throws ValueExprEvaluationException,
0962:                    QueryEvaluationException {
0963:                Value val = evaluate(node.getArg(), bindings);
0964:                String strVal = null;
0965:
0966:                if (val instanceof  URI) {
0967:                    strVal = ((URI) val).toString();
0968:                } else if (val instanceof  Literal) {
0969:                    strVal = ((Literal) val).getLabel();
0970:                }
0971:
0972:                if (strVal == null) {
0973:                    throw new ValueExprEvaluationException();
0974:                }
0975:
0976:                if (!node.isCaseSensitive()) {
0977:                    // Convert strVal to lower case, just like the pattern has been done
0978:                    strVal = strVal.toLowerCase();
0979:                }
0980:
0981:                int valIndex = 0;
0982:                int prevPatternIndex = -1;
0983:                int patternIndex = node.getOpPattern().indexOf('*');
0984:
0985:                if (patternIndex == -1) {
0986:                    // No wildcards
0987:                    return BooleanLiteralImpl.valueOf(node.getOpPattern()
0988:                            .equals(strVal));
0989:                }
0990:
0991:                String snippet;
0992:
0993:                if (patternIndex > 0) {
0994:                    // Pattern does not start with a wildcard, first part must match
0995:                    snippet = node.getOpPattern().substring(0, patternIndex);
0996:                    if (!strVal.startsWith(snippet)) {
0997:                        return BooleanLiteralImpl.FALSE;
0998:                    }
0999:
1000:                    valIndex += snippet.length();
1001:                    prevPatternIndex = patternIndex;
1002:                    patternIndex = node.getOpPattern().indexOf('*',
1003:                            patternIndex + 1);
1004:                }
1005:
1006:                while (patternIndex != -1) {
1007:                    // Get snippet between previous wildcard and this wildcard
1008:                    snippet = node.getOpPattern().substring(
1009:                            prevPatternIndex + 1, patternIndex);
1010:
1011:                    // Search for the snippet in the value
1012:                    valIndex = strVal.indexOf(snippet, valIndex);
1013:                    if (valIndex == -1) {
1014:                        return BooleanLiteralImpl.FALSE;
1015:                    }
1016:
1017:                    valIndex += snippet.length();
1018:                    prevPatternIndex = patternIndex;
1019:                    patternIndex = node.getOpPattern().indexOf('*',
1020:                            patternIndex + 1);
1021:                }
1022:
1023:                // Part after last wildcard
1024:                snippet = node.getOpPattern().substring(prevPatternIndex + 1);
1025:
1026:                if (snippet.length() > 0) {
1027:                    // Pattern does not end with a wildcard.
1028:
1029:                    // Search last occurence of the snippet.
1030:                    valIndex = strVal.indexOf(snippet, valIndex);
1031:                    int i;
1032:                    while ((i = strVal.indexOf(snippet, valIndex + 1)) != -1) {
1033:                        // A later occurence was found.
1034:                        valIndex = i;
1035:                    }
1036:
1037:                    if (valIndex == -1) {
1038:                        return BooleanLiteralImpl.FALSE;
1039:                    }
1040:
1041:                    valIndex += snippet.length();
1042:
1043:                    if (valIndex < strVal.length()) {
1044:                        // Some characters were not matched
1045:                        return BooleanLiteralImpl.FALSE;
1046:                    }
1047:                }
1048:
1049:                return BooleanLiteralImpl.TRUE;
1050:            }
1051:
1052:            /**
1053:             * Evaluates a function.
1054:             */
1055:            public Value evaluate(FunctionCall node, BindingSet bindings)
1056:                    throws ValueExprEvaluationException,
1057:                    QueryEvaluationException {
1058:                Function function = FunctionRegistry.getInstance().get(
1059:                        node.getURI());
1060:
1061:                if (function == null) {
1062:                    throw new QueryEvaluationException("Unknown function '"
1063:                            + node.getURI() + "'");
1064:                }
1065:
1066:                List<ValueExpr> args = node.getArgs();
1067:
1068:                Value[] argValues = new Value[args.size()];
1069:
1070:                for (int i = 0; i < args.size(); i++) {
1071:                    argValues[i] = evaluate(args.get(i), bindings);
1072:                }
1073:
1074:                return function.evaluate(tripleSource.getValueFactory(),
1075:                        argValues);
1076:            }
1077:
1078:            public Value evaluate(And node, BindingSet bindings)
1079:                    throws ValueExprEvaluationException,
1080:                    QueryEvaluationException {
1081:                try {
1082:                    Value leftValue = evaluate(node.getLeftArg(), bindings);
1083:                    if (QueryEvaluationUtil.getEffectiveBooleanValue(leftValue) == false) {
1084:                        // Left argument evaluates to false, we don't need to look any
1085:                        // further
1086:                        return BooleanLiteralImpl.FALSE;
1087:                    }
1088:                } catch (ValueExprEvaluationException e) {
1089:                    // Failed to evaluate the left argument. Result is 'false' when
1090:                    // the right argument evaluates to 'false', failure otherwise.
1091:                    Value rightValue = evaluate(node.getRightArg(), bindings);
1092:                    if (QueryEvaluationUtil
1093:                            .getEffectiveBooleanValue(rightValue) == false) {
1094:                        return BooleanLiteralImpl.FALSE;
1095:                    } else {
1096:                        throw new ValueExprEvaluationException();
1097:                    }
1098:                }
1099:
1100:                // Left argument evaluated to 'true', result is determined
1101:                // by the evaluation of the right argument.
1102:                Value rightValue = evaluate(node.getRightArg(), bindings);
1103:                return BooleanLiteralImpl.valueOf(QueryEvaluationUtil
1104:                        .getEffectiveBooleanValue(rightValue));
1105:            }
1106:
1107:            public Value evaluate(Or node, BindingSet bindings)
1108:                    throws ValueExprEvaluationException,
1109:                    QueryEvaluationException {
1110:                try {
1111:                    Value leftValue = evaluate(node.getLeftArg(), bindings);
1112:                    if (QueryEvaluationUtil.getEffectiveBooleanValue(leftValue) == true) {
1113:                        // Left argument evaluates to true, we don't need to look any
1114:                        // further
1115:                        return BooleanLiteralImpl.TRUE;
1116:                    }
1117:                } catch (ValueExprEvaluationException e) {
1118:                    // Failed to evaluate the left argument. Result is 'true' when
1119:                    // the right argument evaluates to 'true', failure otherwise.
1120:                    Value rightValue = evaluate(node.getRightArg(), bindings);
1121:                    if (QueryEvaluationUtil
1122:                            .getEffectiveBooleanValue(rightValue) == true) {
1123:                        return BooleanLiteralImpl.TRUE;
1124:                    } else {
1125:                        throw new ValueExprEvaluationException();
1126:                    }
1127:                }
1128:
1129:                // Left argument evaluated to 'false', result is determined
1130:                // by the evaluation of the right argument.
1131:                Value rightValue = evaluate(node.getRightArg(), bindings);
1132:                return BooleanLiteralImpl.valueOf(QueryEvaluationUtil
1133:                        .getEffectiveBooleanValue(rightValue));
1134:            }
1135:
1136:            public Value evaluate(Not node, BindingSet bindings)
1137:                    throws ValueExprEvaluationException,
1138:                    QueryEvaluationException {
1139:                Value argValue = evaluate(node.getArg(), bindings);
1140:                boolean argBoolean = QueryEvaluationUtil
1141:                        .getEffectiveBooleanValue(argValue);
1142:                return BooleanLiteralImpl.valueOf(!argBoolean);
1143:            }
1144:
1145:            public Value evaluate(SameTerm node, BindingSet bindings)
1146:                    throws ValueExprEvaluationException,
1147:                    QueryEvaluationException {
1148:                Value leftVal = evaluate(node.getLeftArg(), bindings);
1149:                Value rightVal = evaluate(node.getRightArg(), bindings);
1150:
1151:                return BooleanLiteralImpl.valueOf(leftVal != null
1152:                        && leftVal.equals(rightVal));
1153:            }
1154:
1155:            public Value evaluate(Compare node, BindingSet bindings)
1156:                    throws ValueExprEvaluationException,
1157:                    QueryEvaluationException {
1158:                Value leftVal = evaluate(node.getLeftArg(), bindings);
1159:                Value rightVal = evaluate(node.getRightArg(), bindings);
1160:
1161:                return BooleanLiteralImpl.valueOf(QueryEvaluationUtil.compare(
1162:                        leftVal, rightVal, node.getOperator()));
1163:            }
1164:
1165:            public Value evaluate(MathExpr node, BindingSet bindings)
1166:                    throws ValueExprEvaluationException,
1167:                    QueryEvaluationException {
1168:                // Do the math
1169:                Value leftVal = evaluate(node.getLeftArg(), bindings);
1170:                Value rightVal = evaluate(node.getRightArg(), bindings);
1171:
1172:                if (leftVal instanceof  Literal && rightVal instanceof  Literal) {
1173:                    return getValue((Literal) leftVal, (Literal) rightVal, node
1174:                            .getOperator());
1175:                }
1176:
1177:                return null;
1178:            }
1179:
1180:            public Value evaluate(In node, BindingSet bindings)
1181:                    throws ValueExprEvaluationException,
1182:                    QueryEvaluationException {
1183:                Value leftValue = evaluate(node.getArg(), bindings);
1184:
1185:                // Result is false until a match has been found
1186:                boolean result = false;
1187:
1188:                // Use first binding name from tuple expr to compare values
1189:                String bindingName = node.getSubQuery().getBindingNames()
1190:                        .iterator().next();
1191:
1192:                CloseableIteration<BindingSet, QueryEvaluationException> iter = evaluate(
1193:                        node.getSubQuery(), bindings);
1194:                try {
1195:                    while (result == false && iter.hasNext()) {
1196:                        BindingSet bindingSet = iter.next();
1197:
1198:                        Value rightValue = bindingSet.getValue(bindingName);
1199:
1200:                        result = leftValue == null && rightValue == null
1201:                                || leftValue != null
1202:                                && leftValue.equals(rightValue);
1203:                    }
1204:                } finally {
1205:                    iter.close();
1206:                }
1207:
1208:                return BooleanLiteralImpl.valueOf(result);
1209:            }
1210:
1211:            public Value evaluate(CompareAny node, BindingSet bindings)
1212:                    throws ValueExprEvaluationException,
1213:                    QueryEvaluationException {
1214:                Value leftValue = evaluate(node.getArg(), bindings);
1215:
1216:                // Result is false until a match has been found
1217:                boolean result = false;
1218:
1219:                // Use first binding name from tuple expr to compare values
1220:                String bindingName = node.getSubQuery().getBindingNames()
1221:                        .iterator().next();
1222:
1223:                CloseableIteration<BindingSet, QueryEvaluationException> iter = evaluate(
1224:                        node.getSubQuery(), bindings);
1225:                try {
1226:                    while (result == false && iter.hasNext()) {
1227:                        BindingSet bindingSet = iter.next();
1228:
1229:                        Value rightValue = bindingSet.getValue(bindingName);
1230:
1231:                        try {
1232:                            result = QueryEvaluationUtil.compare(leftValue,
1233:                                    rightValue, node.getOperator());
1234:                        } catch (ValueExprEvaluationException e) {
1235:                            // ignore, maybe next value will match
1236:                        }
1237:                    }
1238:                } finally {
1239:                    iter.close();
1240:                }
1241:
1242:                return BooleanLiteralImpl.valueOf(result);
1243:            }
1244:
1245:            public Value evaluate(CompareAll node, BindingSet bindings)
1246:                    throws ValueExprEvaluationException,
1247:                    QueryEvaluationException {
1248:                Value leftValue = evaluate(node.getArg(), bindings);
1249:
1250:                // Result is true until a mismatch has been found
1251:                boolean result = true;
1252:
1253:                // Use first binding name from tuple expr to compare values
1254:                String bindingName = node.getSubQuery().getBindingNames()
1255:                        .iterator().next();
1256:
1257:                CloseableIteration<BindingSet, QueryEvaluationException> iter = evaluate(
1258:                        node.getSubQuery(), bindings);
1259:                try {
1260:                    while (result == true && iter.hasNext()) {
1261:                        BindingSet bindingSet = iter.next();
1262:
1263:                        Value rightValue = bindingSet.getValue(bindingName);
1264:
1265:                        try {
1266:                            result = QueryEvaluationUtil.compare(leftValue,
1267:                                    rightValue, node.getOperator());
1268:                        } catch (ValueExprEvaluationException e) {
1269:                            // Exception thrown by ValueCompare.isTrue(...)
1270:                            result = false;
1271:                        }
1272:                    }
1273:                } finally {
1274:                    iter.close();
1275:                }
1276:
1277:                return BooleanLiteralImpl.valueOf(result);
1278:            }
1279:
1280:            public Value evaluate(Exists node, BindingSet bindings)
1281:                    throws ValueExprEvaluationException,
1282:                    QueryEvaluationException {
1283:                CloseableIteration<BindingSet, QueryEvaluationException> iter = evaluate(
1284:                        node.getSubQuery(), bindings);
1285:                try {
1286:                    return BooleanLiteralImpl.valueOf(iter.hasNext());
1287:                } finally {
1288:                    iter.close();
1289:                }
1290:            }
1291:
1292:            public boolean isTrue(ValueExpr expr, BindingSet bindings)
1293:                    throws QueryEvaluationException {
1294:                try {
1295:                    Value value = evaluate(expr, bindings);
1296:                    return QueryEvaluationUtil.getEffectiveBooleanValue(value);
1297:                } catch (ValueExprEvaluationException e) {
1298:                    return false;
1299:                }
1300:            }
1301:
1302:            private static Literal getValue(Literal leftLit, Literal rightLit,
1303:                    MathOp op) {
1304:                URI leftDatatype = leftLit.getDatatype();
1305:                URI rightDatatype = rightLit.getDatatype();
1306:
1307:                // Only numeric value can be used in math expressions
1308:                if (leftDatatype != null && rightDatatype != null
1309:                        && XMLDatatypeUtil.isNumericDatatype(leftDatatype)
1310:                        && XMLDatatypeUtil.isNumericDatatype(rightDatatype)) {
1311:                    // Determine most specific datatype that the arguments have in common,
1312:                    // choosing from xsd:integer, xsd:decimal, xsd:float and xsd:double as
1313:                    // per the SPARQL/XPATH spec
1314:                    URI commonDatatype;
1315:
1316:                    if (leftDatatype.equals(XMLSchema.DOUBLE)
1317:                            || rightDatatype.equals(XMLSchema.DOUBLE)) {
1318:                        commonDatatype = XMLSchema.DOUBLE;
1319:                    } else if (leftDatatype.equals(XMLSchema.FLOAT)
1320:                            || rightDatatype.equals(XMLSchema.FLOAT)) {
1321:                        commonDatatype = XMLSchema.FLOAT;
1322:                    } else if (leftDatatype.equals(XMLSchema.DECIMAL)
1323:                            || rightDatatype.equals(XMLSchema.DECIMAL)) {
1324:                        commonDatatype = XMLSchema.DECIMAL;
1325:                    } else if (op == MathOp.DIVIDE) {
1326:                        // Result of integer divide is decimal and requires the arguments to
1327:                        // be handled as such, see for details:
1328:                        // http://www.w3.org/TR/xpath-functions/#func-numeric-divide
1329:                        commonDatatype = XMLSchema.DECIMAL;
1330:                    } else {
1331:                        commonDatatype = XMLSchema.INTEGER;
1332:                    }
1333:
1334:                    // Note: Java already handles cases like divide-by-zero appropriately
1335:                    // for floats and doubles, see:
1336:                    // http://www.particle.kth.se/~lindsey/JavaCourse/Book/Part1/Tech/Chapter02/floatingPt2.html
1337:
1338:                    try {
1339:                        if (commonDatatype.equals(XMLSchema.DOUBLE)) {
1340:                            double left = leftLit.doubleValue();
1341:                            double right = rightLit.doubleValue();
1342:
1343:                            switch (op) {
1344:                            case PLUS:
1345:                                return new NumericLiteralImpl(left + right);
1346:                            case MINUS:
1347:                                return new NumericLiteralImpl(left - right);
1348:                            case MULTIPLY:
1349:                                return new NumericLiteralImpl(left * right);
1350:                            case DIVIDE:
1351:                                return new NumericLiteralImpl(left / right);
1352:                            default:
1353:                                throw new IllegalArgumentException(
1354:                                        "Unknown operator: " + op);
1355:                            }
1356:                        } else if (commonDatatype.equals(XMLSchema.FLOAT)) {
1357:                            float left = leftLit.floatValue();
1358:                            float right = rightLit.floatValue();
1359:
1360:                            switch (op) {
1361:                            case PLUS:
1362:                                return new NumericLiteralImpl(left + right);
1363:                            case MINUS:
1364:                                return new NumericLiteralImpl(left - right);
1365:                            case MULTIPLY:
1366:                                return new NumericLiteralImpl(left * right);
1367:                            case DIVIDE:
1368:                                return new NumericLiteralImpl(left / right);
1369:                            default:
1370:                                throw new IllegalArgumentException(
1371:                                        "Unknown operator: " + op);
1372:                            }
1373:                        } else if (commonDatatype.equals(XMLSchema.DECIMAL)) {
1374:                            BigDecimal left = leftLit.decimalValue();
1375:                            BigDecimal right = rightLit.decimalValue();
1376:
1377:                            switch (op) {
1378:                            case PLUS:
1379:                                return new DecimalLiteralImpl(left.add(right));
1380:                            case MINUS:
1381:                                return new DecimalLiteralImpl(left
1382:                                        .subtract(right));
1383:                            case MULTIPLY:
1384:                                return new DecimalLiteralImpl(left
1385:                                        .multiply(right));
1386:                            case DIVIDE:
1387:                                // Divide by zero handled through NumberFormatException
1388:                                return new DecimalLiteralImpl(left.divide(
1389:                                        right, RoundingMode.HALF_UP));
1390:                            default:
1391:                                throw new IllegalArgumentException(
1392:                                        "Unknown operator: " + op);
1393:                            }
1394:                        } else { // XMLSchema.INTEGER
1395:                            BigInteger left = leftLit.integerValue();
1396:                            BigInteger right = rightLit.integerValue();
1397:
1398:                            switch (op) {
1399:                            case PLUS:
1400:                                return new IntegerLiteralImpl(left.add(right));
1401:                            case MINUS:
1402:                                return new IntegerLiteralImpl(left
1403:                                        .subtract(right));
1404:                            case MULTIPLY:
1405:                                return new IntegerLiteralImpl(left
1406:                                        .multiply(right));
1407:                            case DIVIDE:
1408:                                throw new RuntimeException(
1409:                                        "Integer divisions should be processed as decimal divisions");
1410:                            default:
1411:                                throw new IllegalArgumentException(
1412:                                        "Unknown operator: " + op);
1413:                            }
1414:                        }
1415:                    } catch (NumberFormatException e) {
1416:                        return null;
1417:                    } catch (ArithmeticException e) {
1418:                        return null;
1419:                    }
1420:                }
1421:
1422:                return null;
1423:            }
1424:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.