1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9package com.sleepycat.persist.model; 10 11import com.sleepycat.persist.evolve.Converter; // for javadoc 12import com.sleepycat.persist.raw.RawStore; // for javadoc 13 14/** 15 * Implemented by a proxy class to represent the persistent state of a 16 * (non-persistent) proxied class. Normally classes that are outside the scope 17 * of the developer's control must be proxied since they cannot be annotated, 18 * and because it is desirable to insulate the stored format from changes to 19 * the instance fields of the proxied class. This is useful for classes in the 20 * standard Java libraries, for example. 21 * 22 * <p>{@code PersistentProxy} objects are not required to be thread-safe. A 23 * single thread will create and call the methods of a given {@code 24 * PersistentProxy} object.</p> 25 * 26 * <p>There are three requirements for a proxy class:</p> 27 * <ol> 28 * <li>It must implement the <code>PersistentProxy</code> interface.</li> 29 * <li>It must be specified as a persistent proxy class in the entity model. 30 * When using the {@link AnnotationModel}, a proxy class is indicated by the 31 * {@link Persistent} annotation with the {@link Persistent#proxyFor} 32 * property.</li> 33 * <li>It must be explicitly registered by calling {@link 34 * EntityModel#registerClass} before opening the store.</li> 35 * </ol> 36 * 37 * <p>In order to serialize an instance of the proxied class before it is 38 * stored, an instance of the proxy class is created. The proxied instance is 39 * then passed to the proxy's {@link #initializeProxy initializeProxy} method. 40 * When this method returns, the proxy instance contains the state of the 41 * proxied instance. The proxy instance is then serialized and stored in the 42 * same way as for any persistent object.</p> 43 * 44 * <p>When an instance of the proxy object is deserialized after it is 45 * retrieved from storage, its {@link #convertProxy} method is called. The 46 * instance of the proxied class returned by this method is then returned as a 47 * field in the persistent instance.</p> 48 * 49 * <p>For example:</p> 50 * <pre class="code"> 51 * import java.util.Locale; 52 * 53 * {@literal @Persistent(proxyFor=Locale.class)} 54 * class LocaleProxy implements {@literal PersistentProxy<Locale>} { 55 * 56 * String language; 57 * String country; 58 * String variant; 59 * 60 * private LocaleProxy() {} 61 * 62 * public void initializeProxy(Locale object) { 63 * language = object.getLanguage(); 64 * country = object.getCountry(); 65 * variant = object.getVariant(); 66 * } 67 * 68 * public Locale convertProxy() { 69 * return new Locale(language, country, variant); 70 * } 71 * }</pre> 72 * 73 * <p>The above definition allows the {@code Locale} class to be used in any 74 * persistent class, for example:</p> 75 * <pre class="code"> 76 * {@literal @Persistent} 77 * class LocalizedText { 78 * String text; 79 * Locale locale; 80 * }</pre> 81 * 82 * <p>A proxied class may not be used as a superclass for a persistent class or 83 * entity class. For example, the following is not allowed.</p> 84 * <pre class="code"> 85 * {@literal @Persistent} 86 * class LocalizedText extends Locale { // NOT ALLOWED 87 * String text; 88 * }</pre> 89 * 90 * <p>A proxy for proxied class P does not handle instances of subclasses of P. 91 * To proxy a subclass of P, a separate proxy class is needed.</p> 92 * 93 * <p>Several {@link <a href="Entity.html#proxyTypes">built in proxy types</a>} 94 * are used implicitly. An application defined proxy will be used instead of a 95 * built-in proxy, if both exist for the same proxied class.</p> 96 * 97 * <p>With respect to class evolution, a proxy instance is no different than 98 * any other persistent instance. When using a {@link RawStore} or {@link 99 * Converter}, only the raw data of the proxy instance will be visible. Raw 100 * data for the proxied instance never exists.</p> 101 * 102 * <p>Currently a proxied object may not contain a reference to itself. For 103 * simple proxied objects such as the Locale class shown above, this naturally 104 * won't occur. But for proxied objects that are containers -- the built-in 105 * Collection and Map classes for example -- this can occur if the container is 106 * added as an element of itself. This should be avoided. If an attempt to 107 * store such an object is made, an {@code IllegalArgumentException} will be 108 * thrown.</p> 109 * 110 * <p>Note that a proxy class may not be a subclass of an entity class.</p> 111 * 112 * @author Mark Hayes 113 */ 114public interface PersistentProxy<T> { 115 116 /** 117 * Copies the state of a given proxied class instance to this proxy 118 * instance. 119 */ 120 void initializeProxy(T object); 121 122 /** 123 * Returns a new proxied class instance to which the state of this proxy 124 * instance has been copied. 125 */ 126 T convertProxy(); 127} 128