/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source: /cvsroot/slrp/glitter/com.ibm.adtech.glitter/src/com/ibm/adtech/glitter/query/rewriter/VariableRewriter.java,v $ * Created by: Lee Feigenbaum (<a href="mailto:feigenbl@us.ibm.com">feigenbl@us.ibm.com</a>) * Created on: 10/23/06 * Revision: $Id: VariableRewriter.java 164 2007-07-31 14:11:09Z mroy $ * * Contributors: IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.glitter.query.rewriter; import java.util.ArrayList; import java.util.Map; import java.util.Set; import org.openanzo.exceptions.LogUtils; import org.openanzo.glitter.query.TreeRewriter; import org.openanzo.glitter.syntax.abstrakt.Expression; import org.openanzo.glitter.syntax.abstrakt.Graph; import org.openanzo.glitter.syntax.abstrakt.GraphPattern; import org.openanzo.glitter.syntax.abstrakt.Optional; import org.openanzo.glitter.syntax.abstrakt.TreeNode; import org.openanzo.glitter.syntax.abstrakt.TriplePatternNode; import org.openanzo.glitter.util.Glitter; import org.openanzo.rdf.Bindable; import org.openanzo.rdf.TriplePattern; import org.openanzo.rdf.TriplePatternComponent; import org.openanzo.rdf.Value; import org.openanzo.rdf.Variable; /** * The {@link VariableRewriter} rewrites a triple pattern that contains a variable which is bound to only a single value in the supplied bindings. * * @author lee <lee@cambridgesemantics.com> * */ public class VariableRewriter implements TreeRewriter { private final Map<Bindable, Value> bindings; /** * Constructor. * * @param bindings * Current bindings. */ public VariableRewriter(Map<Bindable, Value> bindings) { this.bindings = bindings; } private boolean bindableBoundInOptionalOnly(Bindable b, TreeNode node) { if (!(b instanceof Variable)) return false; Variable v = (Variable) b; ArrayList<Optional> optionalAncestors = new ArrayList<Optional>(); TreeNode p = node.getParent(); while (p != null) { if (p instanceof Optional) optionalAncestors.add((Optional) p); p = p.getParent(); } for (Optional o : optionalAncestors) { GraphPattern must = o.getMustMatchPattern(); if (must == null || must.mightBindVariable(v)) return true; } return false; } public TreeNode rewriteTreeNode(TreeNode node) { if (node instanceof Graph) { Graph graph = (Graph) node; TriplePatternComponent context = graph.getGraphContext(); if (context instanceof Bindable) { Value value = this.bindings.get(context); if (value != null && !inScopeFilterReferencesBindable(node, (Bindable) context) && !bindableBoundInOptionalOnly((Bindable) context, node)) { Glitter.getLog().debug(LogUtils.GLITTER_MARKER, "Replacing graph variable with bound value"); return new Graph(value, graph.getGraphPattern()); } } } else if (node instanceof TriplePatternNode) { TriplePattern pattern = ((TriplePatternNode) node).getTriplePattern(); TriplePatternComponent subject = pattern.getSubject(), predicate = pattern.getPredicate(), object = pattern.getObject(); boolean buildNewPattern = false; if (subject instanceof Bindable) { Value value = this.bindings.get(subject); if (value != null && !inScopeFilterReferencesBindable(node, (Bindable) subject) && !bindableBoundInOptionalOnly((Bindable) subject, node)) { Glitter.getLog().debug(LogUtils.GLITTER_MARKER, "Replacing subject variable ({}) with bound value", subject); subject = value; buildNewPattern = true; } } if (predicate instanceof Bindable) { Value value = this.bindings.get(predicate); if (value != null && !inScopeFilterReferencesBindable(node, (Bindable) predicate) && !bindableBoundInOptionalOnly((Bindable) predicate, node)) { Glitter.getLog().debug(LogUtils.GLITTER_MARKER, "Replacing predicate variable with bound value"); predicate = value; buildNewPattern = true; } } if (object instanceof Bindable) { Value value = this.bindings.get(object); if (value != null && !inScopeFilterReferencesBindable(node, (Bindable) object) && !bindableBoundInOptionalOnly((Bindable) object, node)) { Glitter.getLog().debug(LogUtils.GLITTER_MARKER, "Replacing object variable with bound value"); object = value; buildNewPattern = true; } } if (buildNewPattern) return new TriplePatternNode(subject, predicate, object); } return node; } private boolean inScopeFilterReferencesBindable(TreeNode n, Bindable b) { Set<Expression> filters = n.getInScopeFilterSet(); for (Expression filter : filters) if (filter.getReferencedVariables().contains(b)) return true; return false; } }