001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: PersistentProxy.java,v 1.12.2.3 2008/01/07 15:14:20 cwl Exp $
007: */
008:
009: package com.sleepycat.persist.model;
010:
011: import com.sleepycat.persist.evolve.Converter; // for javadoc
012: import com.sleepycat.persist.raw.RawStore; // for javadoc
013:
014: /**
015: * Implemented by a proxy class to represent the persistent state of a
016: * (non-persistent) proxied class. Normally classes that are outside the scope
017: * of the developer's control must be proxied since they cannot be annotated,
018: * and because it is desirable to insulate the stored format from changes to
019: * the instance fields of the proxied class. This is useful for classes in the
020: * standard Java libraries, for example.
021: *
022: * <p>{@code PersistentProxy} objects are not required to be thread-safe. A
023: * single thread will create and call the methods of a given {@code
024: * PersistentProxy} object.</p>
025: *
026: * <p>There are three requirements for a proxy class:</p>
027: * <ol>
028: * <li>It must implement the <code>PersistentProxy</code> interface.</li>
029: * <li>It must be specified as a persistent proxy class in the entity model.
030: * When using the {@link AnnotationModel}, a proxy class is indicated by the
031: * {@link Persistent} annotation with the {@link Persistent#proxyFor}
032: * property.</li>
033: * <li>It must be explicitly registered by calling {@link
034: * EntityModel#registerClass} before opening the store.</li>
035: * </ol>
036: *
037: * <p>In order to serialize an instance of the proxied class before it is
038: * stored, an instance of the proxy class is created. The proxied instance is
039: * then passed to the proxy's {@link #initializeProxy initializeProxy} method.
040: * When this method returns, the proxy instance contains the state of the
041: * proxied instance. The proxy instance is then serialized and stored in the
042: * same way as for any persistent object.</p>
043: *
044: * <p>When an instance of the proxy object is deserialized after it is
045: * retrieved from storage, its {@link #convertProxy} method is called. The
046: * instance of the proxied class returned by this method is then returned as a
047: * field in the persistent instance.</p>
048: *
049: * <p>For example:</p>
050: * <pre class="code">
051: * import java.util.Locale;
052: *
053: * {@literal @Persistent(proxyFor=Locale.class)}
054: * class LocaleProxy implements {@literal PersistentProxy<Locale>} {
055: *
056: * String language;
057: * String country;
058: * String variant;
059: *
060: * private LocaleProxy() {}
061: *
062: * public void initializeProxy(Locale object) {
063: * language = object.getLanguage();
064: * country = object.getCountry();
065: * variant = object.getVariant();
066: * }
067: *
068: * public Locale convertProxy() {
069: * return new Locale(language, country, variant);
070: * }
071: * }</pre>
072: *
073: * <p>The above definition allows the {@code Locale} class to be used in any
074: * persistent class, for example:</p>
075: * <pre class="code">
076: * {@literal @Persistent}
077: * class LocalizedText {
078: * String text;
079: * Locale locale;
080: * }</pre>
081: *
082: * <p>A proxy for proxied class P does not handle instances of subclasses of P.
083: * To proxy subclasses of P, a separate proxy class is needed.</p>
084: *
085: * <p>Several {@link <a href="Entity.html#proxyTypes">built in proxy types</a>}
086: * are used implicitly. An application defined proxy will be used instead of a
087: * built-in proxy, if both exist for the same proxied class.</p>
088: *
089: * <p>With respect to class evolution, a proxy instance is no different than
090: * any other persistent instance. When using a {@link RawStore} or {@link
091: * Converter}, only the raw data of the proxy instance will be visible. Raw
092: * data for the proxied instance never exists.</p>
093: *
094: * <p>Currently a proxied object may not contain a reference to itself. For
095: * simple proxied objects such as the Locale class shown above, this naturally
096: * won't occur. But for proxied objects that are containers -- the built-in
097: * Collection and Map classes for example -- this can occur if the container is
098: * added as an element of itself. This should be avoided. If an attempt to
099: * store such an object is made, an {@code IllegalArgumentException} will be
100: * thrown.</p>
101: *
102: * @author Mark Hayes
103: */
104: public interface PersistentProxy<T> {
105:
106: /**
107: * Copies the state of a given proxied class instance to this proxy
108: * instance.
109: */
110: void initializeProxy(T object);
111:
112: /**
113: * Returns a new proxied class instance to which the state of this proxy
114: * instance has been copied.
115: */
116: T convertProxy();
117: }
|