com.sleepycat.persist.impl.FieldInfo Maven / Gradle / Ivy
The newest version!
/*-
* 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.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.sleepycat.compat.DbCompat;
import com.sleepycat.persist.model.EntityModel;
import com.sleepycat.persist.raw.RawField;
import com.sleepycat.persist.model.FieldMetadata;
import com.sleepycat.persist.model.ClassMetadata;
/**
* A field definition used by ComplexFormat and CompositeKeyFormat.
*
* Note that the equals(), compareTo() and hashCode() methods only use the
* name field in this class. Comparing two FieldInfo objects is only done when
* both are declared in the same class, so comparing the field name is
* sufficient.
*
* @author Mark Hayes
*/
class FieldInfo implements RawField, Serializable, Comparable {
private static final long serialVersionUID = 2062721100372306296L;
/**
* Returns a list of all non-transient non-static fields that are declared
* in the given class.
*/
static List getInstanceFields(Class cls,
ClassMetadata clsMeta) {
List fields = null;
if (clsMeta != null) {
Collection persistentFields =
clsMeta.getPersistentFields();
if (persistentFields != null) {
fields = new ArrayList(persistentFields.size());
String clsName = cls.getName();
for (FieldMetadata fieldMeta : persistentFields) {
if (!clsName.equals(fieldMeta.getDeclaringClassName())) {
throw new IllegalArgumentException
("Persistent field " + fieldMeta +
" must be declared in " + clsName);
}
Field field;
try {
field = cls.getDeclaredField(fieldMeta.getName());
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException
("Persistent field " + fieldMeta +
" is not declared in this class");
}
if (!field.getType().getName().equals
(fieldMeta.getClassName())) {
throw new IllegalArgumentException
("Persistent field " + fieldMeta +
" must be of type " + field.getType().getName());
}
if (Modifier.isStatic(field.getModifiers())) {
throw new IllegalArgumentException
("Persistent field " + fieldMeta +
" may not be static");
}
fields.add(new FieldInfo(field));
}
}
}
if (fields == null) {
Field[] declaredFields = cls.getDeclaredFields();
fields = new ArrayList(declaredFields.length);
for (Field field : declaredFields) {
int mods = field.getModifiers();
if (!Modifier.isTransient(mods) && !Modifier.isStatic(mods)) {
fields.add(new FieldInfo(field));
}
}
}
return fields;
}
static FieldInfo getField(List fields, String fieldName) {
int i = getFieldIndex(fields, fieldName);
if (i >= 0) {
return fields.get(i);
} else {
return null;
}
}
static int getFieldIndex(List fields, String fieldName) {
for (int i = 0; i < fields.size(); i += 1) {
FieldInfo field = fields.get(i);
if (fieldName.equals(field.getName())) {
return i;
}
}
return -1;
}
private String name;
private String className;
private Format format;
private transient Class cls;
private transient Field field;
private FieldInfo(Field field) {
name = field.getName();
cls = field.getType();
className = cls.getName();
this.field = field;
}
void collectRelatedFormats(Catalog catalog,
Map newFormats) {
/*
* Prior to intialization we save the newly created format in the
* format field so that it can be used by class evolution. But note
* that it may be replaced by the initialize method. [#16233]
*/
format = catalog.createFormat(cls, newFormats);
/*
* If the created format is a NonPersistentFormat, and the field is a
* map or a collection, then the generic types of this field are
* ParameterizedTypes, e.g., Map, so the formats of
* the generic types for this field, i.e., MyClass1 and MyClass2 will
* be created here. [#19377]
*/
Class cls = field.getType();
if (format instanceof NonPersistentFormat &&
(java.util.Map.class.isAssignableFrom(cls) ||
java.util.Collection.class.isAssignableFrom(cls))) {
if (field != null &&
field.getGenericType() instanceof ParameterizedType) {
collectParameterizedTypeFormats(catalog, newFormats,
(ParameterizedType)field.getGenericType());
}
}
}
/*
* Create formats for the parameterized types, e.g., will create formats
* for MyClass1 and MyClass2 when meeting Map>,
* where MyClass1 and MyClass2 are instance of java.lang.Class.
*/
private void
collectParameterizedTypeFormats(Catalog catalog,
Map newFormats,
ParameterizedType parameType) {
Type[] types = parameType.getActualTypeArguments();
for (int i = 0; i < types.length; i++) {
if (types[i] instanceof ParameterizedType) {
collectParameterizedTypeFormats(catalog, newFormats,
(ParameterizedType)types[i]);
} else if (types[i] instanceof Class) {
/*
* Only use Catalog.createFormat to create the format for the
* class which is instance of java.lang.class.
*/
catalog.createFormat((Class)types[i], newFormats);
}
}
}
void migrateFromBeta(Map formatMap) {
if (format == null) {
format = formatMap.get(className);
if (format == null) {
throw DbCompat.unexpectedState(className);
}
}
}
void initialize(Catalog catalog, EntityModel model, int initVersion) {
/*
* Reset the format if it was never initialized, which can occur when a
* new format instance created during class evolution and discarded
* because nothing changed. [#16233]
*
* Note that the format field may be null when used in a composite key
* format used as a key comparator (via PersistComparator). In that
* case (null format), we must not attempt to reset the format.
*/
if (format != null && format.isNew()) {
format = catalog.getFormat(className);
}
}
Class getFieldClass(Catalog catalog) {
if (cls == null) {
try {
cls = catalog.resolveClass(className);
} catch (ClassNotFoundException e) {
throw DbCompat.unexpectedException(e);
}
}
return cls;
}
String getClassName() {
return className;
}
public String getName() {
return name;
}
public Format getType() {
return format;
}
public int compareTo(FieldInfo o) {
return name.compareTo(o.name);
}
@Override
public boolean equals(Object other) {
if (other instanceof FieldInfo) {
FieldInfo o = (FieldInfo) other;
return name.equals(o.name);
} else {
return false;
}
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return "[Field name: " + name + " class: " + className + ']';
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy