blob: 12999af04485614b715a33a612b6661a468b3f6c [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.persist.impl;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.IdentityHashMap;
import com.sleepycat.compat.DbCompat;
import com.sleepycat.persist.raw.RawObject;
/**
* Base class for EntityInput implementations that type-check RawObject
* instances and convert them to regular persistent objects, via the
* Format.convertRawObject method.
*
* The subclass implements readNext which should call checkAndConvert before
* returning the final value.
*
* @author Mark Hayes
*/
abstract class RawAbstractInput extends AbstractInput {
private IdentityHashMap converted;
RawAbstractInput(Catalog catalog,
boolean rawAccess,
IdentityHashMap converted) {
super(catalog, rawAccess);
this.converted = converted;
}
public Object readObject()
throws RefreshException {
return readNext();
}
public Object readKeyObject(Format format)
throws RefreshException {
return readNext();
}
public Object readStringObject()
throws RefreshException {
return readNext();
}
public void registerPriKeyObject(Object o) {
}
public void registerPriStringKeyObject(Object o) {
}
public int readArrayLength() {
throw DbCompat.unexpectedState();
}
public int readEnumConstant(String[] names) {
throw DbCompat.unexpectedState();
}
public void skipField(Format declaredFormat) {
}
abstract Object readNext()
throws RefreshException;
Object checkAndConvert(Object o, Format declaredFormat)
throws RefreshException {
if (o == null) {
if (declaredFormat.isPrimitive()) {
throw new IllegalArgumentException
("A primitive type may not be null or missing: " +
declaredFormat.getClassName());
}
} else if (declaredFormat.isSimple()) {
if (declaredFormat.isPrimitive()) {
if (o.getClass() !=
declaredFormat.getWrapperFormat().getType()) {
throw new IllegalArgumentException
("Raw value class: " + o.getClass().getName() +
" must be the wrapper class for a primitive type: " +
declaredFormat.getClassName());
}
} else {
if (o.getClass() != declaredFormat.getType()) {
throw new IllegalArgumentException
("Raw value class: " + o.getClass().getName() +
" must be the declared class for a simple type: " +
declaredFormat.getClassName());
}
}
} else {
if (o instanceof RawObject) {
Object o2 = null;
if (!rawAccess) {
if (converted != null) {
o2 = converted.get(o);
} else {
converted = new IdentityHashMap();
}
}
if (o2 != null) {
o = o2;
} else {
if (!rawAccess) {
o = catalog.convertRawObject((RawObject) o, converted);
}
}
} else {
if (!SimpleCatalog.isSimpleType(o.getClass())) {
throw new IllegalArgumentException
("Raw value class: " + o.getClass().getName() +
" must be RawObject a simple type");
}
}
if (rawAccess) {
checkRawType(catalog, o, declaredFormat);
} else {
if (!declaredFormat.getType().isAssignableFrom(o.getClass())) {
throw new IllegalArgumentException
("Raw value class: " + o.getClass().getName() +
" is not assignable to type: " +
declaredFormat.getClassName());
}
}
}
return o;
}
static Format checkRawType(Catalog catalog,
Object o,
Format declaredFormat)
throws RefreshException {
assert declaredFormat != null;
Format format;
if (o instanceof RawObject) {
format = (Format) ((RawObject) o).getType();
/* Ensure a fresh format is used, in case of Replica refresh. */
format = catalog.getFormat(format.getId(), false /*expectStored*/);
} else {
format = catalog.getFormat(o.getClass(),
false /*checkEntitySubclassIndexes*/);
if (!format.isSimple() || format.isEnum()) {
throw new IllegalArgumentException
("Not a RawObject or a non-enum simple type: " +
format.getClassName());
}
}
if (!format.isAssignableTo(declaredFormat)) {
throw new IllegalArgumentException
("Not a subtype of the field's declared class " +
declaredFormat.getClassName() + ": " +
format.getClassName());
}
if (!format.isCurrentVersion()) {
throw new IllegalArgumentException
("Raw type version is not current. Class: " +
format.getClassName() + " Version: " +
format.getVersion());
}
Format proxiedFormat = format.getProxiedFormat();
if (proxiedFormat != null) {
format = proxiedFormat;
}
return format;
}
/* The following methods are a subset of the methods in TupleInput. */
public String readString()
throws RefreshException {
return (String) readNext();
}
public char readChar()
throws RefreshException {
return ((Character) readNext()).charValue();
}
public boolean readBoolean()
throws RefreshException {
return ((Boolean) readNext()).booleanValue();
}
public byte readByte()
throws RefreshException {
return ((Byte) readNext()).byteValue();
}
public short readShort()
throws RefreshException {
return ((Short) readNext()).shortValue();
}
public int readInt()
throws RefreshException {
return ((Integer) readNext()).intValue();
}
public long readLong()
throws RefreshException {
return ((Long) readNext()).longValue();
}
public float readSortedFloat()
throws RefreshException {
return ((Float) readNext()).floatValue();
}
public double readSortedDouble()
throws RefreshException {
return ((Double) readNext()).doubleValue();
}
public BigDecimal readSortedBigDecimal()
throws RefreshException {
return (BigDecimal) readNext();
}
public BigInteger readBigInteger()
throws RefreshException {
return (BigInteger) readNext();
}
}