• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/db-4.8.30/java/src/com/sleepycat/persist/model/
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 java.util.ArrayList;
12import java.util.Collections;
13import java.util.List;
14import java.util.Set;
15
16import com.sleepycat.persist.EntityStore;
17import com.sleepycat.persist.PrimaryIndex;
18import com.sleepycat.persist.SecondaryIndex;
19import com.sleepycat.persist.impl.Format;
20import com.sleepycat.persist.impl.PersistCatalog;
21import com.sleepycat.persist.raw.RawObject;
22import com.sleepycat.persist.raw.RawType;
23
24/**
25 * The base class for classes that provide entity model metadata.  An {@link
26 * EntityModel} defines entity classes, primary keys, secondary keys, and
27 * relationships between entities.  For each entity class that is part of the
28 * model, a single {@link PrimaryIndex} object and zero or more {@link
29 * SecondaryIndex} objects may be accessed via an {@link EntityStore}.
30 *
31 * <p>The built-in entity model, the {@link AnnotationModel}, is based on
32 * annotations that are added to entity classes and their key fields.
33 * Annotations are used in the examples in this package, and it is expected
34 * that annotations will normally be used; most readers should therefore skip
35 * to the {@link AnnotationModel} class.  However, a custom entity model class
36 * may define its own metadata.  This can be used to define entity classes and
37 * keys using mechanisms other than annotations.</p>
38 *
39 * <p>A concrete entity model class should extend this class and implement the
40 * {@link #getClassMetadata}, {@link #getEntityMetadata} and {@link
41 * #getKnownClasses} methods.</p>
42 *
43 * <p>This is an abstract class rather than an interface to allow adding
44 * capabilities to the model at a future date without causing
45 * incompatibilities.  For example, a method may be added in the future for
46 * returning new information about the model and subclasses may override this
47 * method to return the new information.  Any new methods will have default
48 * implementations that return default values, and the use of the new
49 * information will be optional.</p>
50 *
51 * @author Mark Hayes
52 */
53public abstract class EntityModel {
54
55    private PersistCatalog catalog;
56
57    /**
58     * The default constructor for use by subclasses.
59     */
60    protected EntityModel() {
61    }
62
63    /**
64     * Returns whether the model is associated with an open store.
65     *
66     * <p>The {@link #registerClass} method may only be called when the model
67     * is not yet open.  Certain other methods may only be called when the
68     * model is open:</p>
69     * <ul>
70     * <li>{@link #convertRawObject}</li>
71     * <li>{@link #getAllRawTypeVersions}</li>
72     * <li>{@link #getRawType}</li>
73     * <li>{@link #getRawTypeVersion}</li>
74     * </ul>
75     */
76    public final boolean isOpen() {
77        return catalog != null;
78    }
79
80    /**
81     * Registers a persistent class, most importantly, a {@link
82     * PersistentProxy} class or entity subclass.
83     *
84     * <p>Any persistent class may be registered in advance of using it, to
85     * avoid the overhead of updating the catalog database when an instance of
86     * the class is first stored.  This method <em>must</em> be called in two
87     * cases:</p>
88     * <ol>
89     * <li>to register all {@link PersistentProxy} classes, and</li>
90     * <li>to register an entity subclass defining a secondary key, if {@link
91     * EntityStore#getSubclassIndex getSubclassIndex} is not called for the
92     * subclass.</li>
93     * </ol>
94     *
95     * <p>For example:</p>
96     *
97     * <pre class="code">
98     * EntityModel model = new AnnotationModel();
99     * model.registerClass(MyProxy.class);
100     * model.registerClass(MyEntitySubclass.class);
101     *
102     * StoreConfig config = new StoreConfig();
103     * ...
104     * config.setModel(model);
105     *
106     * EntityStore store = new EntityStore(..., config);</pre>
107     *
108     * <p>This method must be called before opening a store based on this
109     * model.</p>
110     *
111     * @throws IllegalStateException if this method is called for a model that
112     * is associated with an open store.
113     *
114     * @throws IllegalArgumentException if the given class is not persistent
115     * or has a different class loader than previously registered classes.
116     */
117    public final void registerClass(Class persistentClass) {
118        if (catalog != null) {
119            throw new IllegalStateException("Store is already open");
120        } else {
121            String className = persistentClass.getName();
122            ClassMetadata meta = getClassMetadata(className);
123            if (meta == null) {
124                throw new IllegalArgumentException
125                    ("Class is not persistent: " + className);
126            }
127        }
128    }
129
130    /**
131     * Gives this model access to the catalog, which is used for returning
132     * raw type information.
133     */
134    void setCatalog(PersistCatalog catalog) {
135        this.catalog = catalog;
136    }
137
138    /**
139     * Returns the metadata for a given persistent class name, including proxy
140     * classes and entity classes.
141     *
142     * @return the metadata or null if the class is not persistent or does not
143     * exist.
144     */
145    public abstract ClassMetadata getClassMetadata(String className);
146
147    /**
148     * Returns the metadata for a given entity class name.
149     *
150     * @return the metadata or null if the class is not an entity class or does
151     * not exist.
152     */
153    public abstract EntityMetadata getEntityMetadata(String className);
154
155    /**
156     * Returns the names of all known persistent classes.  A type becomes known
157     * when an instance of the type is stored for the first time or metadata or
158     * type information is queried for a specific class name.
159     *
160     * @return an unmodifiable set of class names.
161     *
162     * @throws IllegalStateException if this method is called for a model that
163     * is not associated with an open store.
164     */
165    public abstract Set<String> getKnownClasses();
166
167    /**
168     * Returns the type information for the current version of a given class,
169     * or null if the class is not currently persistent.
170     *
171     * @param className the name of the current version of the class.
172     *
173     * @throws IllegalStateException if this method is called for a model that
174     * is not associated with an open store.
175     */
176    public final RawType getRawType(String className) {
177        if (catalog != null) {
178            return catalog.getFormat(className);
179        } else {
180            throw new IllegalStateException("Store is not open");
181        }
182    }
183
184    /**
185     * Returns the type information for a given version of a given class,
186     * or null if the given version of the class is unknown.
187     *
188     * @param className the name of the latest version of the class.
189     *
190     * @param version the desired version of the class.
191     *
192     * @throws IllegalStateException if this method is called for a model that
193     * is not associated with an open store.
194     */
195    public final RawType getRawTypeVersion(String className, int version) {
196        if (catalog != null) {
197            Format format = catalog.getLatestVersion(className);
198            while (format != null) {
199                if (version == format.getVersion()) {
200                    return format;
201                }
202            }
203            return null;
204        } else {
205            throw new IllegalStateException("Store is not open");
206        }
207    }
208
209    /**
210     * Returns all known versions of type information for a given class name,
211     * or null if no persistent version of the class is known.
212     *
213     * @param className the name of the latest version of the class.
214     *
215     * @return an unmodifiable list of types for the given class name in order
216     * from most recent to least recent.
217     *
218     * @throws IllegalStateException if this method is called for a model that
219     * is not associated with an open store.
220     */
221    public final List<RawType> getAllRawTypeVersions(String className) {
222        if (catalog != null) {
223            Format format = catalog.getLatestVersion(className);
224            if (format != null) {
225                List<RawType> list = new ArrayList<RawType>();
226                while (format != null) {
227                    list.add(format);
228                    format = format.getPreviousVersion();
229                }
230                return Collections.unmodifiableList(list);
231            } else {
232                return null;
233            }
234        } else {
235            throw new IllegalStateException("Store is not open");
236        }
237    }
238
239    /**
240     * Returns all versions of all known types.
241     *
242     * @return an unmodifiable list of types.
243     *
244     * @throws IllegalStateException if this method is called for a model that
245     * is not associated with an open store.
246     */
247    public final List<RawType> getAllRawTypes() {
248        if (catalog != null) {
249            return catalog.getAllRawTypes();
250        } else {
251            throw new IllegalStateException("Store is not open");
252        }
253    }
254
255    /**
256     * Converts a given raw object to a live object according to the current
257     * class definitions.
258     *
259     * <p>The given raw object must conform to the current class definitions.
260     * However, the raw type ({@link RawObject#getType}) is allowed to be from
261     * a different store, as long as the class names and the value types match.
262     * This allows converting raw objects that are read from one store to live
263     * objects in another store, for example, in a conversion program.</p>
264     */
265    public final Object convertRawObject(RawObject raw) {
266        return catalog.convertRawObject(raw, null);
267    }
268
269    /**
270     * Calls Class.forName with the current thread context class loader.  This
271     * method should be called by entity model implementations instead of
272     * calling Class.forName whenever loading an application class.
273     */
274    public static Class classForName(String className)
275        throws ClassNotFoundException {
276
277        try {
278            return Class.forName(className, true /*initialize*/,
279                             Thread.currentThread().getContextClassLoader());
280        } catch (ClassNotFoundException e) {
281            return Class.forName(className);
282        }
283    }
284}
285