• 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/impl/
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.impl;
10
11import com.sleepycat.bind.EntityBinding;
12import com.sleepycat.bind.tuple.TupleBase;
13import com.sleepycat.db.DatabaseEntry;
14import com.sleepycat.persist.raw.RawObject;
15
16/**
17 * A persistence entity binding for a given entity class.
18 *
19 * @author Mark Hayes
20 */
21public class PersistEntityBinding implements EntityBinding {
22
23    PersistCatalog catalog;
24    Format entityFormat;
25    boolean rawAccess;
26    PersistKeyAssigner keyAssigner;
27
28    /**
29     * Creates a key binding for a given entity class.
30     */
31    public PersistEntityBinding(PersistCatalog catalog,
32                                String entityClassName,
33                                boolean rawAccess) {
34        this.catalog = catalog;
35        entityFormat = getOrCreateFormat(catalog, entityClassName, rawAccess);
36        if (!entityFormat.isEntity()) {
37            throw new IllegalArgumentException
38                ("Not an entity class: " + entityClassName);
39        }
40        this.rawAccess = rawAccess;
41    }
42
43    public PersistKeyAssigner getKeyAssigner() {
44        return keyAssigner;
45    }
46
47    public Object entryToObject(DatabaseEntry key, DatabaseEntry data) {
48        return readEntity(catalog, key, data, rawAccess);
49    }
50
51    /**
52     * Creates the instance, reads the entity key first to track visited
53     * entities correctly, then reads the data and returns the entity.
54     *
55     * This is a special case of EntityInput.readObject for a top level entity.
56     * Special treatments are:
57     * - The formatId must be >= 0; since this is the top level instance, it
58     *   cannot refer to a visited object nor be a null reference.
59     * - The resulting entity is not added to the visited object set; entities
60     *   cannot be referenced by another (or the same) entity.
61     * - Reader.readPriKey must be called prior to calling Reader.readObject.
62     */
63    static Object readEntity(Catalog catalog,
64                             DatabaseEntry key,
65                             DatabaseEntry data,
66                             boolean rawAccess) {
67        RecordInput keyInput = new RecordInput
68            (catalog, rawAccess, null, 0,
69             key.getData(), key.getOffset(), key.getSize());
70        RecordInput dataInput = new RecordInput
71            (catalog, rawAccess, null, 0,
72             data.getData(), data.getOffset(), data.getSize());
73        int formatId = dataInput.readPackedInt();
74        Format format = catalog.getFormat(formatId);
75        Reader reader = format.getReader();
76        Object entity = reader.newInstance(dataInput, rawAccess);
77        reader.readPriKey(entity, keyInput, rawAccess);
78        return reader.readObject(entity, dataInput, rawAccess);
79    }
80
81    public void objectToData(Object entity, DatabaseEntry data) {
82        Format format = getValidFormat(entity);
83        writeEntity(format, catalog, entity, data, rawAccess);
84    }
85
86    /**
87     * Writes the formatId and object, and returns the bytes.
88     *
89     * This is a special case of EntityOutput.writeObject for a top level
90     * entity.  Special treatments are:
91     * - The entity may not be null.
92     * - The entity is not added to the visited object set nor checked for
93     *   existence in the visited object set; entities cannot be referenced by
94     *   another (or the same) entity.
95     */
96    static void writeEntity(Format format,
97                            Catalog catalog,
98                            Object entity,
99                            DatabaseEntry data,
100                            boolean rawAccess) {
101        RecordOutput output = new RecordOutput(catalog, rawAccess);
102        output.writePackedInt(format.getId());
103        format.writeObject(entity, output, rawAccess);
104        TupleBase.outputToEntry(output, data);
105    }
106
107    public void objectToKey(Object entity, DatabaseEntry key) {
108
109        /*
110         * Write the primary key field as a special case since the output
111         * format is for a key binding, not entity data.
112         */
113        Format format = getValidFormat(entity);
114        RecordOutput output = new RecordOutput(catalog, rawAccess);
115
116        /* Write the primary key and return the bytes. */
117        format.writePriKey(entity, output, rawAccess);
118        TupleBase.outputToEntry(output, key);
119    }
120
121    /**
122     * Returns the format for the given entity and validates it, throwing an
123     * exception if it is invalid for this binding.
124     */
125    private Format getValidFormat(Object entity) {
126
127        /* A null entity is not allowed. */
128        if (entity == null) {
129            throw new IllegalArgumentException("An entity may not be null");
130        }
131
132        /*
133         * Get the format.  getFormat throws IllegalArgumentException if the
134         * class is not persistent.
135         */
136        Format format;
137        if (rawAccess) {
138            if (!(entity instanceof RawObject)) {
139                throw new IllegalArgumentException
140                    ("Entity must be a RawObject");
141            }
142            format = (Format) ((RawObject) entity).getType();
143        } else {
144            format = catalog.getFormat
145                (entity.getClass(), true /*checkEntitySubclassIndexes*/);
146        }
147
148        /* Check that the entity class/subclass is valid for this binding. */
149        if (format.getEntityFormat() != entityFormat) {
150            throw new IllegalArgumentException
151                ("The entity class (" + format.getClassName() +
152                 ") must be this entity class or a subclass of it: " +
153                 entityFormat.getClassName());
154        }
155
156        return format;
157    }
158
159    /**
160     * Utility method for getting or creating a format as appropriate for
161     * bindings and key creators.
162     */
163    static Format getOrCreateFormat(Catalog catalog,
164                                    String clsName,
165                                    boolean rawAccess) {
166        if (rawAccess) {
167            Format format = catalog.getFormat(clsName);
168            if (format == null) {
169                throw new IllegalArgumentException
170                    ("Not a persistent class: " + clsName);
171            }
172            return format;
173        } else {
174            Class cls = SimpleCatalog.keyClassForName(clsName);
175            return catalog.getFormat(cls, true /*checkEntitySubclassIndexes*/);
176        }
177    }
178}
179