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