001: /*
002: * (c) Copyright 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: * All rights reserved.
004: * [See end of file]
005: */
006:
007: package arq.examples.propertyfunction;
008:
009: import java.util.*;
010:
011: import com.hp.hpl.jena.graph.Graph;
012: import com.hp.hpl.jena.graph.Node;
013: import com.hp.hpl.jena.graph.Triple;
014: import com.hp.hpl.jena.sparql.core.Var;
015: import com.hp.hpl.jena.sparql.engine.ExecutionContext;
016: import com.hp.hpl.jena.sparql.engine.QueryIterator;
017: import com.hp.hpl.jena.sparql.engine.binding.Binding;
018: import com.hp.hpl.jena.sparql.engine.binding.Binding1;
019: import com.hp.hpl.jena.sparql.engine.binding.BindingMap;
020: import com.hp.hpl.jena.sparql.engine.iterator.QueryIterNullIterator;
021: import com.hp.hpl.jena.sparql.engine.iterator.QueryIterPlainWrapper;
022: import com.hp.hpl.jena.sparql.engine.iterator.QueryIterSingleton;
023: import com.hp.hpl.jena.sparql.pfunction.PFuncSimple;
024: import com.hp.hpl.jena.sparql.util.NodeUtils;
025: import com.hp.hpl.jena.util.iterator.ExtendedIterator;
026:
027: /** Example property function that creates the association between a URI and it's localname.
028: * See also splitIRI which is more general. This is just an example.
029: *
030: * If it is not a URI, then does not match.
031: *
032: * Use as:
033: *
034: * <pre>
035: * ?uri ext:localname ?localname
036: * </pre>
037: *
038: * Depending on whether the subject/object are bound when called:
039: * <ul>
040: * <li>subject bound, object unbound => assign the local name to variable in object slot</li>
041: * <li>subject bound, object bound => check the subject has the local name given by object</li>
042: * <li>subject unbound, object bound => find all URIs in the model (s, p or o) that have that local name</li>
043: * <li>subject unbound, object unbound => generate all localname for all URI resources in the model</li>
044: * </ul>
045: * The two searching forms (subject unbound) are expensive.
046:
047: * Anything not a URI (subject) or string (object) causes no match.
048: *
049: *
050: * @author Andy Seaborne
051: */
052:
053: public class localname extends PFuncSimple {
054:
055: public QueryIterator execEvaluated(Binding binding, Node nodeURI,
056: Node predicate, Node nodeLocalname, ExecutionContext execCxt) {
057: if (!nodeURI.isVariable())
058: return execFixedSubject(nodeURI, nodeLocalname, binding,
059: execCxt);
060: else
061: return execAllNodes(Var.alloc(nodeURI), nodeLocalname,
062: binding, execCxt);
063: }
064:
065: // Subject is bound : still two cases: object bound (do a check) and object unbound (assign the local name)
066: private QueryIterator execFixedSubject(Node nodeURI,
067: Node nodeLocalname, Binding binding,
068: ExecutionContext execCxt) {
069: if (!nodeURI.isURI())
070: // Subject bound but not a URI
071: return new QueryIterNullIterator(execCxt);
072:
073: // Subject is bound and a URI - get the localname as a Node
074: Node localname = Node.createLiteral(nodeURI.getLocalName());
075:
076: // Object - unbound variable or a value?
077: if (!nodeLocalname.isVariable()) {
078: // Object bound or a query constant. Is it the same as the calculated value?
079: if (nodeLocalname.equals(localname))
080: // Same
081: return new QueryIterSingleton(binding, execCxt);
082: // No - different - no match.
083: return new QueryIterNullIterator(execCxt);
084: }
085:
086: // Object unbound variable - assign the localname to it.
087: Binding b = new Binding1(binding, Var.alloc(nodeLocalname),
088: localname);
089:
090: // Return an iterator.
091: return new QueryIterSingleton(b, execCxt);
092: }
093:
094: // Unbound subject - work hard.
095: // Still two cases: object bound (filter by localname) and object unbound (generate all localnames for all URIs)
096: // Warning - will scan the entire graph (there is no localname index) but this example code.
097:
098: private QueryIterator execAllNodes(Var subjVar, Node nodeLocalname,
099: Binding input, ExecutionContext execCxt) {
100: if (!nodeLocalname.isVariable()) {
101: if (!nodeLocalname.isLiteral())
102: // Not a variable, not a literal=> can't match
103: return new QueryIterNullIterator(execCxt);
104:
105: if (!NodeUtils.isStringLiteral(nodeLocalname))
106: // If a typed literal, must be XSD string.
107: return new QueryIterNullIterator(execCxt);
108: }
109:
110: //Set bindings = new HashSet() ; // Use a Set if you want unique results.
111: List bindings = new ArrayList(); // Use a list if you want counting results.
112: Graph graph = execCxt.getActiveGraph();
113:
114: ExtendedIterator iter = graph
115: .find(Node.ANY, Node.ANY, Node.ANY);
116: for (; iter.hasNext();) {
117: Triple t = (Triple) iter.next();
118: slot(bindings, input, t.getSubject(), subjVar,
119: nodeLocalname);
120: slot(bindings, input, t.getPredicate(), subjVar,
121: nodeLocalname);
122: slot(bindings, input, t.getObject(), subjVar, nodeLocalname);
123: }
124: return new QueryIterPlainWrapper(bindings.iterator(), execCxt);
125: }
126:
127: private void slot(Collection bindings, Binding input, Node node,
128: Var subjVar, Node nodeLocalname) {
129: if (!node.isURI())
130: return;
131: Node localname = Node.createLiteral(node.getLocalName());
132: if (nodeLocalname.isVariable()) {
133: // Object is an unbound variable.
134: Binding b = new BindingMap(input);
135: // Bind a pair for subject and object variables
136: b.add(Var.alloc(subjVar), node);
137: b.add(Var.alloc(nodeLocalname), localname);
138: bindings.add(b);
139: return;
140: }
141:
142: // Object is a value / bound variable.
143: if (!nodeLocalname.sameValueAs(localname))
144: return;
145: // Bind subject to this node.
146: Binding b = new Binding1(input, subjVar, node);
147: bindings.add(b);
148: }
149:
150: }
151:
152: /*
153: * (c) Copyright 2006, 2007, 2008 Hewlett-Packard Development Company, LP
154: * All rights reserved.
155: *
156: * Redistribution and use in source and binary forms, with or without
157: * modification, are permitted provided that the following conditions
158: * are met:
159: * 1. Redistributions of source code must retain the above copyright
160: * notice, this list of conditions and the following disclaimer.
161: * 2. Redistributions in binary form must reproduce the above copyright
162: * notice, this list of conditions and the following disclaimer in the
163: * documentation and/or other materials provided with the distribution.
164: * 3. The name of the author may not be used to endorse or promote products
165: * derived from this software without specific prior written permission.
166: *
167: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
168: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
169: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
170: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
171: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
172: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
173: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
174: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
175: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
176: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
177: */
|