com.sleepycat.persist.model.PersistentProxy Maven / Gradle / Ivy
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.persist.model;
import com.sleepycat.persist.evolve.Converter; // for javadoc
import com.sleepycat.persist.raw.RawStore; // for javadoc
/**
* Implemented by a proxy class to represent the persistent state of a
* (non-persistent) proxied class. Normally classes that are outside the scope
* of the developer's control must be proxied since they cannot be annotated,
* and because it is desirable to insulate the stored format from changes to
* the instance fields of the proxied class. This is useful for classes in the
* standard Java libraries, for example.
*
* {@code PersistentProxy} objects are not required to be thread-safe. A
* single thread will create and call the methods of a given {@code
* PersistentProxy} object.
*
* There are three requirements for a proxy class:
*
* - It must implement the
PersistentProxy
interface.
* - It must be specified as a persistent proxy class in the entity model.
* When using the {@link AnnotationModel}, a proxy class is indicated by the
* {@link Persistent} annotation with the {@link Persistent#proxyFor}
* property.
* - It must be explicitly registered by calling {@link
* EntityModel#registerClass} before opening the store.
*
*
* In order to serialize an instance of the proxied class before it is
* stored, an instance of the proxy class is created. The proxied instance is
* then passed to the proxy's {@link #initializeProxy initializeProxy} method.
* When this method returns, the proxy instance contains the state of the
* proxied instance. The proxy instance is then serialized and stored in the
* same way as for any persistent object.
*
* When an instance of the proxy object is deserialized after it is
* retrieved from storage, its {@link #convertProxy} method is called. The
* instance of the proxied class returned by this method is then returned as a
* field in the persistent instance.
*
* For example:
*
* import java.util.Locale;
*
* {@literal @Persistent(proxyFor=Locale.class)}
* class LocaleProxy implements {@literal PersistentProxy} {
*
* String language;
* String country;
* String variant;
*
* private LocaleProxy() {}
*
* public void initializeProxy(Locale object) {
* language = object.getLanguage();
* country = object.getCountry();
* variant = object.getVariant();
* }
*
* public Locale convertProxy() {
* return new Locale(language, country, variant);
* }
* }
*
* The above definition allows the {@code Locale} class to be used in any
* persistent class, for example:
*
* {@literal @Persistent}
* class LocalizedText {
* String text;
* Locale locale;
* }
*
* A proxied class may not be used as a superclass for a persistent class or
* entity class. For example, the following is not allowed.
*
* {@literal @Persistent}
* class LocalizedText extends Locale { // NOT ALLOWED
* String text;
* }
*
* A proxy for proxied class P does not handle instances of subclasses of P.
* To proxy a subclass of P, a separate proxy class is needed.
*
* Several built in proxy types
* are used implicitly. An application defined proxy will be used instead of a
* built-in proxy, if both exist for the same proxied class.
*
* With respect to class evolution, a proxy instance is no different than
* any other persistent instance. When using a {@link RawStore} or {@link
* Converter}, only the raw data of the proxy instance will be visible. Raw
* data for the proxied instance never exists.
*
* Currently a proxied object may not contain a reference to itself. For
* simple proxied objects such as the Locale class shown above, this naturally
* won't occur. But for proxied objects that are containers -- the built-in
* Collection and Map classes for example -- this can occur if the container is
* added as an element of itself. This should be avoided. If an attempt to
* store such an object is made, an {@code IllegalArgumentException} will be
* thrown.
*
* Note that a proxy class may not be a subclass of an entity class.
*
* @author Mark Hayes
*/
public interface PersistentProxy {
/**
* Copies the state of a given proxied class instance to this proxy
* instance.
*
* @param object the proxied class instance.
*/
void initializeProxy(T object);
/**
* Returns a new proxied class instance to which the state of this proxy
* instance has been copied.
*
* @return the new proxied class instance.
*/
T convertProxy();
}