1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: RawAbstractInput.java,v 1.1 2008/02/07 17:12:27 mark Exp $
7 */
8
9package com.sleepycat.persist.impl;
10
11import java.math.BigInteger;
12import java.util.IdentityHashMap;
13
14import com.sleepycat.persist.raw.RawObject;
15
16/**
17 * Base class for EntityInput implementations that type-check RawObject
18 * instances and convert them to regular persistent objects, via the
19 * Format.convertRawObject method.
20 *
21 * The subclass implements readNext which should call checkAndConvert before
22 * returning the final value.
23 *
24 * @author Mark Hayes
25 */
26abstract class RawAbstractInput extends AbstractInput {
27
28    private IdentityHashMap converted;
29
30    RawAbstractInput(Catalog catalog,
31                     boolean rawAccess,
32                     IdentityHashMap converted) {
33        super(catalog, rawAccess);
34        this.converted = converted;
35    }
36
37    public Object readObject() {
38        return readNext();
39    }
40
41    public Object readKeyObject(Format format) {
42        return readNext();
43    }
44
45    public void registerPriKeyObject(Object o) {
46    }
47
48    public int readArrayLength() {
49        throw new UnsupportedOperationException();
50    }
51
52    public int readEnumConstant(String[] names) {
53        throw new UnsupportedOperationException();
54    }
55
56    public void skipField(Format declaredFormat) {
57    }
58
59    abstract Object readNext();
60
61    Object checkAndConvert(Object o, Format declaredFormat) {
62        if (o == null) {
63            if (declaredFormat.isPrimitive()) {
64                throw new IllegalArgumentException
65                    ("A primitive type may not be null or missing: " +
66                     declaredFormat.getClassName());
67            }
68        } else if (declaredFormat.isSimple()) {
69            if (declaredFormat.isPrimitive()) {
70                if (o.getClass() !=
71                    declaredFormat.getWrapperFormat().getType()) {
72                    throw new IllegalArgumentException
73                        ("Raw value class: " + o.getClass().getName() +
74                         " must be the wrapper class for a primitive type: " +
75                         declaredFormat.getClassName());
76                }
77            } else {
78                if (o.getClass() != declaredFormat.getType()) {
79                    throw new IllegalArgumentException
80                        ("Raw value class: " + o.getClass().getName() +
81                         " must be the declared class for a simple type: " +
82                         declaredFormat.getClassName());
83                }
84            }
85        } else {
86            if (o instanceof RawObject) {
87                Object o2 = null;
88                if (!rawAccess) {
89                    if (converted != null) {
90                        o2 = converted.get(o);
91                    } else {
92                        converted = new IdentityHashMap();
93                    }
94                }
95                if (o2 != null) {
96                    o = o2;
97                } else {
98                    if (!rawAccess) {
99                        o = catalog.convertRawObject((RawObject) o, converted);
100                    }
101                }
102            } else {
103                if (!SimpleCatalog.isSimpleType(o.getClass())) {
104                    throw new IllegalArgumentException
105                        ("Raw value class: " + o.getClass().getName() +
106                         " must be RawObject a simple type");
107                }
108            }
109            if (rawAccess) {
110                checkRawType(catalog, o, declaredFormat);
111            } else {
112                if (!declaredFormat.getType().isAssignableFrom(o.getClass())) {
113                    throw new IllegalArgumentException
114                        ("Raw value class: " + o.getClass().getName() +
115                         " is not assignable to type: " +
116                         declaredFormat.getClassName());
117                }
118            }
119        }
120        return o;
121    }
122
123    static Format checkRawType(Catalog catalog,
124                               Object o,
125                               Format declaredFormat) {
126        assert declaredFormat != null;
127        Format format;
128        if (o instanceof RawObject) {
129            format = (Format) ((RawObject) o).getType();
130        } else {
131            format = catalog.getFormat(o.getClass());
132            if (!format.isSimple() || format.isEnum()) {
133                throw new IllegalArgumentException
134                    ("Not a RawObject or a non-enum simple type: " +
135                     format.getClassName());
136            }
137        }
138        if (!format.isAssignableTo(declaredFormat)) {
139            throw new IllegalArgumentException
140                ("Not a subtype of the field's declared class " +
141                 declaredFormat.getClassName() + ": " +
142                 format.getClassName());
143        }
144        if (!format.isCurrentVersion()) {
145            throw new IllegalArgumentException
146                ("Raw type version is not current.  Class: " +
147                 format.getClassName() + " Version: " +
148                 format.getVersion());
149        }
150        Format proxiedFormat = format.getProxiedFormat();
151        if (proxiedFormat != null) {
152            format = proxiedFormat;
153        }
154        return format;
155    }
156
157    /* The following methods are a subset of the methods in TupleInput. */
158
159    public String readString() {
160        return (String) readNext();
161    }
162
163    public char readChar() {
164        return ((Character) readNext()).charValue();
165    }
166
167    public boolean readBoolean() {
168        return ((Boolean) readNext()).booleanValue();
169    }
170
171    public byte readByte() {
172        return ((Byte) readNext()).byteValue();
173    }
174
175    public short readShort() {
176        return ((Short) readNext()).shortValue();
177    }
178
179    public int readInt() {
180        return ((Integer) readNext()).intValue();
181    }
182
183    public long readLong() {
184        return ((Long) readNext()).longValue();
185    }
186
187    public float readSortedFloat() {
188        return ((Float) readNext()).floatValue();
189    }
190
191    public double readSortedDouble() {
192        return ((Double) readNext()).doubleValue();
193    }
194
195    public BigInteger readBigInteger() {
196        return (BigInteger) readNext();
197    }
198}
199