• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/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 java.lang.reflect.Array;
12import java.util.IdentityHashMap;
13import java.util.Map;
14import java.util.Set;
15
16import com.sleepycat.db.DatabaseEntry;
17import com.sleepycat.persist.model.EntityModel;
18import com.sleepycat.persist.raw.RawObject;
19
20/**
21 * An array of objects having a specified number of dimensions.  All
22 * multidimensional arrays are handled by this class, since even a primitive
23 * array of more than one dimension is an array of objects, where the component
24 * objects may be primitive arrays.  The {@link PrimitiveArrayFormat} class
25 * handles primitive arrays of one dimension only.
26 *
27 * In this class, and {@link PrimitiveArrayFormat}, we resort to using
28 * reflection to allocate multidimensional arrays.  If there is a need for it,
29 * reflection could be avoided in the future by generating code as new array
30 * formats are encountered.
31 *
32 * @author Mark Hayes
33 */
34public class ObjectArrayFormat extends Format {
35
36    private static final long serialVersionUID = 4317004346690441892L;
37
38    private Format componentFormat;
39    private int nDimensions;
40    private transient Format useComponentFormat;
41
42    ObjectArrayFormat(Class type) {
43        super(type);
44        String name = getClassName();
45        for (nDimensions = 0;
46             name.charAt(nDimensions) == '[';
47             nDimensions += 1) {
48        }
49    }
50
51    @Override
52    public boolean isArray() {
53        return true;
54    }
55
56    @Override
57    public int getDimensions() {
58        return nDimensions;
59    }
60
61    @Override
62    public Format getComponentType() {
63        return (useComponentFormat != null) ?
64            useComponentFormat : componentFormat;
65    }
66
67    @Override
68    void collectRelatedFormats(Catalog catalog,
69                               Map<String,Format> newFormats) {
70        Class cls = getType().getComponentType();
71        catalog.createFormat(cls, newFormats);
72    }
73
74    @Override
75    void initialize(Catalog catalog, EntityModel model, int initVersion) {
76        /* Set the component format for a new (never initialized) format. */
77        if (componentFormat == null) {
78            Class cls = getType().getComponentType();
79            componentFormat = catalog.getFormat(cls.getName());
80        }
81        useComponentFormat = componentFormat.getLatestVersion();
82    }
83
84    @Override
85    boolean isAssignableTo(Format format) {
86        if (super.isAssignableTo(format)) {
87            return true;
88        }
89        if (format instanceof ObjectArrayFormat) {
90            ObjectArrayFormat other = (ObjectArrayFormat) format;
91            if (useComponentFormat.isAssignableTo(other.useComponentFormat)) {
92                return true;
93            }
94        }
95        return false;
96    }
97
98    @Override
99    Object newArray(int len) {
100        return Array.newInstance(getType(), len);
101    }
102
103    @Override
104    public Object newInstance(EntityInput input, boolean rawAccess) {
105        int len = input.readArrayLength();
106        if (rawAccess) {
107            return new RawObject(this, new Object[len]);
108        } else {
109            return useComponentFormat.newArray(len);
110        }
111    }
112
113    @Override
114    public Object readObject(Object o, EntityInput input, boolean rawAccess) {
115        Object[] a;
116        if (rawAccess) {
117            a = ((RawObject) o).getElements();
118        } else {
119            a = (Object[]) o;
120        }
121        for (int i = 0; i < a.length; i += 1) {
122            a[i] = input.readObject();
123        }
124        return o;
125    }
126
127    @Override
128    void writeObject(Object o, EntityOutput output, boolean rawAccess) {
129        Object[] a;
130        if (rawAccess) {
131            a = ((RawObject) o).getElements();
132        } else {
133            a = (Object[]) o;
134        }
135        output.writeArrayLength(a.length);
136        for (int i = 0; i < a.length; i += 1) {
137            output.writeObject(a[i], useComponentFormat);
138        }
139    }
140
141    @Override
142    Object convertRawObject(Catalog catalog,
143                            boolean rawAccess,
144                            RawObject rawObject,
145                            IdentityHashMap converted) {
146        RawArrayInput input = new RawArrayInput
147            (catalog, rawAccess, converted, rawObject, useComponentFormat);
148        Object a = newInstance(input, rawAccess);
149        converted.put(rawObject, a);
150        return readObject(a, input, rawAccess);
151    }
152
153    @Override
154    void skipContents(RecordInput input) {
155        int len = input.readPackedInt();
156        for (int i = 0; i < len; i += 1) {
157            input.skipField(useComponentFormat);
158        }
159    }
160
161    @Override
162    void copySecMultiKey(RecordInput input, Format keyFormat, Set results) {
163        int len = input.readPackedInt();
164        for (int i = 0; i < len; i += 1) {
165            KeyLocation loc = input.getKeyLocation(useComponentFormat);
166            if (loc == null) {
167                throw new IllegalArgumentException
168                    ("Secondary key values in array may not be null");
169            }
170            if (loc.format != useComponentFormat) {
171                throw new IllegalStateException
172                    (useComponentFormat.getClassName());
173            }
174            int off1 = loc.input.getBufferOffset();
175            useComponentFormat.skipContents(loc.input);
176            int off2 = loc.input.getBufferOffset();
177            DatabaseEntry entry = new DatabaseEntry
178                (loc.input.getBufferBytes(), off1, off2 - off1);
179            results.add(entry);
180        }
181    }
182
183    @Override
184    boolean evolve(Format newFormat, Evolver evolver) {
185
186        /*
187         * When the class name of the component changes, we need a new format
188         * that references it.  Otherwise, don't propogate changes from
189         * components upward to their arrays.
190         */
191        Format latest = componentFormat.getLatestVersion();
192        if (latest != componentFormat &&
193            !latest.getClassName().equals(componentFormat.getClassName())) {
194            evolver.useEvolvedFormat(this, newFormat, newFormat);
195        } else {
196            evolver.useOldFormat(this, newFormat);
197        }
198        return true;
199    }
200}
201