/** * Copyright 2005-2012 Akiban Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.persistit.ref; import java.lang.ref.WeakReference; /** * <p> * An abstract superclass for implementations of {@link PersistitReference} that * implement weak reference semantics. A concrete subclass implements the * method: <blockquote> * * <pre> * public Object lookup(Object id) * </pre> * * </blockquote> which should return the Object associated with the supplied id, * or <code>null</code> if there is none. The meaning of the identifier, and the * mechanism used to look up and deserialize the associated object (the * referent), are implementation-specific. * </p> * <p> * This implementation differs from {@link AbstractReference} in that the * referent object is referenced through a * <code>java.lang.ref.WeakReference</code>. Thus the garbage collector may * choose to discard the referent value, in which case the <code>get</code> * method will simply look it up again on demand. * </p> * * @version 1.0 */ public abstract class AbstractWeakReference implements PersistitReference { protected Object _id; protected transient WeakReference _weakReference; protected boolean _knownNull; /** * No-arg constructor supplied for object serialization/deserialization. * */ protected AbstractWeakReference() { } /** * Construct a reference to the referent Object with the supplied persistent * identifier. For correct operation, the referent Object must be equivalent * to the object that would result from invoking <code>lookup</code> on the * persistent identifier. the object that would be returned by the lookup * * @param id * The persistent identifier. The value of the id must be * associated with a unique referent object, and must be stable * over time. * @param referent * The object identified by the id */ protected AbstractWeakReference(final Object id, final Object referent) { _id = id; if (referent == null) _knownNull = true; else _weakReference = new WeakReference(referent); } /** * Construct a reference using the persistent identity of an object. A * subsequent invocation of the <code>get</code> method will cause the * object to be looked up and instantiated. * * @param id */ protected AbstractWeakReference(final Object id) { _id = id; _weakReference = null; _knownNull = false; } /** * Gets the referent object. If the object has already been looked up, or if * this reference was created using the two-argument constructor, then this * merely returns the object. Otherwise this method attempts to look up and * instantiate the object using its persistent identifier. * * @return The referent object. */ @Override public Object get() { if (_id == null) { throw new IllegalStateException("identifier not initialized"); } if (_knownNull) return null; Object referent = null; if (_weakReference != null) referent = _weakReference.get(); if (referent == null) { referent = lookup(_id); if (referent == null) _knownNull = true; else _weakReference = new WeakReference(referent); } return _weakReference; } /** * Look up and instantiate an object using its persistent identifier. * Typically this will be done by setting up a * {@link com.persistit.Exchange} and fetching its value. * * @param id * The identifier * @return The referent object. */ protected abstract Object lookup(Object id); }