001: /*
002: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: [See end of file]
004: $Id: Polymorphic.java,v 1.12 2008/01/02 12:09:11 andy_seaborne Exp $
005: */
006:
007: package com.hp.hpl.jena.enhanced;
008:
009: /**
010: * Abstract base class for all polymorphic RDF objects, especially enhanced node and enhanced graph.
011: *
012: * @author <a href="mailto:Jeremy.Carroll@hp.com">Jeremy Carroll</a> (original code)<br>
013: * <a href="mailto:Chris.Dollin@hp.com">Chris Dollin</a> (original code)<br>
014: * <a href="mailto:Ian.Dickinson@hp.com">Ian Dickinson</a> (tidying up and comments)
015: */
016: public abstract class Polymorphic {
017:
018: /** Each new polymorphic object is in a ring of views */
019: private Polymorphic ring;
020:
021: /**
022: initially we're in the singleton ring.
023: */
024: Polymorphic() {
025: this .ring = this ;
026: }
027:
028: // External contract methods
029:
030: /**
031: * Answer the personality object bound to this polymorphic instance
032: * @return The personality object
033: */
034: protected abstract Personality getPersonality();
035:
036: /**
037: * Answer true iff <i>this</i> is already acceptable to the given type t.
038: * Delegates to t to test if this class is an acceptable implementation.
039: * @param t A type to test
040: * @return True iff this object is already an acceptable implementation of t
041: */
042: protected boolean already(Class t) {
043: return t.isInstance(this );
044: }
045:
046: /**
047: return _true_ iff this polymorphic object supports the specified interface.
048: Synonymous with "does the argument class have this as an instance".
049: Actually it shouldn't be. Review.
050: */
051: public boolean supports(Class t) {
052: Polymorphic supporter = findExistingView(t);
053: return supporter != null || this .canSupport(t);
054: }
055:
056: /**
057: * Answer a polymorphic object that presents <i>this</i> in a way which satisfies type
058: * t.
059: * @param t A type
060: * @return A polymorphic instance, possibly but not necessarily this, that conforms to t.
061: */
062: protected final Polymorphic asInternal(Class t) {
063: Polymorphic other = findExistingView(t);
064: return other == null ? this .convertTo(t) : other;
065: }
066:
067: /**
068: find an existing view in the ring which is an instance of _t_ and
069: return it; otherwise return null. If _this_ is an instance, the
070: search takes care to find it first.
071: */
072: private Polymorphic findExistingView(Class t) {
073: Polymorphic r = this ;
074: for (;;) {
075: if (t.isInstance(r) && r.isValid())
076: return r;
077: r = r.ring;
078: if (r == this )
079: return null;
080: }
081: }
082:
083: /**
084: Answer true iff this polymorphic object already has a valid view of
085: type <code>t</code> in its ring (so .as()ing it doesn't need to
086: construct a new object).
087: */
088: protected boolean alreadyHasView(Class t) {
089: return findExistingView(t) != null;
090: }
091:
092: /**
093: answer true iff this enhanced node is still underpinned in the graph
094: by triples appropriate to its type.
095: */
096: public abstract boolean isValid();
097:
098: /**
099: subclasses must provide a method for converting _this_, if
100: possible, into an instance of _t_. It will only be called if _this_
101: doesn't already have (or be) a suitable ring-sibling.
102: */
103: protected abstract Polymorphic convertTo(Class t);
104:
105: /**
106: subclasses must provide a method for testing if _this_ can be
107: converted to an instance of _t_.
108: */
109: protected abstract boolean canSupport(Class t);
110:
111: /**
112: subclasses must override equals. Actually they may not have
113: to nowadays ... I have expunged the clever facet-identity test
114: (and indeed facets).
115: */
116: public abstract boolean equals(Object o);
117:
118: /**
119: add another view for this object. <code>other</code> must be freshly
120: constructed. To be called by subclasses when they have constructed a
121: new view for this object.
122:
123: <p>The method is synchronised because addView is an update operation
124: that may happen in a read context (because of .as()). Synchronising
125: it ensures that simultaneous updates don't end up leaving the rings
126: in an inconsistent state. (It's not clear whether this would actually
127: lead to any problems; it's hard to write tests to expose these issues.)
128:
129: This method is public ONLY so that it can be tested.
130: TODO find a better way to make it testable.
131: */
132: public synchronized void addView(Polymorphic other) {
133: if (other.ring == other) {
134: other.ring = this .ring;
135: this .ring = other;
136: } else
137: throw new AlreadyLinkedViewException(other);
138: }
139:
140: }
141:
142: /*
143: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
144: All rights reserved.
145:
146: Redistribution and use in source and binary forms, with or without
147: modification, are permitted provided that the following conditions
148: are met:
149:
150: 1. Redistributions of source code must retain the above copyright
151: notice, this list of conditions and the following disclaimer.
152:
153: 2. Redistributions in binary form must reproduce the above copyright
154: notice, this list of conditions and the following disclaimer in the
155: documentation and/or other materials provided with the distribution.
156:
157: 3. The name of the author may not be used to endorse or promote products
158: derived from this software without specific prior written permission.
159:
160: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
161: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
162: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
163: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
164: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
165: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
166: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
167: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
168: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
169: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
170: */
|