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