001: /*
002: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: [See end of file]
004: $Id: SimpleReifier.java,v 1.55 2008/02/11 09:32:33 chris-dollin Exp $
005: */
006:
007: package com.hp.hpl.jena.graph.impl;
008:
009: /**
010: @author kers
011: <p>
012: A base-level implementation of Reifier, intended to be straightforward
013: and obvious. It fails this test nowadays ...
014: */
015:
016: import com.hp.hpl.jena.graph.*;
017: import com.hp.hpl.jena.shared.*;
018: import com.hp.hpl.jena.util.iterator.*;
019:
020: import com.hp.hpl.jena.vocabulary.RDF;
021:
022: public class SimpleReifier implements Reifier {
023: protected final GraphBase parent;
024: protected final boolean intercepting;
025: protected final boolean concealing;
026: protected final ReificationStyle style;
027:
028: protected ReifierFragmentsMap fragmentsMap;
029: protected ReifierTripleMap tripleMap;
030:
031: protected boolean closed = false;
032:
033: /**
034: construct a simple reifier that is bound to the parent graph .
035:
036: @param parent the Graph which we're reifiying for
037: @param style the reification style to use
038: */
039: public SimpleReifier(GraphBase parent, ReificationStyle style) {
040: this (parent, new SimpleReifierTripleMap(),
041: new SimpleReifierFragmentsMap(), style);
042: }
043:
044: public SimpleReifier(GraphBase parent, ReifierTripleMap tm,
045: ReifierFragmentsMap fm, ReificationStyle style) {
046: this .parent = parent;
047: this .fragmentsMap = fm;
048: this .tripleMap = tm;
049: this .intercepting = style.intercepts();
050: this .concealing = style.conceals();
051: this .style = style;
052: }
053:
054: public ReificationStyle getStyle() {
055: return style;
056: }
057:
058: /** return the parent graph we are bound to */
059: public Graph getParentGraph() {
060: return parent;
061: }
062:
063: /** return the triple bound to _n_ */
064: public Triple getTriple(Node n) {
065: return tripleMap.getTriple(n);
066: }
067:
068: /** true iff there is a triple bound to _n_ */
069: public boolean hasTriple(Node n) {
070: return getTriple(n) != null;
071: }
072:
073: /** */
074: public ExtendedIterator allNodes() {
075: return tripleMap.tagIterator();
076: }
077:
078: public ExtendedIterator allNodes(Triple t) {
079: return tripleMap.tagIterator(t);
080: }
081:
082: public void clear() {
083: fragmentsMap.clear();
084: tripleMap.clear();
085: }
086:
087: /**
088: reifiy <code>toReify</code> with tag <code>tag</code>. If a different triple is
089: already reified under <code>tag</code>, throw an AlreadyReifiedException.
090: */
091: public Node reifyAs(Node tag, Triple toReify) {
092: Triple existing = (Triple) tripleMap.getTriple(tag);
093: if (existing != null) {
094: if (!toReify.equals(existing))
095: throw new AlreadyReifiedException(tag);
096: } else
097: reifyNewTriple(tag, toReify);
098: if (concealing == false)
099: graphAddQuad(parent, tag, toReify);
100: return tag;
101: }
102:
103: /**
104: Reify <code>toReify</code> under <code>tag</code>; there is no existing
105: complete reification. This code goes around the houses by adding the
106: fragments one-by-one and then seeing if that made a complete reification.
107: Perhaps there's a better way, but I couldn't see it.
108: */
109: protected void reifyNewTriple(Node tag, Triple toReify) {
110: if (fragmentsMap.hasFragments(tag)) {
111: graphAddQuad(parent, tag, toReify);
112: if (tripleMap.getTriple(tag) == null)
113: throw new CannotReifyException(tag);
114: } else
115: tripleMap.putTriple(tag, toReify);
116: }
117:
118: /**
119: If n is bound to the triple t, remove that triple. If we're not concealing reification
120: quadlets, we need to remove them from the parent graph too.
121: */
122: public void remove(Node n, Triple t) {
123: Triple x = (Triple) tripleMap.getTriple(n);
124: if (t.equals(x)) {
125: tripleMap.removeTriple(n, t);
126: if (!concealing)
127: parentRemoveQuad(n, t);
128: }
129: }
130:
131: public void remove(Triple t) {
132: tripleMap.removeTriple(t);
133: }
134:
135: public boolean hasTriple(Triple t) {
136: return tripleMap.hasTriple(t);
137: }
138:
139: public boolean handledAdd(Triple fragment) {
140: if (intercepting) {
141: ReifierFragmentHandler s = fragmentsMap
142: .getFragmentHandler(fragment);
143: if (s == null)
144: return false;
145: else {
146: addFragment(s, fragment);
147: return true;
148: }
149: } else
150: return false;
151: }
152:
153: /**
154: Add <code>fragment</code> to the fragments already present. This may
155: create a complete triple, or over-specify.
156: * @param s
157: * @param fragment
158: */
159: protected void addFragment(ReifierFragmentHandler s, Triple fragment) {
160: Node tag = fragment.getSubject(), object = fragment.getObject();
161: Triple reified = tripleMap.getTriple(tag);
162: if (reified == null)
163: updateFragments(s, fragment, tag, object);
164: else if (s.clashedWith(tag, object, reified))
165: tripleMap.removeTriple(tag, reified);
166: }
167:
168: /**
169: * @param s
170: * @param fragment
171: * @param tag
172: * @param object
173: */
174: private void updateFragments(ReifierFragmentHandler s,
175: Triple fragment, Node tag, Node object) {
176: Triple t = s.reifyIfCompleteQuad(fragment, tag, object);
177: if (t instanceof Triple)
178: tripleMap.putTriple(tag, t);
179: }
180:
181: public boolean handledRemove(Triple fragment) {
182: if (intercepting) {
183: ReifierFragmentHandler s = fragmentsMap
184: .getFragmentHandler(fragment);
185: if (s == null)
186: return false;
187: else {
188: removeFragment(s, fragment);
189: return true;
190: }
191: } else
192: return false;
193: }
194:
195: /**
196: * @param s
197: * @param fragment
198: */
199: private void removeFragment(ReifierFragmentHandler s,
200: Triple fragment) {
201: Node tag = fragment.getSubject();
202: Triple already = tripleMap.getTriple(tag);
203: Triple complete = s.removeFragment(tag, already, fragment);
204: if (complete == null)
205: tripleMap.removeTriple(tag);
206: else
207: tripleMap.putTriple(tag, complete);
208: }
209:
210: public ExtendedIterator find(TripleMatch m) {
211: return matchesReification(m) ? tripleMap.find(m).andThen(
212: fragmentsMap.find(m)) : NullIterator.instance;
213: }
214:
215: /**
216: Answer true iff <code>m</code> might match a reification triple.
217: */
218: private boolean matchesReification(TripleMatch m) {
219: Node predicate = m.asTriple().getPredicate();
220: return !predicate.isConcrete()
221: || predicate.equals(RDF.Nodes.subject)
222: || predicate.equals(RDF.Nodes.predicate)
223: || predicate.equals(RDF.Nodes.object)
224: || predicate.equals(RDF.Nodes.type)
225: && matchesStatement(m.asTriple().getObject());
226: }
227:
228: private boolean matchesStatement(Node x) {
229: return !x.isConcrete() || x.equals(RDF.Nodes.Statement);
230: }
231:
232: public ExtendedIterator findExposed(TripleMatch m) {
233: return findEither(m, false);
234: }
235:
236: public ExtendedIterator findEither(TripleMatch m, boolean showHidden) {
237: return showHidden == concealing ? find(m)
238: : NullIterator.instance;
239: }
240:
241: public int size() {
242: return concealing ? 0 : tripleMap.size() + fragmentsMap.size();
243: }
244:
245: /**
246: remove from the parent all of the triples that correspond to a reification
247: of t on tag.
248: */
249: private void parentRemoveQuad(Node n, Triple t) {
250: parent.delete(Triple.create(n, RDF.Nodes.type,
251: RDF.Nodes.Statement));
252: parent.delete(Triple.create(n, RDF.Nodes.subject, t
253: .getSubject()));
254: parent.delete(Triple.create(n, RDF.Nodes.predicate, t
255: .getPredicate()));
256: parent
257: .delete(Triple.create(n, RDF.Nodes.object, t
258: .getObject()));
259: }
260:
261: public static void graphAddQuad(GraphAdd g, Node node, Triple t) {
262: g.add(Triple.create(node, RDF.Nodes.subject, t.getSubject()));
263: g.add(Triple
264: .create(node, RDF.Nodes.predicate, t.getPredicate()));
265: g.add(Triple.create(node, RDF.Nodes.object, t.getObject()));
266: g.add(Triple.create(node, RDF.Nodes.type, RDF.Nodes.Statement));
267: }
268:
269: /**
270: our string representation is <R ...> wrapped round the string representation
271: of our node map.
272: */
273: public String toString() {
274: return "<R " + fragmentsMap + "|" + tripleMap + ">";
275: }
276:
277: /**
278: Close this reifier - discard (big) resources.
279: */
280: public void close() {
281: fragmentsMap = null;
282: tripleMap = null;
283: closed = true;
284: }
285:
286: /**
287: Answer true iff this SImpleReifier has been closed.
288: */
289: public boolean isClosed() {
290: return closed;
291: }
292: }
293:
294: /*
295: (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
296: All rights reserved.
297:
298: Redistribution and use in source and binary forms, with or without
299: modification, are permitted provided that the following conditions
300: are met:
301:
302: 1. Redistributions of source code must retain the above copyright
303: notice, this list of conditions and the following disclaimer.
304:
305: 2. Redistributions in binary form must reproduce the above copyright
306: notice, this list of conditions and the following disclaimer in the
307: documentation and/or other materials provided with the distribution.
308:
309: 3. The name of the author may not be used to endorse or promote products
310: derived from this software without specific prior written permission.
311:
312: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
313: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
314: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
315: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
316: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
317: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
318: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
319: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
320: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
321: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322: */
|