/* * Copyright 2008 Fedora Commons, Inc. * * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.mulgara.krule.rlog.ast; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; import org.mulgara.krule.rlog.ParseContext; import org.mulgara.krule.rlog.parser.URIParseException; import org.mulgara.krule.rlog.rdf.RDFNode; import org.mulgara.krule.rlog.rdf.URIReference; import org.mulgara.krule.rlog.rdf.Var; import static org.mulgara.util.ObjectUtil.eq; /** * A predicate in a statement appearing in the AST. * * @created May 16, 2008 * @author Paula Gearon * @copyright © 2008 <a href="http://www.fedora-commons.org/">Fedora Commons</a> */ public abstract class Predicate extends Node { /** The parent node in the AST. Always a statement. */ private Statement parent; /** The predicate value of this predicate. */ protected RDFNode predicate = null; /** The subject of this predicate. */ protected RDFNode subject = null; /** The object of this predicate. */ protected RDFNode object = null; /** The graph of this predicate. */ protected URIReference graphAnnotation = null; /** The exception generated when trying to parse the predicate. Hopwefully null. */ protected URIParseException delayedPredicateException = null; /** The exception generated when trying to parse the predicate. Hopwefully null. */ protected URIParseException delayedSubjectException = null; /** The exception generated when trying to parse the predicate. Hopwefully null. */ protected URIParseException delayedObjectException = null; /** * Create this predicate instance, with the context it requires. * @param context The context passed in from the parser. */ public Predicate(ParseContext context) { super(context); } /** * Sets the parent AST node. * @param parent The statement which contains this predicate. */ public void setParent(Statement parent) { this.parent = parent; } /** * Gets the parent AST node. Always returns a statement. * @return The Statement containing this node. */ public Statement getParent() { return parent; } /** * Check if any variables are referenced by this predicate. More efficient implementation * of !getVariables().isEmpty() * @return <code>true</code> if there are any variables in this predicate. */ public boolean containsVariables() { return !getVariables().isEmpty(); } /** * Get all variables referred to in this predicate. * @return a collection with all the variable, or zero veriables if none are referenced. */ public abstract Collection<Var> getVariables(); /** * Get the subject of this predicate. * @return Either a URIReference, or a variable */ public RDFNode getSubject() throws URIParseException { if (subject != null) return subject; throw delayedSubjectException; } /** * Get the predicate of this predicate. * @return Either a URIReference, or a variable */ public RDFNode getPredicate() throws URIParseException { if (predicate != null) return predicate; throw delayedPredicateException; } /** * Get the object of this predicate. * @return Either a URIReference, a variable, or a literal */ public RDFNode getObject() throws URIParseException { if (object != null) return object; throw delayedObjectException; } /** * Indicates that this predicate has an annotation on how it gets resolved. * @return <code>true</code> if a resolution annotation exists. */ public boolean hasGraphAnnotation() { return graphAnnotation != null; } /** * Retrieves the graph annotation for this predicate. * @return The graph for resolving this predicate. */ public URIReference getGraphAnnotation() throws URIParseException { return graphAnnotation; } /** * Gets the elements from this relationship that are references. * @return An ordered set containing the references. * @throws URIParseException The references had invalid syntax. */ public Set<URIReference> getReferences() throws URIParseException { Set<URIReference> refs = new LinkedHashSet<URIReference>(); RDFNode n = getSubject(); if (n.isReference()) refs.add((URIReference)n); n = getPredicate(); if (n.isReference()) refs.add((URIReference)n); n = getObject(); if (n.isReference()) refs.add((URIReference)n); return refs; } /** * Tests if this predicate possibly matches a pattern of subject/predicate/object * @param s The subject from the pattern to test for match. * @param p The predicate from the pattern to test for match. * @param o The object from the pattern to test for match. * @return <code>false</code> if this predicate cannote matches the subject/predicate/object, * <code>true</code> otherwise. */ public boolean matches(RDFNode s, RDFNode p, RDFNode o) throws URIParseException { RDFNode localS = getSubject(); RDFNode localP = getPredicate(); RDFNode localO = getObject(); // can only fail if both are not variable and not equal if (!s.isVariable() && !localS.isVariable() && !localS.equals(s)) return false; if (!p.isVariable() && !localP.isVariable() && !localP.equals(p)) return false; if (!o.isVariable() && !localO.isVariable() && !localO.equals(o)) return false; // this rule has the potential to match the pattern return true; } /** {@inheritDoc} */ public boolean equals(Object o) { if (!(o instanceof Predicate)) return false; Predicate p = (Predicate)o; return eq(predicate, p.predicate) && eq(subject, p.subject) && eq(object, p.object) && eq(graphAnnotation, p.graphAnnotation); } /** * Returns a canonical version of this predicate. * @return A new canonical predicate, with canonicalized elements. */ abstract CanonicalPredicate getCanonical(); /** * Converts a Variable to a Var. Accepts multiple types. * @param v The Variable to convert. This must be a Variable. * @return a new Var that is equivalent to the v. * @throws ClassCastException If something other than a Variable is passed in. */ protected Var toVar(Object v) { return new Var(((Variable)v).name); } }