/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Various modifications to this file copyright: * The Australian Commonwealth Government * Department of Defense * Developed by Netymon Pty Ltd * under contract 4500430665 * contributed to the Kowari Project under the * Mozilla Public License version 1.1 * per clause 4.1.3 of the above contract. * * Various modifications to this file copyright: * 2005-2006 Netymon Pty Ltd: mail@netymon.com * * Various modifications to this file copyright: * 2005-2007 Andrae Muys: andrae@muys.id.au * * getModel() contributed by Netymon Pty Ltd on behalf of * The Australian Commonwealth Government under contract 4500507038. * ConstraintLocalization contributed by Netymon Pty Ltd on behalf of * The Australian Commonwealth Government under contract 4500507038. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.resolver; // Java 2 standard packages import java.util.*; // Third party packages import org.apache.log4j.Logger; import org.jrdf.graph.URIReference; // Local packages import org.mulgara.query.*; import org.mulgara.query.filter.SameTerm; import org.mulgara.query.filter.value.Var; import org.mulgara.query.rdf.URIReferenceImpl; import org.mulgara.resolver.spi.ConstraintBindingHandler; import org.mulgara.resolver.spi.ConstraintLocalization; import org.mulgara.resolver.spi.ConstraintGraphRewrite; import org.mulgara.resolver.spi.ConstraintResolutionHandler; import org.mulgara.resolver.spi.ConstraintVariableRewrite; import org.mulgara.resolver.spi.GraphResolutionHandler; import org.mulgara.resolver.spi.QueryEvaluationContext; import org.mulgara.store.tuples.Tuples; import org.mulgara.store.tuples.TuplesOperations; import org.mulgara.util.NVPair; /** * Provides handlers for the standard constraints included in mulgara. * * @created 2007-11-09 * @author <a href="mailto:andrae@netymon.com">Andrae Muys</a> * @company <a href="http://www.netymon.com">Netymon Pty Ltd</a> * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ class DefaultConstraintHandlers { /** Logger. */ @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(DefaultConstraintHandlers.class.getName()); static void initializeHandlers() { initializeModelResolutionHandlers(); initializeConstraintResolutionHandlers(); initializeConstraintBindingHandlers(); initializeConstraintModelRewrites(); initializeConstraintVariableRewrites(); initializeConstraintLocalizations(); } @SuppressWarnings("unchecked") static void initializeModelResolutionHandlers() { ConstraintOperations.addModelResolutionHandlers(new NVPair[] { new NVPair<Class<GraphUnion>, GraphResolutionHandler>(GraphUnion.class, new GraphResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, Constraint constraint) throws Exception { Tuples lhs = ConstraintOperations. resolveModelExpression(context, ((GraphOperation)modelExpr).getLHS(), constraint); Tuples rhs = ConstraintOperations. resolveModelExpression(context, ((GraphOperation)modelExpr).getRHS(), constraint); Tuples result = null; try { result = TuplesOperations.append(lhs, rhs); lhs.close(); lhs = null; rhs.close(); return result; } finally { if (lhs != null) { // result != null means failed during lhs.close() if (result == null) lhs.close(); rhs.close(); } // else failed during rhs.close() } } }), new NVPair<Class<GraphIntersection>, GraphResolutionHandler>(GraphIntersection.class, new GraphResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, Constraint constraint) throws Exception { Tuples lhs = ConstraintOperations. resolveModelExpression(context, ((GraphOperation)modelExpr).getLHS(), constraint); Tuples rhs = ConstraintOperations. resolveModelExpression(context, ((GraphOperation)modelExpr).getRHS(), constraint); Tuples result = null; try { result = TuplesOperations.join(lhs, rhs); lhs.close(); lhs = null; rhs.close(); return result; } catch (TuplesException e) { if (lhs != null) { // haven't closed anything yet if (result == null) lhs.close(); // if result is set then exception due to lhs.close rhs.close(); } // else means failed during rhs.close throw e; } } }), new NVPair<Class<GraphResource>, GraphResolutionHandler>(GraphResource.class, new GraphResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, Constraint constraint) throws Exception { return context.resolve((GraphResource)modelExpr, (Constraint)constraint); } }), new NVPair<Class<GraphVariable>, GraphResolutionHandler>(GraphVariable.class, new GraphResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, Constraint constraint) throws Exception { Variable modelVar = ((GraphVariable)modelExpr).getVariable(); if (constraint.getVariables().contains(modelVar)) { // need to change the re-write and wrap the result in a filter Variable newVar = new Variable("*" + modelVar.getName() + "0"); constraint = ConstraintOperations.rewriteConstraintVariable(modelVar, newVar, constraint); Tuples result = context.resolve(null, constraint); return TuplesOperations.filter(result, new SameTerm(convert(newVar), convert(modelVar)), context); } return context.resolve(null, ConstraintOperations.rewriteConstraintModel(modelVar, constraint)); } }) }); } /** Utility for converting a Variable to a filterable Var */ static Var convert(Variable v) { return new Var(v.getName()); } @SuppressWarnings("unchecked") static void initializeConstraintResolutionHandlers() { ConstraintOperations.addConstraintResolutionHandlers(new NVPair[] { new NVPair<Class<ConstraintConjunction>, ConstraintResolutionHandler>(ConstraintConjunction.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { List<Tuples> l = context.resolveConstraintOperation(modelExpr, (ConstraintOperation)constraintExpr); try { return TuplesOperations.join(l); } finally { Iterator<?> i = l.iterator(); while (i.hasNext()) { ((Tuples)i.next()).close(); } } } }), new NVPair<Class<ConstraintDisjunction>, ConstraintResolutionHandler>(ConstraintDisjunction.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { List<Tuples> l = context.resolveConstraintOperation(modelExpr, (ConstraintOperation)constraintExpr); try { if (context.isDistinctQuery()) return TuplesOperations.append(l); else return TuplesOperations.unorderedAppend(l); } finally { Iterator<?> i = l.iterator(); while (i.hasNext()) { ((Tuples)i.next()).close(); } } } }), new NVPair<Class<ConstraintDifference>, ConstraintResolutionHandler>(ConstraintDifference.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { List<ConstraintExpression> constraints = ((ConstraintOperation)constraintExpr).getElements(); assert constraints.size() == 2; Tuples lhs = ConstraintOperations.resolveConstraintExpression(context, modelExpr, constraints.get(0)); // The RHS must be searchable, so it must return a distinct result // since DISTINCT forces sorting boolean distinct = context.setDistinctQuery(true); Tuples rhs = ConstraintOperations.resolveConstraintExpression(context, modelExpr, constraints.get(1)); context.setDistinctQuery(distinct); Tuples result = null; try { result = TuplesOperations.subtract(lhs, rhs); lhs.close(); lhs = null; rhs.close(); return result; } finally { if (lhs != null) { // result != null means failed during lhs.close() if (result == null) lhs.close(); rhs.close(); } // else failed during rhs.close() } } }), new NVPair<Class<ConstraintOptionalJoin>, ConstraintResolutionHandler>(ConstraintOptionalJoin.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { List<Tuples> args = context.resolveConstraintOperation(modelExpr, (ConstraintOperation)constraintExpr); assert args.size() == 2; Tuples result = null, a0 = (Tuples)args.get(0), a1 = (Tuples)args.get(1); try { result = TuplesOperations.optionalJoin(a0, a1, ((ConstraintOptionalJoin)constraintExpr).getFilter(), context); a0.close(); a0 = null; a1.close(); return result; } finally { if (a0 != null) { // result != null means failed during a0.close() if (result == null) a0.close(); a1.close(); } // else failed during a1.close() } } }), new NVPair<Class<ConstraintIs>, ConstraintResolutionHandler>(ConstraintIs.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { ConstraintIs constraint = (ConstraintIs)constraintExpr; return TuplesOperations.assign((Variable)context.localize(constraint.getVariable()), ((LocalNode)context.localize(constraint.getValueNode())).getValue()); } }), new NVPair<Class<ConstraintAssignment>, ConstraintResolutionHandler>(ConstraintAssignment.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { ConstraintAssignment assignment = (ConstraintAssignment)constraintExpr; Tuples arg = ConstraintOperations.resolveConstraintExpression(context, modelExpr, assignment.getContextConstraint()); return TuplesOperations.assign(arg, assignment.getVariable(), assignment.getExpression(), context); } }), new NVPair<Class<ConstraintImpl>, ConstraintResolutionHandler>(ConstraintImpl.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { ConstraintImpl constraint = (ConstraintImpl)constraintExpr; ConstraintElement constraintElem = constraint.getModel(); assert constraintElem != null; if (constraintElem.equals(Variable.FROM)) { return ConstraintOperations.resolveModelExpression(context, modelExpr, constraint); } else if (constraintElem instanceof URIReference) { return ConstraintOperations.resolveModelExpression(context, new GraphResource(((URIReference)constraintElem).getURI()), constraint); } else if (constraintElem instanceof LocalNode) { return context.resolve(null, constraint); } else if (constraintElem instanceof Variable) { for (int i = 0; i < 3; i++) { if (constraintElem.equals(constraint.getElement(i))) { GraphVariable modelVar = new GraphVariable((Variable)constraintElem); return ConstraintOperations.resolveModelExpression(context, modelVar, constraint); } } return context.resolve(null, (ConstraintImpl)constraintExpr); } else { throw new QueryException("Specified model not a URIReference/Variable: " + constraintElem +" is a " + constraintElem.getClass().getName() ); } } }), new NVPair<Class<WalkConstraint>, ConstraintResolutionHandler>(WalkConstraint.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { return WalkFunction.walk(context, (WalkConstraint)constraintExpr, modelExpr, context.getResolverSession()); } }), new NVPair<Class<SingleTransitiveConstraint>, ConstraintResolutionHandler>(SingleTransitiveConstraint.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { SingleTransitiveConstraint constraint = (SingleTransitiveConstraint)constraintExpr; if (constraint.isAnchored()) { return DirectTransitiveFunction.infer(context, constraint, modelExpr, context.getResolverSession()); } else { return ExhaustiveTransitiveFunction.infer(context, constraint, modelExpr, context.getResolverSession()); } } }), new NVPair<Class<TransitiveConstraint>, ConstraintResolutionHandler>(TransitiveConstraint.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { return ExhaustiveTransitiveFunction.infer(context, (TransitiveConstraint)constraintExpr, modelExpr, context.getResolverSession()); } }), new NVPair<Class<ConstraintFilter>, ConstraintResolutionHandler>(ConstraintFilter.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { Tuples unfiltered = ConstraintOperations.resolveConstraintExpression(context, modelExpr, ((ConstraintFilter)constraintExpr).getUnfilteredConstraint()); Tuples result = null; try { result = TuplesOperations.filter(unfiltered, ((ConstraintFilter)constraintExpr).getFilter(), context); unfiltered.close(); return result; } catch (TuplesException e) { // result != null means that exception occurred during unfiltered.close() if (result == null) unfiltered.close(); throw e; } } }), new NVPair<Class<ConstraintIn>, ConstraintResolutionHandler>(ConstraintIn.class, new ConstraintResolutionHandler() { public Tuples resolve(QueryEvaluationContext context, GraphExpression modelExpr, ConstraintExpression constraintExpr) throws Exception { ConstraintIn constraint = (ConstraintIn)constraintExpr; GraphExpression graph; if (constraint.getGraph() instanceof URIReferenceImpl) { graph = new GraphResource(((URIReferenceImpl)constraint.getGraph()).getURI()); } else { assert constraint.getGraph() instanceof Variable; graph = new GraphVariable((Variable)constraint.getGraph()); } return ConstraintOperations.resolveConstraintExpression(context, graph, constraint.getConstraintParam()); } }), }); } @SuppressWarnings("unchecked") static void initializeConstraintBindingHandlers() { ConstraintOperations.addConstraintBindingHandlers(new NVPair[] { new NVPair<Class<ConstraintTrue>, ConstraintBindingHandler>(ConstraintTrue.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return constraintExpr; } }), new NVPair<Class<ConstraintFalse>, ConstraintBindingHandler>(ConstraintFalse.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return constraintExpr; } }), new NVPair<Class<ConstraintImpl>, ConstraintBindingHandler>(ConstraintImpl.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return ConstraintOperations.replace(bindings, (Constraint)constraintExpr); } }), new NVPair<Class<ConstraintIs>, ConstraintBindingHandler>(ConstraintIs.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return ConstraintOperations.replace(bindings, (Constraint)constraintExpr); } }), new NVPair<Class<SingleTransitiveConstraint>, ConstraintBindingHandler>(SingleTransitiveConstraint.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return new SingleTransitiveConstraint(ConstraintOperations.replace(bindings, (Constraint)constraintExpr)); } }), new NVPair<Class<TransitiveConstraint>, ConstraintBindingHandler>(TransitiveConstraint.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { TransitiveConstraint tc = (TransitiveConstraint)constraintExpr; return new TransitiveConstraint(ConstraintOperations.replace(bindings, tc.getAnchoredConstraint()), ConstraintOperations.replace(bindings, tc.getUnanchoredConstraint())); } }), new NVPair<Class<WalkConstraint>, ConstraintBindingHandler>(WalkConstraint.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { WalkConstraint wc = (WalkConstraint)constraintExpr; return new WalkConstraint(ConstraintOperations.replace(bindings, wc.getAnchoredConstraint()), ConstraintOperations.replace(bindings, wc.getUnanchoredConstraint())); } }), new NVPair<Class<ConstraintFilter>, ConstraintBindingHandler>(ConstraintFilter.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return new ConstraintFilter(ConstraintOperations.replace(bindings, (Constraint)constraintExpr), ((ConstraintFilter)constraintExpr).getFilter()); } }), new NVPair<Class<ConstraintConjunction>, ConstraintBindingHandler>(ConstraintConjunction.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return new ConstraintConjunction(ConstraintOperations.replaceOperationArgs(bindings, (ConstraintOperation)constraintExpr)); } }), new NVPair<Class<ConstraintDisjunction>, ConstraintBindingHandler>(ConstraintDisjunction.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { return new ConstraintDisjunction(ConstraintOperations.replaceOperationArgs(bindings, (ConstraintOperation)constraintExpr)); } }), new NVPair<Class<ConstraintDifference>, ConstraintBindingHandler>(ConstraintDifference.class, new ConstraintBindingHandler() { public ConstraintExpression bindVariables(Map<Variable, Value> bindings, ConstraintExpression constraintExpr) throws Exception { List<?> args = ConstraintOperations.replaceOperationArgs(bindings, (ConstraintOperation)constraintExpr); return new ConstraintDifference((ConstraintExpression)args.get(0), (ConstraintExpression)args.get(1)); } }), }); } @SuppressWarnings("unchecked") static void initializeConstraintModelRewrites() { ConstraintOperations.addConstraintModelRewrites(new NVPair[] { new NVPair<Class<ConstraintImpl>, ConstraintGraphRewrite>(ConstraintImpl.class, new ConstraintGraphRewrite() { public Constraint rewrite(ConstraintElement newModel, Constraint constraint) throws Exception { return new ConstraintImpl(constraint.getElement(0), constraint.getElement(1), constraint.getElement(2), newModel); } }), }); } @SuppressWarnings("unchecked") static void initializeConstraintVariableRewrites() { ConstraintOperations.addConstraintVariableRewrites(new NVPair[] { new NVPair<Class<ConstraintImpl>, ConstraintVariableRewrite>(ConstraintImpl.class, new ConstraintVariableRewrite() { public Constraint rewrite(Variable modelVar, Variable newVar, Constraint constraint) throws Exception { ConstraintElement[] ce = new ConstraintElement[3]; for (int e = 0; e < ce.length; e++) { ce[e] = constraint.getElement(e); if (ce[e] instanceof Variable && ((Variable)ce[e]).getName().equals(modelVar.getName())) { ce[e] = newVar; } } return new ConstraintImpl(ce[0], ce[1], ce[2], modelVar); } }), }); } @SuppressWarnings("unchecked") static void initializeConstraintLocalizations() { ConstraintOperations.addConstraintLocalizations(new NVPair[] { new NVPair<Class<ConstraintImpl>, ConstraintLocalization>(ConstraintImpl.class, new ConstraintLocalization() { public Constraint localize(QueryEvaluationContext context, Constraint constraint) throws Exception { return new ConstraintImpl(context.localize(constraint.getElement(0)), context.localize(constraint.getElement(1)), context.localize(constraint.getElement(2)), context.localize(constraint.getElement(3))); } }), }); } }