1 /** 2 * Redistribution and use of this software and associated documentation ("Software"), with or 3 * without modification, are permitted provided that the following conditions are met: 4 * 5 * 1. Redistributions of source code must retain copyright statements and notices. Redistributions 6 * must also contain a copy of this document. 7 * 8 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of 9 * conditions and the following disclaimer in the documentation and/or other materials provided with 10 * the distribution. 11 * 12 * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software 13 * without prior written permission of Intalio, Inc. For written permission, please contact 14 * info@exolab.org. 15 * 16 * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in 17 * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of 18 * Intalio, Inc. 19 * 20 * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/). 21 * 22 * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 24 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY 29 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Copyright 1999 (C) Intalio, Inc. All Rights Reserved. 32 * 33 * $Id$ 34 */ 35 36 package org.exolab.castor.xml.schema; 37 38 /** 39 * Implements a reference to an object that will be resolved at a later time using some resolver 40 * mechanism. A resolvable reference can be created in both resolved and unresolved states. 41 * Resolvable references are immutable by definition. 42 * <p> 43 * A resolverable reference has two states: resolved and unresolved. When in the resolved state, the 44 * reference will always return the same resolved object. When in the unresolved state, the first 45 * time the object is requested, it will be resolved and returned. At that point the reference 46 * becomes resolved and the same object is returned in subsequent requests. 47 * <p> 48 * The following example creates a resolved and unresolved objects and then resolved the two: 49 * 50 * <pre> 51 * ResolvableReference resolved, unresolved; 52 * 53 * resolved = new ResolvableReference(myObject); 54 * unresolved = new ResolvableReference("id", resolver); 55 * if (resolved.get() == myObject) 56 * ; // This will always be true 57 * if (unresolved.get() == resolver.resolve("id")) 58 * ; // This will always be true 59 * </pre> 60 * <p> 61 * 62 * @author <a href="mailto:arkin@intalio.com">Assaf Arkin</a> 63 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a> 64 * @see Resolver 65 * @version $Revision$ $Date: 2003-03-03 00:05:44 -0700 (Mon, 03 Mar 2003) $ 66 **/ 67 public final class ResolvableReference { 68 69 /** 70 * Determines whether or not the reference can be resolved at the time this method is called. A 71 * call to this method does not guarantee a null value will not be returned by a call to the get() 72 * method. 73 **/ 74 public boolean resolvable() { 75 // -- if resolver is null, the referent must be known, or 76 // -- never will be known, so return true 77 if (_resolver == null) 78 return true; 79 // -- otherwise check resolver to see if it can resolve the id 80 return (_resolver.resolve(_id) != null); 81 } // -- resolvable 82 83 /** 84 * Called to resolve the object and return it. The returned object must be cast to the proper 85 * class. If a referent was specified in the constructor, that referent will be returned. If an 86 * identifier was specified, the resolved will be called to resolve the object. The resolver will 87 * be called only the first time this method is called. Subsequent calls will return the same 88 * object. 89 * <p> 90 * Null is returned if the object was resolved to null. 91 * 92 * @return The resolved object 93 */ 94 public Referable get() { 95 // If resolver is null, the referent is known. 96 if (_resolver == null) 97 return _referent; 98 99 // Must synchronize, resolving should only occur once. 100 // If two get methods get to this point at once, the 101 // first one will resolve, the second one will not. 102 synchronized (this) { 103 if (_resolver != null) { 104 _referent = _resolver.resolve(_id); 105 _resolver = null; 106 } 107 return _referent; 108 } 109 } 110 111 /** 112 * Constructs a resolvable reference for the named object. This reference will be resolved on 113 * demand by calling the resolver with the specified identifier. The object need not be resolvable 114 * until the {@link #get} method is called. 115 * 116 * @param id The object's identifier 117 * @param resolver The resolve to use 118 */ 119 public ResolvableReference(String id, Resolver resolver) { 120 _id = id; 121 _resolver = resolver; 122 } 123 124 125 /** 126 * Constructs a resolvable reference for the given object. This reference will always resolve to 127 * the specified referent. 128 * 129 * @param referent The object to resolve to 130 */ 131 public ResolvableReference(Referable referent) { 132 _referent = referent; 133 } 134 135 136 /** 137 * The resolver used to resolve the object. This variable will only be held while the reference is 138 * unresolved. Once the reference has been resolved, this variable will be set to null. Unused 139 * resolvers will be garbage collected. 140 */ 141 private Resolver _resolver; 142 143 144 /** 145 * References the resolved object if passed from the constructor or has been resolved by a call to 146 * {@link #get}. Once an object has been resolved, the same object will always be returned. 147 */ 148 private Referable _referent; 149 150 151 /** 152 * The identifier to use for resolving the reference. 153 */ 154 private String _id; 155 156 } 157