• 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/raw/
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.raw;
10
11import java.util.Arrays;
12import java.util.Map;
13import java.util.TreeSet;
14
15import com.sleepycat.persist.evolve.Conversion;
16import com.sleepycat.persist.model.EntityModel;
17
18/**
19 * A raw instance that can be used with a {@link RawStore} or {@link
20 * Conversion}.  A <code>RawObject</code> is used to represent instances of
21 * complex types (persistent classes with fields), arrays, and enum values.  It
22 * is not used to represent non-enum simple types, which are represented as
23 * simple objects.  This includes primitives, which are represented as
24 * instances of their wrapper class.
25 *
26 * <p>{@code RawObject} objects are thread-safe.  Multiple threads may safely
27 * call the methods of a shared {@code RawObject} object.</p>
28 *
29 * @author Mark Hayes
30 */
31public class RawObject {
32
33    private static final String INDENT = "  ";
34
35    private RawType type;
36    private Map<String,Object> values;
37    private Object[] elements;
38    private String enumConstant;
39    private RawObject superObject;
40
41    /**
42     * Creates a raw object with a given set of field values for a complex
43     * type.
44     *
45     * @param type the type of this raw object.
46     *
47     * @param values a map of field name to value for each declared field in
48     * the class, or null to create an empty map.  Each value in the map is a
49     * {@link RawObject}, a {@link <a
50     * href="../model/Entity.html#simpleTypes">simple type</a>} instance, or
51     * null.
52     *
53     * @param superObject the instance of the superclass, or null if the
54     * superclass is {@code Object}.
55     *
56     * @throws IllegalArgumentException if the type argument is an array type.
57     */
58    public RawObject(RawType type,
59                     Map<String,Object> values,
60                     RawObject superObject) {
61        if (type == null || values == null) {
62            throw new NullPointerException();
63        }
64        this.type = type;
65        this.values = values;
66        this.superObject = superObject;
67    }
68
69    /**
70     * Creates a raw object with the given array elements for an array type.
71     *
72     * @param type the type of this raw object.
73     *
74     * @param elements an array of elements.  Each element in the array is a
75     * {@link RawObject}, a {@link <a
76     * href="../model/Entity.html#simpleTypes">simple type</a>} instance, or
77     * null.
78     *
79     * @throws IllegalArgumentException if the type argument is not an array
80     * type.
81     */
82    public RawObject(RawType type, Object[] elements) {
83        if (type == null || elements == null) {
84            throw new NullPointerException();
85        }
86        this.type = type;
87        this.elements = elements;
88    }
89
90    /**
91     * Creates a raw object with the given enum value for an enum type.
92     *
93     * @param type the type of this raw object.
94     *
95     * @param enumConstant the String value of this enum constant; must be
96     * one of the Strings returned by {@link RawType#getEnumConstants}.
97     *
98     * @throws IllegalArgumentException if the type argument is not an array
99     * type.
100     */
101    public RawObject(RawType type, String enumConstant) {
102        if (type == null || enumConstant == null) {
103            throw new NullPointerException();
104        }
105        this.type = type;
106        this.enumConstant = enumConstant;
107    }
108
109    /**
110     * Returns the raw type information for this raw object.
111     *
112     * <p>Note that if this object is unevolved, the returned type may be
113     * different from the current type returned by {@link
114     * EntityModel#getRawType EntityModel.getRawType} for the same class name.
115     * This can only occur in a {@link Conversion#convert
116     * Conversion.convert}.</p>
117     */
118    public RawType getType() {
119        return type;
120    }
121
122    /**
123     * Returns a map of field name to value for a complex type, or null for an
124     * array type or an enum type.  The map contains a String key for each
125     * declared field in the class.  Each value in the map is a {@link
126     * RawObject}, a {@link <a href="../model/Entity.html#simpleTypes">simple
127     * type</a>} instance, or null.
128     *
129     * <p>There will be an entry in the map for every field declared in this
130     * type, as determined by {@link RawType#getFields} for the type returned
131     * by {@link #getType}.  Values in the map may be null for fields with
132     * non-primitive types.</p>
133     */
134    public Map<String,Object> getValues() {
135        return values;
136    }
137
138    /**
139     * Returns the array of elements for an array type, or null for a complex
140     * type or an enum type.  Each element in the array is a {@link RawObject},
141     * a {@link <a href="../model/Entity.html#simpleTypes">simple type</a>}
142     * instance, or null.
143     */
144    public Object[] getElements() {
145        return elements;
146    }
147
148    /**
149     * Returns the enum constant String for an enum type, or null for a complex
150     * type or an array type.  The String returned will be one of the Strings
151     * returned by {@link RawType#getEnumConstants}.
152     */
153    public String getEnum() {
154        return enumConstant;
155    }
156
157    /**
158     * Returns the instance of the superclass, or null if the superclass is
159     * {@code Object} or {@code Enum}.
160     */
161    public RawObject getSuper() {
162        return superObject;
163    }
164
165    @Override
166    public boolean equals(Object other) {
167        if (other == this) {
168            return true;
169        }
170        if (!(other instanceof RawObject)) {
171            return false;
172        }
173        RawObject o = (RawObject) other;
174        if (type != o.type) {
175            return false;
176        }
177        if (!Arrays.deepEquals(elements, o.elements)) {
178            return false;
179        }
180        if (enumConstant != null) {
181            if (!enumConstant.equals(o.enumConstant)) {
182                return false;
183            }
184        } else {
185            if (o.enumConstant != null) {
186                return false;
187            }
188        }
189        if (values != null) {
190            if (!values.equals(o.values)) {
191                return false;
192            }
193        } else {
194            if (o.values != null) {
195                return false;
196            }
197        }
198        if (superObject != null) {
199            if (!superObject.equals(o.superObject)) {
200                return false;
201            }
202        } else {
203            if (o.superObject != null) {
204                return false;
205            }
206        }
207        return true;
208    }
209
210    @Override
211    public int hashCode() {
212        return System.identityHashCode(type) +
213               Arrays.deepHashCode(elements) +
214               (enumConstant != null ? enumConstant.hashCode() : 0) +
215               (values != null ? values.hashCode() : 0) +
216               (superObject != null ? superObject.hashCode() : 0);
217    }
218
219    /**
220     * Returns an XML representation of the raw object.
221     */
222    @Override
223    public String toString() {
224        StringBuffer buf = new StringBuffer(500);
225        formatRawObject(buf, "", null, false);
226        return buf.toString();
227    }
228
229    private void formatRawObject(StringBuffer buf,
230                                 String indent,
231                                 String id,
232                                 boolean isSuper) {
233        if (type.isEnum()) {
234            buf.append(indent);
235            buf.append("<Enum");
236            formatId(buf, id);
237            buf.append(" class=\"");
238            buf.append(type.getClassName());
239            buf.append("\" typeId=\"");
240            buf.append(type.getId());
241            buf.append("\">");
242            buf.append(enumConstant);
243            buf.append("</Enum>\n");
244        } else {
245            String indent2 = indent + INDENT;
246            String endTag;
247            buf.append(indent);
248            if (type.isArray()) {
249                buf.append("<Array");
250                endTag = "</Array>";
251            } else if (isSuper) {
252                buf.append("<Super");
253                endTag = "</Super>";
254            } else {
255                buf.append("<Object");
256                endTag = "</Object>";
257            }
258            formatId(buf, id);
259            if (type.isArray()) {
260                buf.append(" length=\"");
261                buf.append(elements.length);
262                buf.append('"');
263            }
264            buf.append(" class=\"");
265            buf.append(type.getClassName());
266            buf.append("\" typeId=\"");
267            buf.append(type.getId());
268            buf.append("\">\n");
269
270            if (superObject != null) {
271                superObject.formatRawObject(buf, indent2, null, true);
272            }
273            if (type.isArray()) {
274                for (int i = 0; i < elements.length; i += 1) {
275                    formatValue(buf, indent2, String.valueOf(i), elements[i]);
276                }
277            } else {
278                TreeSet<String> keys = new TreeSet<String>(values.keySet());
279                for (String name : keys) {
280                    formatValue(buf, indent2, name, values.get(name));
281                }
282            }
283            buf.append(indent);
284            buf.append(endTag);
285            buf.append("\n");
286        }
287    }
288
289    private static void formatValue(StringBuffer buf,
290                                    String indent,
291                                    String id,
292                                    Object val) {
293        if (val == null) {
294            buf.append(indent);
295            buf.append("<Null");
296            formatId(buf, id);
297            buf.append("/>\n");
298        } else if (val instanceof RawObject) {
299            ((RawObject) val).formatRawObject(buf, indent, id, false);
300        } else {
301            buf.append(indent);
302            buf.append("<Value");
303            formatId(buf, id);
304            buf.append(" class=\"");
305            buf.append(val.getClass().getName());
306            buf.append("\">");
307            buf.append(val.toString());
308            buf.append("</Value>\n");
309        }
310    }
311
312    private static void formatId(StringBuffer buf, String id) {
313        if (id != null) {
314            if (Character.isDigit(id.charAt(0))) {
315                buf.append(" index=\"");
316            } else {
317                buf.append(" field=\"");
318            }
319            buf.append(id);
320            buf.append('"');
321        }
322    }
323}
324