use of org.datanucleus.metadata.ColumnMetaData in project datanucleus-rdbms by datanucleus.
the class MappingManagerImpl method createDatastoreMapping.
/**
* Method to create the datastore mapping for a java type mapping at a particular index.
* @param mapping The java mapping
* @param mmd MetaData for the field/property
* @param index Index of the column
* @param column The column
* @return The datastore mapping
*/
public DatastoreMapping createDatastoreMapping(JavaTypeMapping mapping, AbstractMemberMetaData mmd, int index, Column column) {
Class datastoreMappingClass = null;
if (mmd.getColumnMetaData().length > 0) {
// Use "datastore-mapping-class" extension if provided
if (mmd.getColumnMetaData()[index].hasExtension("datastore-mapping-class")) {
datastoreMappingClass = clr.classForName(mmd.getColumnMetaData()[index].getValueForExtension("datastore-mapping-class"));
}
}
if (datastoreMappingClass == null) {
String javaType = mapping.getJavaTypeForDatastoreMapping(index);
String jdbcType = null;
String sqlType = null;
if (mapping.getRoleForMember() == FieldRole.ROLE_ARRAY_ELEMENT || mapping.getRoleForMember() == FieldRole.ROLE_COLLECTION_ELEMENT) {
// Element of a collection/array
ColumnMetaData[] colmds = (mmd.getElementMetaData() != null ? mmd.getElementMetaData().getColumnMetaData() : null);
if (colmds != null && colmds.length > 0) {
jdbcType = colmds[index].getJdbcTypeName();
sqlType = colmds[index].getSqlType();
}
if (mmd.getCollection() != null && mmd.getCollection().isSerializedElement()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
if (mmd.getArray() != null && mmd.getArray().isSerializedElement()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
} else if (mapping.getRoleForMember() == FieldRole.ROLE_MAP_KEY) {
// Key of a map
ColumnMetaData[] colmds = (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getColumnMetaData() : null);
if (colmds != null && colmds.length > 0) {
jdbcType = colmds[index].getJdbcTypeName();
sqlType = colmds[index].getSqlType();
}
if (mmd.getMap().isSerializedKey()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
} else if (mapping.getRoleForMember() == FieldRole.ROLE_MAP_VALUE) {
// Value of a map
ColumnMetaData[] colmds = (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getColumnMetaData() : null);
if (colmds != null && colmds.length > 0) {
jdbcType = colmds[index].getJdbcTypeName();
sqlType = colmds[index].getSqlType();
}
if (mmd.getMap().isSerializedValue()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
} else {
// Normal field
if (mmd.getColumnMetaData().length > 0) {
// Utilise the jdbc and sql types if specified
jdbcType = mmd.getColumnMetaData()[index].getJdbcTypeName();
sqlType = mmd.getColumnMetaData()[index].getSqlType();
}
// Special case where we have IDENTITY strategy and the datastore imposes a limitation on the required datastore type
ValueGenerationStrategy strategy = mmd.getValueStrategy();
if (strategy != null) {
String strategyName = strategy.toString();
if (strategy == ValueGenerationStrategy.NATIVE) {
strategyName = storeMgr.getValueGenerationStrategyForNative(mmd.getAbstractClassMetaData(), mmd.getAbsoluteFieldNumber());
}
if (strategyName != null && ValueGenerationStrategy.IDENTITY.toString().equals(strategyName)) {
Class requestedType = clr.classForName(javaType);
Class requiredType = storeMgr.getDatastoreAdapter().getAutoIncrementJavaTypeForType(requestedType);
if (requiredType != mmd.getType()) {
NucleusLogger.DATASTORE_SCHEMA.debug("Member " + mmd.getFullFieldName() + " uses IDENTITY strategy and rather than using memberType of " + mmd.getTypeName() + " for the column type, using " + requiredType + " since the datastore requires that");
}
javaType = requiredType.getName();
}
}
if (mmd.isSerialized()) {
javaType = ClassNameConstants.JAVA_IO_SERIALIZABLE;
}
}
datastoreMappingClass = storeMgr.getDatastoreAdapter().getDatastoreMappingClass(javaType, jdbcType, sqlType, clr, mmd.getFullFieldName());
}
DatastoreMapping datastoreMapping = DatastoreMappingFactory.createMapping(datastoreMappingClass, mapping, storeMgr, column);
if (column != null) {
column.setDatastoreMapping(datastoreMapping);
}
return datastoreMapping;
}
use of org.datanucleus.metadata.ColumnMetaData in project datanucleus-rdbms by datanucleus.
the class EmbeddedMapping method initialize.
/**
* Initialize for the specified member.
* @param mmd metadata for the embedded member
* @param table Table for persisting this field
* @param clr The ClassLoaderResolver
* @param emd Embedded MetaData for the object being embedded
* @param typeName type of the embedded PC object being stored
* @param objectType Object type of the PC object being embedded (see StateManagerImpl object types)
*/
public void initialize(AbstractMemberMetaData mmd, Table table, ClassLoaderResolver clr, EmbeddedMetaData emd, String typeName, int objectType) {
super.initialize(mmd, table, clr);
this.clr = clr;
this.emd = emd;
this.typeName = typeName;
this.objectType = (short) objectType;
// Find the MetaData for the embedded PC class
MetaDataManager mmgr = table.getStoreManager().getMetaDataManager();
AbstractClassMetaData rootEmbCmd = mmgr.getMetaDataForClass(typeName, clr);
if (rootEmbCmd == null) {
// Not found so must be an interface
// Try using the fieldTypes on the field/property - we support it if only 1 implementation
String[] fieldTypes = mmd.getFieldTypes();
if (fieldTypes != null && fieldTypes.length == 1) {
rootEmbCmd = mmgr.getMetaDataForClass(fieldTypes[0], clr);
} else if (fieldTypes != null && fieldTypes.length > 1) {
// TODO Cater for multiple implementations
throw new NucleusUserException("Field " + mmd.getFullFieldName() + " is a reference field that is embedded with multiple possible implementations. " + "DataNucleus doesnt support embedded reference fields that have more than 1 implementation");
}
if (rootEmbCmd == null) {
// Try a persistent interface
rootEmbCmd = mmgr.getMetaDataForInterface(clr.classForName(typeName), clr);
if (rootEmbCmd == null && mmd.getFieldTypes() != null && mmd.getFieldTypes().length == 1) {
// No MetaData for the type so try "fieldType" specified on the field
rootEmbCmd = mmgr.getMetaDataForInterface(clr.classForName(mmd.getFieldTypes()[0]), clr);
}
}
}
if (rootEmbCmd == null) {
throw new NucleusUserException("Unable to find root class embedded metadata for field=" + mmd.getFullFieldName());
}
embCmd = rootEmbCmd;
AbstractMemberMetaData[] embFmds = null;
if (emd == null && rootEmbCmd.isEmbeddedOnly()) {
// No <embedded> block yet the class is defined as embedded-only so just use its own definition of fields
embFmds = rootEmbCmd.getManagedMembers();
} else if (emd != null) {
// <embedded> block so use those field definitions
embFmds = emd.getMemberMetaData();
}
String[] subclasses = mmgr.getSubclassesForClass(rootEmbCmd.getFullClassName(), true);
if (subclasses != null && subclasses.length > 0) {
if (rootEmbCmd.hasDiscriminatorStrategy()) {
// Fabricate a DiscriminatorMetaData to use for the embedded object
discrimMetaData = new DiscriminatorMetaData();
InheritanceMetaData embInhMd = new InheritanceMetaData();
embInhMd.setParent(rootEmbCmd);
discrimMetaData.setParent(embInhMd);
// Set strategy based on the inheritance of the embedded object, otherwise class name.
DiscriminatorMetaData dismd = rootEmbCmd.getDiscriminatorMetaDataRoot();
if (dismd.getStrategy() != null && dismd.getStrategy() != DiscriminatorStrategy.NONE) {
discrimMetaData.setStrategy(dismd.getStrategy());
} else {
// Fallback to class name
discrimMetaData.setStrategy(DiscriminatorStrategy.CLASS_NAME);
}
// Set column for discriminator
ColumnMetaData disColmd = new ColumnMetaData();
disColmd.setAllowsNull(Boolean.TRUE);
DiscriminatorMetaData embDismd = (emd != null) ? emd.getDiscriminatorMetaData() : null;
if (embDismd != null && embDismd.getColumnMetaData() != null) {
disColmd.setName(embDismd.getColumnMetaData().getName());
} else {
ColumnMetaData colmd = dismd.getColumnMetaData();
if (colmd != null && colmd.getName() != null) {
disColmd.setName(colmd.getName());
}
}
discrimMetaData.setColumnMetaData(disColmd);
discrimMapping = DiscriminatorMapping.createDiscriminatorMapping(table, discrimMetaData);
addDatastoreMapping(discrimMapping.getDatastoreMapping(0));
} else {
NucleusLogger.PERSISTENCE.info("Member " + mmd.getFullFieldName() + " is embedded and the type " + "(" + rootEmbCmd.getFullClassName() + ") has potential subclasses." + " Impossible to detect which is stored embedded. Add a discriminator to the embedded type");
}
}
// Add all fields of the embedded class (that are persistent)
int[] pcFieldNumbers = rootEmbCmd.getAllMemberPositions();
for (int i = 0; i < pcFieldNumbers.length; i++) {
AbstractMemberMetaData rootEmbMmd = rootEmbCmd.getMetaDataForManagedMemberAtAbsolutePosition(pcFieldNumbers[i]);
if (rootEmbMmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
addMappingForMember(rootEmbCmd, rootEmbMmd, embFmds);
}
}
// Add fields for any subtypes (that are persistent)
if (discrimMapping != null && subclasses != null && subclasses.length > 0) {
for (int i = 0; i < subclasses.length; i++) {
AbstractClassMetaData subEmbCmd = storeMgr.getMetaDataManager().getMetaDataForClass(subclasses[i], clr);
AbstractMemberMetaData[] subEmbMmds = subEmbCmd.getManagedMembers();
if (subEmbMmds != null) {
for (int j = 0; j < subEmbMmds.length; j++) {
if (subEmbMmds[j].getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
addMappingForMember(subEmbCmd, subEmbMmds[j], embFmds);
}
}
}
}
}
}
use of org.datanucleus.metadata.ColumnMetaData in project datanucleus-rdbms by datanucleus.
the class AbstractContainerMapping method prepareDatastoreMapping.
/**
* Method to prepare a field mapping for use in the datastore.
* This creates the column in the table.
*/
protected void prepareDatastoreMapping() {
if (containerIsStoredInSingleColumn()) {
// Serialised collections/maps/arrays should just create a (typically BLOB) column as normal in the owning table
MappingManager mmgr = storeMgr.getMappingManager();
ColumnMetaData colmd = null;
ColumnMetaData[] colmds = mmd.getColumnMetaData();
if (colmds != null && colmds.length > 0) {
// Try the field column info
colmd = colmds[0];
} else if (mmd.hasCollection() || mmd.hasArray()) {
// Fallback to the element column info
colmds = (mmd.getElementMetaData() != null) ? mmd.getElementMetaData().getColumnMetaData() : null;
if (colmds != null && colmds.length > 0) {
colmd = colmds[0];
}
}
Column col = mmgr.createColumn(this, getJavaTypeForDatastoreMapping(0), colmd);
mmgr.createDatastoreMapping(this, mmd, 0, col);
}
}
use of org.datanucleus.metadata.ColumnMetaData in project datanucleus-rdbms by datanucleus.
the class ReferenceMapping method prepareDatastoreMapping.
/**
* Convenience method to create the necessary columns to represent this reference in the datastore.
* With "per-implementation" mapping strategy will create columns for each of the possible implementations.
* With "identity"/"xcalia" will create a single column to store a reference to the implementation value.
* @param clr The ClassLoaderResolver
*/
protected void prepareDatastoreMapping(ClassLoaderResolver clr) {
if (mappingStrategy == PER_IMPLEMENTATION_MAPPING) {
// Mapping per reference implementation, so create columns for each possible implementation
if (roleForMember == FieldRole.ROLE_ARRAY_ELEMENT) {
// Creation of columns in join table for array of references
ColumnMetaData[] colmds = null;
ElementMetaData elemmd = mmd.getElementMetaData();
if (elemmd != null && elemmd.getColumnMetaData() != null && elemmd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = elemmd.getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else if (roleForMember == FieldRole.ROLE_COLLECTION_ELEMENT) {
// Creation of columns in join table for collection of references
ColumnMetaData[] colmds = null;
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
ElementMetaData elemmd = mmd.getElementMetaData();
if (elemmd != null && elemmd.getColumnMetaData() != null && elemmd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = elemmd.getColumnMetaData();
} else if (relatedMmds != null && relatedMmds[0].getJoinMetaData() != null && relatedMmds[0].getJoinMetaData().getColumnMetaData() != null && relatedMmds[0].getJoinMetaData().getColumnMetaData().length > 0) {
// Column mappings defined at other side (M-N) on <join>
colmds = relatedMmds[0].getJoinMetaData().getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else if (roleForMember == FieldRole.ROLE_MAP_KEY) {
// Creation of columns in join table for map of references as keys
ColumnMetaData[] colmds = null;
KeyMetaData keymd = mmd.getKeyMetaData();
if (keymd != null && keymd.getColumnMetaData() != null && keymd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = keymd.getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else if (roleForMember == FieldRole.ROLE_MAP_VALUE) {
// Creation of columns in join table for map of references as values
ColumnMetaData[] colmds = null;
ValueMetaData valuemd = mmd.getValueMetaData();
if (valuemd != null && valuemd.getColumnMetaData() != null && valuemd.getColumnMetaData().length > 0) {
// Column mappings defined at this side (1-N, M-N)
colmds = valuemd.getColumnMetaData();
}
createPerImplementationColumnsForReferenceField(false, false, false, false, roleForMember, colmds, clr);
} else {
if (mmd.getMappedBy() == null) {
// Unidirectional 1-1
boolean embedded = (mmd.isEmbedded() || mmd.getEmbeddedMetaData() != null);
createPerImplementationColumnsForReferenceField(false, true, false, embedded, roleForMember, mmd.getColumnMetaData(), clr);
} else {
// Bidirectional 1-1/N-1
AbstractClassMetaData refCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForInterface(mmd.getType(), clr);
if (refCmd != null && refCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
// TODO Is this block actually reachable ? Would we specify "inheritance" under "interface" elements?
// Find the actual tables storing the other end (can be multiple subclasses)
AbstractClassMetaData[] cmds = storeMgr.getClassesManagingTableForClass(refCmd, clr);
if (cmds != null && cmds.length > 0) {
if (cmds.length > 1) {
NucleusLogger.PERSISTENCE.warn("Field " + mmd.getFullFieldName() + " represents either a 1-1 relation, or a N-1 relation where the other end uses" + " \"subclass-table\" inheritance strategy and more than 1 subclasses with a table. " + "This is not fully supported currently");
}
} else {
// TODO Throw an exception ?
return;
}
// TODO We need a mapping for each of the possible subclass tables
/*JavaTypeMapping referenceMapping = */
storeMgr.getDatastoreClass(cmds[0].getFullClassName(), clr).getIdMapping();
} else {
String[] implTypes = MetaDataUtils.getInstance().getImplementationNamesForReferenceField(mmd, FieldRole.ROLE_FIELD, clr, storeMgr.getMetaDataManager());
for (int j = 0; j < implTypes.length; j++) {
JavaTypeMapping refMapping = storeMgr.getDatastoreClass(implTypes[j], clr).getIdMapping();
JavaTypeMapping mapping = storeMgr.getMappingManager().getMapping(clr.classForName(implTypes[j]));
mapping.setReferenceMapping(refMapping);
this.addJavaTypeMapping(mapping);
}
}
}
}
} else if (mappingStrategy == ID_MAPPING || mappingStrategy == XCALIA_MAPPING) {
// Single (String) column storing the identity of the related object
MappingManager mapMgr = storeMgr.getMappingManager();
JavaTypeMapping mapping = mapMgr.getMapping(String.class);
mapping.setMemberMetaData(mmd);
mapping.setTable(table);
mapping.setRoleForMember(roleForMember);
Column col = mapMgr.createColumn(mapping, String.class.getName(), 0);
mapMgr.createDatastoreMapping(mapping, mmd, 0, col);
this.addJavaTypeMapping(mapping);
}
}
use of org.datanucleus.metadata.ColumnMetaData in project datanucleus-rdbms by datanucleus.
the class ReferenceMapping method createPerImplementationColumnsForReferenceField.
/**
* Create columns for reference (Interface/Object) fields on a per-implementation basis.
* This call ColumnCreator.createColumnsForField for each implementation class of the reference.
*/
void createPerImplementationColumnsForReferenceField(boolean pk, boolean nullable, boolean serialised, boolean embedded, FieldRole fieldRole, ColumnMetaData[] columnMetaData, ClassLoaderResolver clr) {
if (this instanceof InterfaceMapping && mmd.hasExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES)) {
// Store the implementation-classes with the mapping (persistent interfaces?)
((InterfaceMapping) this).setImplementationClasses(mmd.getValueForExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES));
}
// Find the available implementations that we are creating columns for
String[] implTypes = null;
try {
implTypes = MetaDataUtils.getInstance().getImplementationNamesForReferenceField(mmd, fieldRole, clr, storeMgr.getMetaDataManager());
} catch (NucleusUserException nue) {
// No implementation classes found, so log warning and return
if (storeMgr.getBooleanProperty(PropertyNames.PROPERTY_STORE_ALLOW_REFS_WITHOUT_IMPLS, false)) {
NucleusLogger.DATASTORE_SCHEMA.warn("Possible problem encountered while adding columns for field " + mmd.getFullFieldName() + " : " + nue.getMessage());
return;
}
throw nue;
}
// Set the PK and nullability of column(s) for the implementations (based on the number of impls etc)
if (implTypes.length > 1) {
// Cannot be part of PK if more than 1 implementation
pk = false;
}
if (implTypes.length > 1 && !pk) {
// Must be nullable if more than 1 impl (since only 1 impl can have value at a time)
nullable = true;
}
// Create list of classes that require columns.
// We only add columns for the implementation that is the root of a particular inheritance tree
// e.g if we have A implements I1, and B extends A then they both are valid implementations
// but we only want to create column(s) for A.
Collection implClasses = new ArrayList();
for (int i = 0; i < implTypes.length; i++) {
Class type = clr.classForName(implTypes[i]);
if (type == null) {
throw new NucleusUserException(Localiser.msg("020189", mmd.getTypeName(), implTypes[i]));
} else if (type.isInterface()) {
throw new NucleusUserException(Localiser.msg("020190", mmd.getFullFieldName(), mmd.getTypeName(), implTypes[i]));
}
Iterator iter = implClasses.iterator();
boolean toBeAdded = true;
Class clsToSwap = null;
while (iter.hasNext()) {
Class cls = (Class) iter.next();
if (cls == type) {
// Implementation already present
toBeAdded = false;
break;
}
if (type.isAssignableFrom(cls)) {
// "type" is superclass of "cls" so swap subclass for this class
clsToSwap = cls;
toBeAdded = false;
break;
} else if (cls.isAssignableFrom(type)) {
toBeAdded = false;
break;
}
}
if (toBeAdded) {
implClasses.add(type);
} else if (clsToSwap != null) {
implClasses.remove(clsToSwap);
implClasses.add(type);
}
}
// Add columns for each of these implementations
int colPos = 0;
Iterator implClsIter = implClasses.iterator();
while (implClsIter.hasNext()) {
Class implClass = (Class) implClsIter.next();
boolean present = false;
int numJavaTypeMappings = getJavaTypeMapping().length;
for (int i = 0; i < numJavaTypeMappings; i++) {
JavaTypeMapping implMapping = getJavaTypeMapping()[i];
if (implClass.getName().equals(implMapping.getType())) {
present = true;
}
}
if (present) {
// Implementation already present in mapping (e.g reinitialising) so skip this
continue;
}
String fieldTypeName = getReferenceFieldType(fieldRole);
boolean isPersistentInterfaceField = storeMgr.getNucleusContext().getMetaDataManager().isPersistentInterface(fieldTypeName);
boolean columnsNeeded = true;
if (isPersistentInterfaceField && !storeMgr.getNucleusContext().getMetaDataManager().isPersistentInterfaceImplementation(fieldTypeName, implClass.getName())) {
// We have a "persistent-interface" field yet this is not a generated implementation so ignore it
// It is arguable if we should allow the real implementations of this interface here, but the JDO2 TCK doesn't
// make that assumption so we don't either
columnsNeeded = false;
}
if (columnsNeeded) {
// Get the mapping for this implementation
JavaTypeMapping m;
if (storeMgr.getMappingManager().isSupportedMappedType(implClass.getName())) {
m = storeMgr.getMappingManager().getMapping(implClass, serialised, embedded, mmd.getFullFieldName());
} else {
try {
DatastoreClass dc = storeMgr.getDatastoreClass(implClass.getName(), clr);
m = dc.getIdMapping();
} catch (NoTableManagedException ex) {
// TODO Localise this message
throw new NucleusUserException("Cannot define columns for " + mmd.getFullFieldName() + " due to " + ex.getMessage(), ex);
}
}
ColumnMetaData[] columnMetaDataForType = null;
if (columnMetaData != null && columnMetaData.length > 0) {
if (columnMetaData.length < colPos + m.getNumberOfDatastoreMappings()) {
throw new NucleusUserException(Localiser.msg("020186", mmd.getFullFieldName(), "" + columnMetaData.length, "" + (colPos + m.getNumberOfDatastoreMappings())));
}
columnMetaDataForType = new ColumnMetaData[m.getNumberOfDatastoreMappings()];
System.arraycopy(columnMetaData, colPos, columnMetaDataForType, 0, columnMetaDataForType.length);
colPos += columnMetaDataForType.length;
}
// Create the FK column(s) for this implementation
ColumnCreator.createColumnsForField(implClass, this, table, storeMgr, mmd, pk, nullable, serialised, embedded, fieldRole, columnMetaDataForType, clr, true, null);
if (NucleusLogger.DATASTORE.isInfoEnabled()) {
NucleusLogger.DATASTORE.info(Localiser.msg("020188", implClass, mmd.getName()));
}
}
}
}
Aggregations