Search in sources :

Example 6 with MapMetaData

use of org.datanucleus.metadata.MapMetaData in project datanucleus-rdbms by datanucleus.

the class MapValueMethod method getAsSubquery.

/**
 * Implementation of VALUE(map) using a subquery on the table representing the map, returning the value.
 * @param stmt SQLStatement
 * @param mapExpr The map expression
 * @return The value expression
 */
protected SQLExpression getAsSubquery(SQLStatement stmt, MapExpression mapExpr) {
    AbstractMemberMetaData mmd = mapExpr.getJavaTypeMapping().getMemberMetaData();
    MapMetaData mapmd = mmd.getMap();
    RDBMSStoreManager storeMgr = stmt.getRDBMSManager();
    ClassLoaderResolver clr = stmt.getQueryGenerator().getClassLoaderResolver();
    JavaTypeMapping ownerMapping = null;
    JavaTypeMapping valMapping = null;
    Table mapTbl = null;
    if (mapmd.getMapType() == MapType.MAP_TYPE_JOIN) {
        // JoinTable
        mapTbl = storeMgr.getTable(mmd);
        ownerMapping = ((MapTable) mapTbl).getOwnerMapping();
        valMapping = ((MapTable) mapTbl).getValueMapping();
    } else if (mapmd.getMapType() == MapType.MAP_TYPE_KEY_IN_VALUE) {
        // ForeignKey from value table to key
        AbstractClassMetaData valCmd = mapmd.getValueClassMetaData(clr);
        mapTbl = storeMgr.getDatastoreClass(mmd.getMap().getValueType(), clr);
        if (mmd.getMappedBy() != null) {
            ownerMapping = mapTbl.getMemberMapping(valCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = ((DatastoreClass) mapTbl).getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        valMapping = mapTbl.getIdMapping();
    } else if (mapmd.getMapType() == MapType.MAP_TYPE_VALUE_IN_KEY) {
        // ForeignKey from key table to value
        AbstractClassMetaData keyCmd = mapmd.getKeyClassMetaData(clr);
        mapTbl = storeMgr.getDatastoreClass(mmd.getMap().getKeyType(), clr);
        if (mmd.getMappedBy() != null) {
            ownerMapping = mapTbl.getMemberMapping(keyCmd.getMetaDataForMember(mmd.getMappedBy()));
        } else {
            ownerMapping = ((DatastoreClass) mapTbl).getExternalMapping(mmd, MappingType.EXTERNAL_FK);
        }
        String valFieldName = mmd.getValueMetaData().getMappedBy();
        AbstractMemberMetaData keyValMmd = keyCmd.getMetaDataForMember(valFieldName);
        valMapping = mapTbl.getMemberMapping(keyValMmd);
    } else {
        throw new NucleusException("Invalid map for " + mapExpr + " in get() call");
    }
    SQLExpressionFactory exprFactory = stmt.getSQLExpressionFactory();
    SelectStatement subStmt = new SelectStatement(stmt, storeMgr, mapTbl, null, null);
    subStmt.setClassLoaderResolver(clr);
    SQLExpression valExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), valMapping);
    subStmt.select(valExpr, null);
    // Link to primary statement
    SQLExpression elementOwnerExpr = exprFactory.newExpression(subStmt, subStmt.getPrimaryTable(), ownerMapping);
    SQLExpression ownerIdExpr = exprFactory.newExpression(stmt, mapExpr.getSQLTable(), mapExpr.getSQLTable().getTable().getIdMapping());
    subStmt.whereAnd(elementOwnerExpr.eq(ownerIdExpr), true);
    SubqueryExpression subExpr = new SubqueryExpression(stmt, subStmt);
    subExpr.setJavaTypeMapping(valMapping);
    return subExpr;
}
Also used : Table(org.datanucleus.store.rdbms.table.Table) MapTable(org.datanucleus.store.rdbms.table.MapTable) SQLTable(org.datanucleus.store.rdbms.sql.SQLTable) SQLExpressionFactory(org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory) SQLExpression(org.datanucleus.store.rdbms.sql.expression.SQLExpression) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) MapMetaData(org.datanucleus.metadata.MapMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RDBMSStoreManager(org.datanucleus.store.rdbms.RDBMSStoreManager) SubqueryExpression(org.datanucleus.store.rdbms.sql.expression.SubqueryExpression) SelectStatement(org.datanucleus.store.rdbms.sql.SelectStatement) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 7 with MapMetaData

use of org.datanucleus.metadata.MapMetaData in project datanucleus-rdbms by datanucleus.

the class MapTable method initialize.

/**
 * Method to initialise the table definition.
 * @param clr The ClassLoaderResolver
 */
public void initialize(ClassLoaderResolver clr) {
    assertIsUninitialized();
    MapMetaData mapmd = mmd.getMap();
    if (mapmd == null) {
        throw new NucleusUserException(Localiser.msg("057017", mmd));
    }
    PrimaryKeyMetaData pkmd = (mmd.getJoinMetaData() != null ? mmd.getJoinMetaData().getPrimaryKeyMetaData() : null);
    boolean pkColsSpecified = (pkmd != null && pkmd.getColumnMetaData() != null);
    boolean pkRequired = requiresPrimaryKey();
    // Add owner mapping
    ColumnMetaData[] ownerColmd = null;
    if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getColumnMetaData() != null && mmd.getJoinMetaData().getColumnMetaData().length > 0) {
        // Column mappings defined at this side (1-N, M-N)
        // When specified at this side they use the <join> tag
        ownerColmd = mmd.getJoinMetaData().getColumnMetaData();
    }
    ownerMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(ownerType), mmd, ownerColmd, storeMgr, this, pkRequired, false, FieldRole.ROLE_OWNER, clr, null);
    if (NucleusLogger.DATASTORE.isDebugEnabled()) {
        logMapping(mmd.getFullFieldName() + ".[OWNER]", ownerMapping);
    }
    String keyValueFieldName = (mmd.getKeyMetaData() != null ? mmd.getKeyMetaData().getMappedBy() : null);
    String valueKeyFieldName = (mmd.getValueMetaData() != null ? mmd.getValueMetaData().getMappedBy() : null);
    // Add key mapping
    boolean keyPC = (mmd.hasMap() && mmd.getMap().keyIsPersistent());
    Class keyCls = clr.classForName(mapmd.getKeyType());
    if (keyValueFieldName != null && isEmbeddedValuePC()) {
    // Added in value code
    } else if (isSerialisedKey() || isEmbeddedKeyPC() || (isEmbeddedKey() && !keyPC) || ClassUtils.isReferenceType(keyCls)) {
        // Key = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
        keyMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_KEY);
        if (Boolean.TRUE.equals(mmd.getContainer().allowNulls())) {
            // Make all key col(s) nullable so we can store null elements
            for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
                Column elementCol = keyMapping.getDatastoreMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[KEY]", keyMapping);
        }
        if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
            // Key (PC) is embedded and value is a field of the key
            EmbeddedKeyPCMapping embMapping = (EmbeddedKeyPCMapping) keyMapping;
            valueMapping = embMapping.getJavaTypeMapping(valueKeyFieldName);
        }
    } else {
        // Key = PC
        ColumnMetaData[] keyColmd = 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)
            keyColmd = keymd.getColumnMetaData();
        }
        keyMapping = ColumnCreator.createColumnsForJoinTables(keyCls, mmd, keyColmd, storeMgr, this, false, false, FieldRole.ROLE_MAP_KEY, clr, null);
        if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
            // Make all key col(s) nullable so we can store null elements
            for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
                Column elementCol = keyMapping.getDatastoreMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[KEY]", keyMapping);
        }
    }
    // Add value mapping
    boolean valuePC = (mmd.hasMap() && mmd.getMap().valueIsPersistent());
    Class valueCls = clr.classForName(mapmd.getValueType());
    if (valueKeyFieldName != null && isEmbeddedKeyPC()) {
    // Added in key code
    } else if (isSerialisedValue() || isEmbeddedValuePC() || (isEmbeddedValue() && !valuePC) || ClassUtils.isReferenceType(valueCls)) {
        // Value = PC(embedded), PC(serialised), Non-PC(serialised), Non-PC(embedded), Reference
        valueMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_MAP_VALUE);
        if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
            // Make all value col(s) nullable so we can store null elements
            for (int i = 0; i < valueMapping.getNumberOfDatastoreMappings(); i++) {
                Column elementCol = valueMapping.getDatastoreMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[VALUE]", valueMapping);
        }
        if (keyValueFieldName != null && isEmbeddedValuePC()) {
            // Value (PC) is embedded and key is a field of the value
            EmbeddedValuePCMapping embMapping = (EmbeddedValuePCMapping) valueMapping;
            keyMapping = embMapping.getJavaTypeMapping(keyValueFieldName);
        }
    } else {
        // Value = PC
        ColumnMetaData[] valueColmd = 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)
            valueColmd = valuemd.getColumnMetaData();
        }
        valueMapping = ColumnCreator.createColumnsForJoinTables(clr.classForName(mapmd.getValueType()), mmd, valueColmd, storeMgr, this, false, true, FieldRole.ROLE_MAP_VALUE, clr, null);
        if (mmd.getContainer().allowNulls() == Boolean.TRUE) {
            // Make all value col(s) nullable so we can store null elements
            for (int i = 0; i < valueMapping.getNumberOfDatastoreMappings(); i++) {
                Column elementCol = valueMapping.getDatastoreMapping(i).getColumn();
                elementCol.setNullable(true);
            }
        }
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[VALUE]", valueMapping);
        }
    }
    // Add order mapping if required
    boolean orderRequired = false;
    if (mmd.getOrderMetaData() != null) {
        // User requested order column so add one
        orderRequired = true;
    } else if (requiresPrimaryKey() && !pkColsSpecified) {
        // PK is required so maybe need to add an index to form the PK
        if (isEmbeddedKeyPC()) {
            if (mmd.hasExtension("surrogate-pk-column") && mmd.getValueForExtension("surrogate-pk-column").equalsIgnoreCase("true")) {
                // Allow user to request surrogate pk column be added (for use with JPA)
                orderRequired = true;
            } else if (storeMgr.getApiAdapter().getName().equalsIgnoreCase("JDO") && mmd.getMap().getKeyClassMetaData(clr).getIdentityType() != IdentityType.APPLICATION) {
                // Embedded key PC with datastore id so we need an index to form the PK TODO It is arguable that we can just use all embedded key fields as part of PK here always
                orderRequired = true;
            }
        } else if (isSerialisedKey()) {
            // Serialised key, so need an index to form the PK
            orderRequired = true;
        } else if (keyMapping instanceof ReferenceMapping) {
            // ReferenceMapping, so have order if more than 1 implementation
            ReferenceMapping refMapping = (ReferenceMapping) keyMapping;
            if (refMapping.getJavaTypeMapping().length > 1) {
                orderRequired = true;
            }
        } else if (!(keyMapping instanceof PersistableMapping)) {
            // Non-PC, so depends if the key column can be used as part of a PK
            // TODO This assumes the keyMapping has a single column but what if it is Color with 4 cols?
            Column elementCol = keyMapping.getDatastoreMapping(0).getColumn();
            if (!storeMgr.getDatastoreAdapter().isValidPrimaryKeyType(elementCol.getJdbcType())) {
                // Not possible to use this Non-PC type as part of the PK
                orderRequired = true;
            }
        }
    }
    if (orderRequired) {
        // Order/Adapter (index) column is required (integer based)
        ColumnMetaData orderColmd = null;
        if (mmd.getOrderMetaData() != null && mmd.getOrderMetaData().getColumnMetaData() != null && mmd.getOrderMetaData().getColumnMetaData().length > 0) {
            // Specified "order" column info
            orderColmd = mmd.getOrderMetaData().getColumnMetaData()[0];
            if (orderColmd.getName() == null) {
                // No column name so use default
                orderColmd = new ColumnMetaData(orderColmd);
                DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
                orderColmd.setName(id.getName());
            }
        } else {
            // No column name so use default
            DatastoreIdentifier id = storeMgr.getIdentifierFactory().newIndexFieldIdentifier(mmd);
            orderColmd = new ColumnMetaData();
            orderColmd.setName(id.getName());
        }
        // JDO2 spec [18.5] order column is assumed to be "int"
        orderMapping = storeMgr.getMappingManager().getMapping(int.class);
        ColumnCreator.createIndexColumn(orderMapping, storeMgr, clr, this, orderColmd, pkRequired && !pkColsSpecified);
        if (NucleusLogger.DATASTORE.isDebugEnabled()) {
            logMapping(mmd.getFullFieldName() + ".[ORDER]", orderMapping);
        }
    }
    // Define primary key of the join table (if any)
    if (pkRequired) {
        if (pkColsSpecified) {
            // Apply the users PK specification
            applyUserPrimaryKeySpecification(pkmd);
        } else {
            // Define PK using internal rules
            if (orderRequired) {
                // Order column specified so owner+order are the PK
                orderMapping.getDatastoreMapping(0).getColumn().setPrimaryKey();
            } else {
                // No order column specified so owner+key are the PK
                for (int i = 0; i < keyMapping.getNumberOfDatastoreMappings(); i++) {
                    keyMapping.getDatastoreMapping(i).getColumn().setPrimaryKey();
                }
            }
        }
    }
    if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled()) {
        NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("057023", this));
    }
    storeMgr.registerTableInitialized(this);
    state = TABLE_STATE_INITIALIZED;
}
Also used : KeyMetaData(org.datanucleus.metadata.KeyMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedValuePCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedValuePCMapping) MapMetaData(org.datanucleus.metadata.MapMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) ReferenceMapping(org.datanucleus.store.rdbms.mapping.java.ReferenceMapping) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) ValueMetaData(org.datanucleus.metadata.ValueMetaData) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) EmbeddedKeyPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedKeyPCMapping)

Example 8 with MapMetaData

use of org.datanucleus.metadata.MapMetaData in project datanucleus-api-jdo by datanucleus.

the class JDOAnnotationReader method processMemberAnnotations.

/**
 * Convenience method to process the annotations for a field/property. The passed annotations may have been specified on the field or on the getter methods.
 * @param cmd The ClassMetaData/InterfaceMetaData to update
 * @param member The field/property
 * @param annotations Annotations for the field/property
 * @return The FieldMetaData/PropertyMetaData that was added (if any)
 */
protected AbstractMemberMetaData processMemberAnnotations(AbstractClassMetaData cmd, Member member, AnnotationObject[] annotations) {
    if (annotations == null || annotations.length == 0) {
        return null;
    }
    AbstractMemberMetaData mmd = null;
    boolean primaryKey = false;
    boolean serialised = false;
    boolean embeddedMember = false;
    boolean nonPersistentField = false;
    boolean transactionalField = false;
    String cacheable = null;
    Class[] elementTypes = null;
    String embeddedElement = null;
    String serializedElement = null;
    String dependentElement = null;
    Class[] keyTypes = null;
    String embeddedKey = null;
    String serializedKey = null;
    String dependentKey = null;
    Class[] valueTypes = null;
    String embeddedValue = null;
    String serializedValue = null;
    String dependentValue = null;
    String embeddedOwnerField = null;
    String embeddedNullIndicatorColumn = null;
    String embeddedNullIndicatorValue = null;
    Persistent[] embeddedMembers = null;
    Persistent[] embeddedElementMembers = null;
    Persistent[] embeddedKeyMembers = null;
    Persistent[] embeddedValueMembers = null;
    ColumnMetaData[] colmds = null;
    JoinMetaData joinmd = null;
    ElementMetaData elemmd = null;
    KeyMetaData keymd = null;
    ValueMetaData valuemd = null;
    OrderMetaData ordermd = null;
    IndexMetaData idxmd = null;
    UniqueMetaData unimd = null;
    ForeignKeyMetaData fkmd = null;
    Map<String, String> extensions = null;
    Class convertConverterCls = null;
    for (AnnotationObject annotation : annotations) {
        String annName = annotation.getName();
        Map<String, Object> annotationValues = annotation.getNameValueMap();
        if (annName.equals(JDOAnnotationUtils.PERSISTENT)) {
            String pkStr = "" + annotationValues.get("primaryKey");
            Boolean pk = null;
            if (!StringUtils.isWhitespace(pkStr)) {
                pk = Boolean.valueOf(pkStr);
            }
            String dfgStr = (String) annotationValues.get("defaultFetchGroup");
            Boolean dfg = null;
            if (!StringUtils.isWhitespace(dfgStr)) {
                dfg = Boolean.valueOf(dfgStr);
            }
            String nullValue = JDOAnnotationUtils.getNullValueString((NullValue) annotationValues.get("nullValue"));
            String embStr = (String) annotationValues.get("embedded");
            Boolean embedded = null;
            if (!StringUtils.isWhitespace(embStr)) {
                embedded = Boolean.valueOf(embStr);
            }
            String serStr = (String) annotationValues.get("serialized");
            Boolean serialized = null;
            if (!StringUtils.isWhitespace(serStr)) {
                serialized = Boolean.valueOf(serStr);
            }
            String depStr = (String) annotationValues.get("dependent");
            Boolean dependent = null;
            if (!StringUtils.isWhitespace(depStr)) {
                dependent = Boolean.valueOf(depStr);
            }
            String valueStrategy = JDOAnnotationUtils.getValueGenerationStrategyString((IdGeneratorStrategy) annotationValues.get("valueStrategy"));
            String customValueStrategy = (String) annotationValues.get("customValueStrategy");
            if (!StringUtils.isWhitespace(customValueStrategy)) {
                // User has provided an extension strategy
                valueStrategy = customValueStrategy;
            }
            FieldPersistenceModifier modifier = JDOAnnotationUtils.getFieldPersistenceModifier((PersistenceModifier) annotationValues.get("persistenceModifier"));
            if (modifier == null) {
                modifier = FieldPersistenceModifier.PERSISTENT;
            }
            String sequence = (String) annotationValues.get("sequence");
            String mappedBy = (String) annotationValues.get("mappedBy");
            String table = (String) annotationValues.get("table");
            String column = (String) annotationValues.get("column");
            String loadFetchGroup = (String) annotationValues.get("loadFetchGroup");
            String fieldTypeName = null;
            int recursionDepth = ((Integer) annotationValues.get("recursionDepth")).intValue();
            cacheable = (String) annotationValues.get("cacheable");
            Class[] fieldTypes = (Class[]) annotationValues.get("types");
            if (fieldTypes != null && fieldTypes.length > 0) {
                StringBuilder typeStr = new StringBuilder();
                for (Class fieldType : fieldTypes) {
                    if (typeStr.length() > 0) {
                        typeStr.append(',');
                    }
                    if (fieldType != null && fieldType != void.class) {
                        typeStr.append(fieldType.getName());
                    }
                }
                fieldTypeName = typeStr.toString();
            }
            dependentElement = (String) annotationValues.get("dependentElement");
            serializedElement = (String) annotationValues.get("serializedElement");
            embeddedElement = (String) annotationValues.get("embeddedElement");
            dependentKey = (String) annotationValues.get("dependentKey");
            serializedKey = (String) annotationValues.get("serializedKey");
            embeddedKey = (String) annotationValues.get("embeddedKey");
            dependentValue = (String) annotationValues.get("dependentValue");
            serializedValue = (String) annotationValues.get("serializedValue");
            embeddedValue = (String) annotationValues.get("embeddedValue");
            Class converterCls = (Class) annotationValues.get("converter");
            if (converterCls == UseDefault.class) {
                converterCls = null;
            }
            Boolean disableConversion = (Boolean) annotationValues.get("useDefaultConversion");
            mmd = member.isProperty() ? new PropertyMetaData(cmd, member.getName()) : new FieldMetaData(cmd, member.getName());
            if (isPersistenceContext()) {
                if (disableConversion != null && disableConversion) {
                    mmd.setTypeConverterDisabled();
                } else if (converterCls != null) {
                    TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                    if (typeMgr.getTypeConverterForName(converterCls.getName()) == null) {
                        // Not yet cached an instance of this converter so create one
                        AttributeConverter conv = JDOTypeConverterUtils.createAttributeConverter((PersistenceNucleusContext) mmgr.getNucleusContext(), converterCls);
                        Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, member.getType());
                        Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                        // Register the TypeConverter under the name of the AttributeConverter class
                        JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                        typeMgr.registerConverter(converterCls.getName(), typeConv, attrType, dbType, false, null);
                    }
                    mmd.setTypeConverterName(converterCls.getName());
                }
            }
            if (modifier != null) {
                mmd.setPersistenceModifier(modifier);
            }
            if (dfg != null) {
                mmd.setDefaultFetchGroup(dfg);
            }
            if (pk != null) {
                mmd.setPrimaryKey(pk);
            }
            if (embedded != null) {
                mmd.setEmbedded(embedded);
            }
            if (serialized != null) {
                mmd.setSerialised(serialized);
            }
            if (dependent != null) {
                mmd.setDependent(dependent);
            }
            mmd.setNullValue(org.datanucleus.metadata.NullValue.getNullValue(nullValue));
            mmd.setMappedBy(mappedBy);
            mmd.setColumn(column);
            mmd.setTable(table);
            mmd.setRecursionDepth(recursionDepth);
            mmd.setLoadFetchGroup(loadFetchGroup);
            mmd.setValueStrategy(valueStrategy);
            mmd.setSequence(sequence);
            mmd.setFieldTypes(fieldTypeName);
            // Add any columns defined on the @Persistent
            Column[] columns = (Column[]) annotationValues.get("columns");
            if (columns != null && columns.length > 0) {
                for (Column col : columns) {
                    mmd.addColumn(JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(col));
                }
            }
            JDOAnnotationUtils.addExtensionsToMetaData(mmd, (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.PRIMARY_KEY)) {
            primaryKey = true;
            if (cmd.getIdentityType() == IdentityType.DATASTORE) {
                // ClassMetaData was created as DATASTORE so change it to APPLICATION
                cmd.setIdentityType(IdentityType.APPLICATION);
            }
        } else if (annName.equals(JDOAnnotationUtils.SERIALIZED)) {
            serialised = true;
        } else if (annName.equals(JDOAnnotationUtils.NOTPERSISTENT)) {
            nonPersistentField = true;
        } else if (annName.equals(JDOAnnotationUtils.TRANSACTIONAL)) {
            transactionalField = true;
        } else if (annName.equals(JDOAnnotationUtils.COLUMNS)) {
            // Multiple column specification
            Column[] cols = (Column[]) annotationValues.get("value");
            if (cols != null && cols.length > 0) {
                colmds = new ColumnMetaData[cols.length];
                for (int j = 0; j < cols.length; j++) {
                    colmds[j] = JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(cols[j]);
                    JDOAnnotationUtils.addExtensionsToMetaData(colmds[j], cols[j].extensions());
                }
            }
        } else if (annName.equals(JDOAnnotationUtils.COLUMN)) {
            // Single column specification
            colmds = new ColumnMetaData[1];
            colmds[0] = JDOAnnotationUtils.getColumnMetaDataForAnnotations(annotationValues);
            JDOAnnotationUtils.addExtensionsToMetaData(colmds[0], (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.JOIN)) {
            String joinColumn = (String) annotationValues.get("column");
            String joinOuter = (String) annotationValues.get("outer");
            String deleteAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("deleteAction"));
            String pkName = (String) annotationValues.get("primaryKey");
            String fkName = (String) annotationValues.get("foreignKey");
            String generateFK = (String) annotationValues.get("generateForeignKey");
            String indexed = (String) annotationValues.get("indexed");
            String indexName = (String) annotationValues.get("index");
            String unique = (String) annotationValues.get("unique");
            String uniqueName = (String) annotationValues.get("uniqueKey");
            String generatePK = (String) annotationValues.get("generatePrimaryKey");
            if (!StringUtils.isWhitespace(uniqueName)) {
                unique = "true";
            }
            if (!StringUtils.isWhitespace(indexName)) {
                indexed = "true";
            }
            Column[] joinColumns = (Column[]) annotationValues.get("columns");
            joinmd = new JoinMetaData();
            joinmd.setColumnName(joinColumn);
            joinmd.setOuter(MetaDataUtils.getBooleanForString(joinOuter, false));
            joinmd.setIndexed(IndexedValue.getIndexedValue(indexed));
            joinmd.setUnique(unique);
            joinmd.setDeleteAction(deleteAction);
            if (!StringUtils.isWhitespace(pkName)) {
                PrimaryKeyMetaData pkmd = new PrimaryKeyMetaData();
                pkmd.setName(pkName);
                joinmd.setPrimaryKeyMetaData(pkmd);
            } else if (generatePK != null && generatePK.equalsIgnoreCase("true")) {
                joinmd.setPrimaryKeyMetaData(new PrimaryKeyMetaData());
            }
            if (!StringUtils.isWhitespace(fkName)) {
                ForeignKeyMetaData joinFkmd = joinmd.getForeignKeyMetaData();
                if (joinFkmd == null) {
                    joinFkmd = new ForeignKeyMetaData();
                    joinFkmd.setName(fkName);
                    joinmd.setForeignKeyMetaData(joinFkmd);
                } else {
                    joinFkmd.setName(fkName);
                }
            } else if (generateFK != null && generateFK.equalsIgnoreCase("true")) {
                joinmd.setForeignKeyMetaData(new ForeignKeyMetaData());
            }
            if (!StringUtils.isWhitespace(indexName)) {
                IndexMetaData joinIdxmd = joinmd.getIndexMetaData();
                if (joinIdxmd == null) {
                    joinIdxmd = new IndexMetaData();
                    joinmd.setIndexMetaData(joinIdxmd);
                }
                joinIdxmd.setName(indexName);
            }
            if (!StringUtils.isWhitespace(uniqueName)) {
                UniqueMetaData joinUnimd = joinmd.getUniqueMetaData();
                if (joinUnimd == null) {
                    joinUnimd = new UniqueMetaData();
                    joinmd.setUniqueMetaData(joinUnimd);
                }
                joinUnimd.setName(uniqueName);
            }
            if (joinColumns != null && joinColumns.length > 0) {
                for (Column joinCol : joinColumns) {
                    joinmd.addColumn(JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(joinCol));
                }
            }
            JDOAnnotationUtils.addExtensionsToMetaData(joinmd, (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.ELEMENT)) {
            // Element of a Collection/Array
            elementTypes = (Class[]) annotationValues.get("types");
            embeddedElement = (String) annotationValues.get("embedded");
            serializedElement = (String) annotationValues.get("serialized");
            dependentElement = (String) annotationValues.get("dependent");
            String elementDeleteAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("deleteAction"));
            String elementUpdateAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("updateAction"));
            String fkName = (String) annotationValues.get("foreignKey");
            String generateFK = (String) annotationValues.get("generateForeignKey");
            String indexed = (String) annotationValues.get("indexed");
            String indexName = (String) annotationValues.get("index");
            String unique = (String) annotationValues.get("unique");
            String uniqueName = (String) annotationValues.get("uniqueKey");
            Class converterCls = (Class) annotationValues.get("converter");
            if (converterCls == UseDefault.class) {
                converterCls = null;
            }
            Boolean disableConversion = (Boolean) annotationValues.get("useDefaultConversion");
            if (!StringUtils.isWhitespace(uniqueName)) {
                unique = "true";
            }
            if (!StringUtils.isWhitespace(indexName)) {
                indexed = "true";
            }
            elemmd = new ElementMetaData();
            elemmd.setTable((String) annotationValues.get("table"));
            elemmd.setColumnName((String) annotationValues.get("column"));
            elemmd.setDeleteAction(elementDeleteAction);
            elemmd.setUpdateAction(elementUpdateAction);
            elemmd.setIndexed(IndexedValue.getIndexedValue(indexed));
            elemmd.setUnique(MetaDataUtils.getBooleanForString(unique, false));
            elemmd.setMappedBy((String) annotationValues.get("mappedBy"));
            if (!StringUtils.isWhitespace(fkName)) {
                ForeignKeyMetaData elemFkmd = elemmd.getForeignKeyMetaData();
                if (elemFkmd == null) {
                    elemFkmd = new ForeignKeyMetaData();
                    elemFkmd.setName(fkName);
                    elemmd.setForeignKeyMetaData(elemFkmd);
                } else {
                    elemFkmd.setName(fkName);
                }
            } else if (generateFK != null && generateFK.equalsIgnoreCase("true")) {
                elemmd.setForeignKeyMetaData(new ForeignKeyMetaData());
            }
            if (!StringUtils.isWhitespace(indexName)) {
                IndexMetaData elemIdxmd = elemmd.getIndexMetaData();
                if (elemIdxmd == null) {
                    elemIdxmd = new IndexMetaData();
                    elemmd.setIndexMetaData(elemIdxmd);
                }
                elemIdxmd.setName(indexName);
            }
            if (!StringUtils.isWhitespace(uniqueName)) {
                UniqueMetaData elemUnimd = elemmd.getUniqueMetaData();
                if (elemUnimd == null) {
                    elemUnimd = new UniqueMetaData();
                    elemmd.setUniqueMetaData(elemUnimd);
                }
                elemUnimd.setName(uniqueName);
            }
            Column[] elementColumns = (Column[]) annotationValues.get("columns");
            if (elementColumns != null && elementColumns.length > 0) {
                for (Column elementCol : elementColumns) {
                    elemmd.addColumn(JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(elementCol));
                }
            }
            if (isPersistenceContext()) {
                if (disableConversion != null && disableConversion) {
                    elemmd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_DISABLED, "true");
                } else if (converterCls != null) {
                    TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                    if (typeMgr.getTypeConverterForName(converterCls.getName()) == null) {
                        // Not yet cached an instance of this converter so create one
                        AttributeConverter conv = JDOTypeConverterUtils.createAttributeConverter((PersistenceNucleusContext) mmgr.getNucleusContext(), converterCls);
                        Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, ClassUtils.getCollectionElementType(member.getType(), member.getGenericType()));
                        Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                        // Register the TypeConverter under the name of the AttributeConverter class
                        JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                        typeMgr.registerConverter(converterCls.getName(), typeConv, attrType, dbType, false, null);
                    }
                    elemmd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME, converterCls.getName());
                }
            }
            JDOAnnotationUtils.addExtensionsToMetaData(elemmd, (Extension[]) annotationValues.get("extensions"));
            Embedded[] embeddedMappings = (Embedded[]) annotationValues.get("embeddedMapping");
            if (embeddedMappings != null && embeddedMappings.length > 0) {
                // Embedded element
                EmbeddedMetaData embmd = new EmbeddedMetaData();
                embmd.setOwnerMember(embeddedMappings[0].ownerMember());
                embmd.setNullIndicatorColumn(embeddedMappings[0].nullIndicatorColumn());
                embmd.setNullIndicatorValue(embeddedMappings[0].nullIndicatorValue());
                try {
                    Discriminator disc = embeddedMappings[0].discriminatorColumnName();
                    if (disc != null) {
                        DiscriminatorMetaData dismd = embmd.newDiscriminatorMetadata();
                        dismd.setColumnName(disc.column());
                        dismd.setStrategy(JDOAnnotationUtils.getDiscriminatorStrategyString(disc.strategy()));
                    // TODO Support other attributes of discriminator?
                    }
                } catch (Throwable thr) {
                // Ignore this. Maybe not using JDO3.1 jar
                }
                elemmd.setEmbeddedMetaData(embmd);
                embeddedElementMembers = embeddedMappings[0].members();
            // Delay addition of embeddedElementMembers til completion of this loop so we have the
            // element type
            }
        } else if (annName.equals(JDOAnnotationUtils.KEY)) {
            // Key of a Map
            keyTypes = (Class[]) annotationValues.get("types");
            embeddedKey = (String) annotationValues.get("embedded");
            serializedKey = (String) annotationValues.get("serialized");
            dependentKey = (String) annotationValues.get("dependent");
            String keyDeleteAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("deleteAction"));
            String keyUpdateAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("updateAction"));
            String fkName = (String) annotationValues.get("foreignKey");
            String generateFK = (String) annotationValues.get("generateForeignKey");
            String indexed = (String) annotationValues.get("indexed");
            String indexName = (String) annotationValues.get("index");
            String unique = (String) annotationValues.get("unique");
            String uniqueName = (String) annotationValues.get("uniqueKey");
            Class converterCls = (Class) annotationValues.get("converter");
            if (converterCls == UseDefault.class) {
                converterCls = null;
            }
            Boolean disableConversion = (Boolean) annotationValues.get("useDefaultConversion");
            if (!StringUtils.isWhitespace(uniqueName)) {
                unique = "true";
            }
            if (!StringUtils.isWhitespace(indexName)) {
                indexed = "true";
            }
            keymd = new KeyMetaData();
            keymd.setTable((String) annotationValues.get("table"));
            keymd.setColumnName((String) annotationValues.get("column"));
            keymd.setDeleteAction(keyDeleteAction);
            keymd.setUpdateAction(keyUpdateAction);
            keymd.setIndexed(IndexedValue.getIndexedValue(indexed));
            keymd.setUnique(MetaDataUtils.getBooleanForString(unique, false));
            keymd.setMappedBy((String) annotationValues.get("mappedBy"));
            if (!StringUtils.isWhitespace(fkName)) {
                ForeignKeyMetaData keyFkmd = keymd.getForeignKeyMetaData();
                if (keyFkmd == null) {
                    keyFkmd = new ForeignKeyMetaData();
                    keyFkmd.setName(fkName);
                    keymd.setForeignKeyMetaData(keyFkmd);
                } else {
                    keyFkmd.setName(fkName);
                }
            } else if (generateFK != null && generateFK.equalsIgnoreCase("true")) {
                keymd.setForeignKeyMetaData(new ForeignKeyMetaData());
            }
            if (!StringUtils.isWhitespace(indexName)) {
                IndexMetaData keyIdxmd = keymd.getIndexMetaData();
                if (keyIdxmd == null) {
                    keyIdxmd = new IndexMetaData();
                    keymd.setIndexMetaData(keyIdxmd);
                }
                keyIdxmd.setName(indexName);
            }
            if (!StringUtils.isWhitespace(uniqueName)) {
                UniqueMetaData keyUnimd = keymd.getUniqueMetaData();
                if (keyUnimd == null) {
                    keyUnimd = new UniqueMetaData();
                    keymd.setUniqueMetaData(keyUnimd);
                }
                keyUnimd.setName(uniqueName);
            }
            Column[] keyColumns = (Column[]) annotationValues.get("columns");
            if (keyColumns != null && keyColumns.length > 0) {
                for (Column keyCol : keyColumns) {
                    keymd.addColumn(JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(keyCol));
                }
            }
            if (isPersistenceContext()) {
                if (disableConversion != null && disableConversion) {
                    keymd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_DISABLED, "true");
                } else if (converterCls != null) {
                    TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                    if (typeMgr.getTypeConverterForName(converterCls.getName()) == null) {
                        // Not yet cached an instance of this converter so create one
                        AttributeConverter conv = JDOTypeConverterUtils.createAttributeConverter((PersistenceNucleusContext) mmgr.getNucleusContext(), converterCls);
                        Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, ClassUtils.getMapKeyType(member.getType(), member.getGenericType()));
                        Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                        // Register the TypeConverter under the name of the AttributeConverter class
                        JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                        typeMgr.registerConverter(converterCls.getName(), typeConv, attrType, dbType, false, null);
                    }
                    keymd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME, converterCls.getName());
                }
            }
            JDOAnnotationUtils.addExtensionsToMetaData(keymd, (Extension[]) annotationValues.get("extensions"));
            Embedded[] embeddedMappings = (Embedded[]) annotationValues.get("embeddedMapping");
            if (embeddedMappings != null && embeddedMappings.length > 0) {
                // Embedded key
                EmbeddedMetaData embmd = new EmbeddedMetaData();
                embmd.setOwnerMember(embeddedMappings[0].ownerMember());
                embmd.setNullIndicatorColumn(embeddedMappings[0].nullIndicatorColumn());
                embmd.setNullIndicatorValue(embeddedMappings[0].nullIndicatorValue());
                keymd.setEmbeddedMetaData(embmd);
                embeddedKeyMembers = embeddedMappings[0].members();
            // Delay addition of embeddedKeyMembers til completion of this loop so we have the key
            // type
            }
        } else if (annName.equals(JDOAnnotationUtils.VALUE)) {
            // Value of a Map
            valueTypes = (Class[]) annotationValues.get("types");
            embeddedValue = (String) annotationValues.get("embedded");
            serializedValue = (String) annotationValues.get("serialized");
            dependentValue = (String) annotationValues.get("dependent");
            String valueDeleteAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("deleteAction"));
            String valueUpdateAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("updateAction"));
            String fkName = (String) annotationValues.get("foreignKey");
            String generateFK = (String) annotationValues.get("generateForeignKey");
            String indexed = (String) annotationValues.get("indexed");
            String indexName = (String) annotationValues.get("index");
            String unique = (String) annotationValues.get("unique");
            String uniqueName = (String) annotationValues.get("uniqueKey");
            Class converterCls = (Class) annotationValues.get("converter");
            if (converterCls == UseDefault.class) {
                converterCls = null;
            }
            Boolean disableConversion = (Boolean) annotationValues.get("useDefaultConversion");
            if (!StringUtils.isWhitespace(uniqueName)) {
                unique = "true";
            }
            if (!StringUtils.isWhitespace(indexName)) {
                indexed = "true";
            }
            valuemd = new ValueMetaData();
            valuemd.setTable((String) annotationValues.get("table"));
            valuemd.setColumnName((String) annotationValues.get("column"));
            valuemd.setDeleteAction(valueDeleteAction);
            valuemd.setUpdateAction(valueUpdateAction);
            valuemd.setIndexed(IndexedValue.getIndexedValue(indexed));
            valuemd.setUnique(MetaDataUtils.getBooleanForString(unique, false));
            valuemd.setMappedBy((String) annotationValues.get("mappedBy"));
            if (!StringUtils.isWhitespace(fkName)) {
                ForeignKeyMetaData valueFkmd = valuemd.getForeignKeyMetaData();
                if (valueFkmd == null) {
                    valueFkmd = new ForeignKeyMetaData();
                    valueFkmd.setName(fkName);
                    valuemd.setForeignKeyMetaData(valueFkmd);
                } else {
                    valueFkmd.setName(fkName);
                }
            } else if (generateFK != null && generateFK.equalsIgnoreCase("true")) {
                valuemd.setForeignKeyMetaData(new ForeignKeyMetaData());
            }
            if (!StringUtils.isWhitespace(indexName)) {
                IndexMetaData valueIdxmd = valuemd.getIndexMetaData();
                if (valueIdxmd == null) {
                    valueIdxmd = new IndexMetaData();
                    valuemd.setIndexMetaData(valueIdxmd);
                }
                valueIdxmd.setName(indexName);
            }
            if (!StringUtils.isWhitespace(uniqueName)) {
                UniqueMetaData valueUnimd = valuemd.getUniqueMetaData();
                if (valueUnimd == null) {
                    valueUnimd = new UniqueMetaData();
                    valuemd.setUniqueMetaData(valueUnimd);
                }
                valueUnimd.setName(uniqueName);
            }
            Column[] valueColumns = (Column[]) annotationValues.get("columns");
            if (valueColumns != null && valueColumns.length > 0) {
                for (Column valueCol : valueColumns) {
                    valuemd.addColumn(JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(valueCol));
                }
            }
            if (isPersistenceContext()) {
                if (disableConversion != null && disableConversion) {
                    valuemd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_DISABLED, "true");
                } else if (converterCls != null) {
                    TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                    if (typeMgr.getTypeConverterForName(converterCls.getName()) == null) {
                        // Not yet cached an instance of this converter so create one
                        AttributeConverter conv = JDOTypeConverterUtils.createAttributeConverter((PersistenceNucleusContext) mmgr.getNucleusContext(), converterCls);
                        Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, ClassUtils.getMapValueType(member.getType(), member.getGenericType()));
                        Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                        // Register the TypeConverter under the name of the AttributeConverter class
                        JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                        typeMgr.registerConverter(converterCls.getName(), typeConv, attrType, dbType, false, null);
                    }
                    valuemd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME, converterCls.getName());
                }
            }
            JDOAnnotationUtils.addExtensionsToMetaData(valuemd, (Extension[]) annotationValues.get("extensions"));
            Embedded[] embeddedMappings = (Embedded[]) annotationValues.get("embeddedMapping");
            if (embeddedMappings != null && embeddedMappings.length > 0) {
                // Embedded value
                EmbeddedMetaData embmd = new EmbeddedMetaData();
                embmd.setOwnerMember(embeddedMappings[0].ownerMember());
                embmd.setNullIndicatorColumn(embeddedMappings[0].nullIndicatorColumn());
                embmd.setNullIndicatorValue(embeddedMappings[0].nullIndicatorValue());
                valuemd.setEmbeddedMetaData(embmd);
                embeddedValueMembers = embeddedMappings[0].members();
            // Delay addition of embeddedValueMembers til completion of this loop so we have the value type
            }
        } else if (annName.equals(JDOAnnotationUtils.ORDER)) {
            ordermd = new OrderMetaData();
            ordermd.setColumnName((String) annotationValues.get("column"));
            ordermd.setMappedBy((String) annotationValues.get("mappedBy"));
            Column[] orderColumns = (Column[]) annotationValues.get("columns");
            if (orderColumns != null && orderColumns.length > 0) {
                for (Column orderCol : orderColumns) {
                    ordermd.addColumn(JDOAnnotationUtils.getColumnMetaDataForColumnAnnotation(orderCol));
                }
            }
            JDOAnnotationUtils.addExtensionsToMetaData(ordermd, (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.EMBEDDED)) {
            embeddedMember = true;
            embeddedOwnerField = (String) annotationValues.get("ownerMember");
            if (StringUtils.isWhitespace(embeddedOwnerField)) {
                embeddedOwnerField = null;
            }
            embeddedNullIndicatorColumn = (String) annotationValues.get("nullIndicatorColumn");
            if (StringUtils.isWhitespace(embeddedNullIndicatorColumn)) {
                embeddedNullIndicatorColumn = null;
            }
            embeddedNullIndicatorValue = (String) annotationValues.get("nullIndicatorValue");
            if (StringUtils.isWhitespace(embeddedNullIndicatorValue)) {
                embeddedNullIndicatorValue = null;
            }
            embeddedMembers = (Persistent[]) annotationValues.get("members");
            if (embeddedMembers != null && embeddedMembers.length == 0) {
                embeddedMembers = null;
            }
        // TODO Support discriminator
        } else if (annName.equals(JDOAnnotationUtils.INDEX)) {
            // Index for the field
            String name = (String) annotationValues.get("name");
            String table = (String) annotationValues.get("table");
            String unique = (String) annotationValues.get("unique");
            String[] members = (String[]) annotationValues.get("members");
            Column[] columns = (Column[]) annotationValues.get("columns");
            idxmd = JDOAnnotationUtils.getIndexMetaData(name, table, unique, members, columns);
            JDOAnnotationUtils.addExtensionsToMetaData(idxmd, (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.UNIQUE)) {
            // Unique for the field
            String name = (String) annotationValues.get("name");
            String table = (String) annotationValues.get("table");
            String deferred = (String) annotationValues.get("deferred");
            String[] members = (String[]) annotationValues.get("members");
            Column[] columns = (Column[]) annotationValues.get("columns");
            unimd = JDOAnnotationUtils.getUniqueMetaData(name, table, deferred, members, columns);
            JDOAnnotationUtils.addExtensionsToMetaData(unimd, (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.FOREIGNKEY)) {
            // ForeignKey for field
            String name = (String) annotationValues.get("name");
            String table = (String) annotationValues.get("table");
            String unique = (String) annotationValues.get("unique");
            String deferred = (String) annotationValues.get("deferred");
            String deleteAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("deleteAction"));
            String updateAction = JDOAnnotationUtils.getForeignKeyActionString((ForeignKeyAction) annotationValues.get("updateAction"));
            String[] members = (String[]) annotationValues.get("members");
            Column[] columns = (Column[]) annotationValues.get("columns");
            fkmd = JDOAnnotationUtils.getFKMetaData(name, table, unique, deferred, deleteAction, updateAction, members, columns);
            JDOAnnotationUtils.addExtensionsToMetaData(fkmd, (Extension[]) annotationValues.get("extensions"));
        } else if (annName.equals(JDOAnnotationUtils.CACHEABLE)) {
            String cache = (String) annotationValues.get("value");
            if (cache != null) {
                cacheable = cache;
            }
        } else if (annName.equals(JDOAnnotationUtils.CONVERT)) {
            convertConverterCls = (Class) annotationValues.get("value");
            if (convertConverterCls == UseDefault.class) {
                convertConverterCls = null;
            }
            Boolean enabled = (Boolean) annotationValues.get("enabled");
            if (!enabled) {
                convertConverterCls = null;
            }
        } else if (annName.equals(JDOAnnotationUtils.EXTENSIONS)) {
            Extension[] values = (Extension[]) annotationValues.get("value");
            if (values != null && values.length > 0) {
                extensions = new HashMap<String, String>(values.length);
                for (Extension ext : values) {
                    String vendorName = ext.vendorName();
                    if (StringUtils.isWhitespace(vendorName)) {
                        throw new InvalidMetaDataException("044160", vendorName, ext.key().toString(), ext.value().toString());
                    } else if (vendorName.equalsIgnoreCase(MetaData.VENDOR_NAME)) {
                        extensions.put(ext.key().toString(), ext.value().toString());
                    }
                }
            }
        } else if (annName.equals(JDOAnnotationUtils.EXTENSION)) {
            String vendorName = (String) annotationValues.get("vendorName");
            if (StringUtils.isWhitespace(vendorName)) {
                throw new InvalidMetaDataException("044160", vendorName, annotationValues.get("key"), annotationValues.get("value"));
            } else if (vendorName.equalsIgnoreCase(MetaData.VENDOR_NAME)) {
                extensions = new HashMap<String, String>(1);
                extensions.put((String) annotationValues.get("key"), (String) annotationValues.get("value"));
            }
        } else {
            NucleusLogger.METADATA.debug(Localiser.msg("044211", cmd.getFullClassName(), member.getName(), annotation.getName()));
        }
    }
    if (mmd == null && (transactionalField || nonPersistentField || primaryKey || colmds != null || serialised || embeddedOwnerField != null || embeddedNullIndicatorColumn != null || embeddedNullIndicatorValue != null || embeddedMembers != null || elemmd != null || keymd != null || valuemd != null || ordermd != null || idxmd != null || unimd != null || fkmd != null || joinmd != null || extensions != null || convertConverterCls != null)) {
        // @Persistent not supplied but other relevant annotations defined, so add default metadata element
        mmd = member.isProperty() ? new PropertyMetaData(cmd, member.getName()) : new FieldMetaData(cmd, member.getName());
        if (primaryKey) {
            mmd.setPersistenceModifier(FieldPersistenceModifier.PERSISTENT);
            mmd.setPrimaryKey(primaryKey);
        }
        if (serialised) {
            mmd.setPersistenceModifier(FieldPersistenceModifier.PERSISTENT);
        }
    }
    if (mmd != null) {
        cmd.addMember(mmd);
        if (primaryKey) {
            mmd.setPrimaryKey(true);
        }
        if (serialised) {
            mmd.setSerialised(true);
        }
        if (embeddedMember) {
            mmd.setEmbedded(true);
        }
        if (nonPersistentField) {
            mmd.setNotPersistent();
        }
        if (transactionalField) {
            mmd.setTransactional();
        }
        if (isPersistenceContext()) {
            if (convertConverterCls != null) {
                TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                if (typeMgr.getTypeConverterForName(convertConverterCls.getName()) == null) {
                    // Not yet cached an instance of this converter so create one
                    AttributeConverter conv = JDOTypeConverterUtils.createAttributeConverter((PersistenceNucleusContext) mmgr.getNucleusContext(), convertConverterCls);
                    Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(convertConverterCls, member.getType());
                    Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(convertConverterCls, attrType, null);
                    // Register the TypeConverter under the name of the AttributeConverter class
                    JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                    typeMgr.registerConverter(convertConverterCls.getName(), typeConv, attrType, dbType, false, null);
                }
                mmd.setTypeConverterName(convertConverterCls.getName());
            }
        }
        // Add any embedded info
        if (embeddedMember) {
            if (embeddedOwnerField != null || embeddedNullIndicatorColumn != null || embeddedNullIndicatorValue != null || embeddedMembers != null) {
                EmbeddedMetaData embmd = new EmbeddedMetaData();
                embmd.setOwnerMember(embeddedOwnerField);
                embmd.setNullIndicatorColumn(embeddedNullIndicatorColumn);
                embmd.setNullIndicatorValue(embeddedNullIndicatorValue);
                mmd.setEmbeddedMetaData(embmd);
                if (embeddedMembers != null && embeddedMembers.length > 0) {
                    for (Persistent embMember : embeddedMembers) {
                        // Add the metadata for the embedded field/property to the embedded metadata
                        String memberName = embMember.name();
                        if (memberName.indexOf('.') > 0) {
                            memberName = memberName.substring(memberName.lastIndexOf('.') + 1);
                        }
                        AbstractMemberMetaData embfmd = getFieldMetaDataForPersistent(embmd, embMember, isMemberOfClassAField(member.getType(), memberName));
                        embmd.addMember(embfmd);
                    }
                }
            }
        }
        TypeManager typeManager = mmgr.getNucleusContext().getTypeManager();
        ContainerHandler containerHandler = typeManager.getContainerHandler(member.getType());
        ContainerMetaData contmd = null;
        // If the field is a container then add its container element
        if (containerHandler != null) {
            contmd = containerHandler.newMetaData();
        }
        if (contmd instanceof CollectionMetaData) {
            Class collectionElementType = null;
            StringBuilder elementTypeStr = new StringBuilder();
            if (elementTypes != null && elementTypes.length > 0 && elementTypes[0] != void.class) {
                // User-specified element type(s)
                for (Class elementType : elementTypes) {
                    if (elementTypeStr.length() > 0) {
                        elementTypeStr.append(',');
                    }
                    elementTypeStr.append(elementType.getName());
                }
                // Use the first only
                collectionElementType = elementTypes[0];
            } else {
                // Try to derive element type from generics info
                collectionElementType = ClassUtils.getCollectionElementType(member.getType(), member.getGenericType());
            }
            contmd = new CollectionMetaData();
            contmd.setParent(mmd);
            CollectionMetaData collmd = (CollectionMetaData) contmd;
            collmd.setElementType(elementTypeStr.toString());
            if (!StringUtils.isWhitespace(embeddedElement)) {
                collmd.setEmbeddedElement(Boolean.valueOf(embeddedElement));
            }
            if (!StringUtils.isWhitespace(serializedElement)) {
                collmd.setSerializedElement(Boolean.valueOf(serializedElement));
            }
            if (!StringUtils.isWhitespace(dependentElement)) {
                collmd.setDependentElement(Boolean.valueOf(dependentElement));
            }
            if ((embeddedElementMembers != null || "true".equalsIgnoreCase(embeddedElement)) && elemmd == null) {
                elemmd = new ElementMetaData();
                mmd.setElementMetaData(elemmd);
            }
            if (elemmd != null) {
                if (embeddedElementMembers != null) {
                    // Add any embedded element mappings
                    EmbeddedMetaData embmd = elemmd.getEmbeddedMetaData();
                    if ("true".equalsIgnoreCase(embeddedElement) && elemmd.getEmbeddedMetaData() == null) {
                        // Create EmbeddedMetaData for element since not existing
                        embmd = elemmd.newEmbeddedMetaData();
                    }
                    for (Persistent embeddedElementMember : embeddedElementMembers) {
                        // Add the metadata for the embedded element to the embedded metadata
                        String memberName = embeddedElementMember.name();
                        if (memberName.indexOf('.') > 0) {
                            memberName = memberName.substring(memberName.lastIndexOf('.') + 1);
                        }
                        AbstractMemberMetaData embfmd = getFieldMetaDataForPersistent(embmd, embeddedElementMember, isMemberOfClassAField(collectionElementType, memberName));
                        embmd.addMember(embfmd);
                    }
                }
            }
        } else if (contmd instanceof ArrayMetaData) {
            StringBuilder elementTypeStr = new StringBuilder();
            if (elementTypes != null && elementTypes.length > 0 && elementTypes[0] != void.class) {
                // User-specified element type(s)
                for (Class elementType : elementTypes) {
                    if (elementTypeStr.length() > 0) {
                        elementTypeStr.append(',');
                    }
                    elementTypeStr.append(elementType.getName());
                }
            } else {
                // Derive from component type
                elementTypeStr.append(member.getType().getComponentType().getName());
            }
            contmd = new ArrayMetaData();
            contmd.setParent(mmd);
            ArrayMetaData arrmd = (ArrayMetaData) contmd;
            arrmd.setElementType(elementTypeStr.toString());
            if (!StringUtils.isWhitespace(embeddedElement)) {
                arrmd.setEmbeddedElement(Boolean.valueOf(embeddedElement));
            }
            if (!StringUtils.isWhitespace(serializedElement)) {
                arrmd.setSerializedElement(Boolean.valueOf(serializedElement));
            }
            if (!StringUtils.isWhitespace(dependentElement)) {
                arrmd.setDependentElement(Boolean.valueOf(dependentElement));
            }
        } else if (contmd instanceof MapMetaData) {
            Class mapKeyType = null;
            if (keyTypes != null && keyTypes.length > 0 && keyTypes[0] != void.class) {
                // User-specified key type TODO Support multiple keys (interface implementations)
                mapKeyType = keyTypes[0];
            } else {
                // Try to derive key type from generics info
                mapKeyType = ClassUtils.getMapKeyType(member.getType(), member.getGenericType());
            }
            Class mapValueType = null;
            if (valueTypes != null && valueTypes.length > 0 && valueTypes[0] != void.class) {
                // User-specified value type TODO Support multiple values (interface implementations)
                mapValueType = valueTypes[0];
            } else {
                // Try to derive value type from generics info
                mapValueType = ClassUtils.getMapValueType(member.getType(), member.getGenericType());
            }
            contmd = new MapMetaData();
            contmd.setParent(mmd);
            MapMetaData mapmd = (MapMetaData) contmd;
            mapmd.setKeyType((mapKeyType != null ? mapKeyType.getName() : null));
            if (!StringUtils.isWhitespace(embeddedKey)) {
                mapmd.setEmbeddedKey(Boolean.valueOf(embeddedKey));
            }
            if (!StringUtils.isWhitespace(serializedKey)) {
                mapmd.setSerializedKey(Boolean.valueOf(serializedKey));
            }
            if (!StringUtils.isWhitespace(dependentKey)) {
                mapmd.setDependentKey(Boolean.valueOf(dependentKey));
            }
            mapmd.setValueType((mapValueType != null ? mapValueType.getName() : null));
            if (!StringUtils.isWhitespace(embeddedValue)) {
                mapmd.setEmbeddedValue(Boolean.valueOf(embeddedValue));
            }
            if (!StringUtils.isWhitespace(serializedValue)) {
                mapmd.setSerializedValue(Boolean.valueOf(serializedValue));
            }
            if (!StringUtils.isWhitespace(dependentValue)) {
                mapmd.setDependentValue(Boolean.valueOf(dependentValue));
            }
            if ((embeddedKeyMembers != null || "true".equalsIgnoreCase(embeddedKey)) && keymd == null) {
                keymd = new KeyMetaData();
                mmd.setKeyMetaData(keymd);
            }
            if (keymd != null) {
                if (embeddedKeyMembers != null) {
                    // Add any embedded key mappings
                    EmbeddedMetaData embmd = keymd.getEmbeddedMetaData();
                    if ("true".equalsIgnoreCase(embeddedKey) && keymd.getEmbeddedMetaData() == null) {
                        // Create EmbeddedMetaData for key since not existing
                        embmd = keymd.newEmbeddedMetaData();
                    }
                    for (Persistent embeddedKeyMember : embeddedKeyMembers) {
                        // Add the metadata for the embedded key to the embedded metadata
                        String memberName = embeddedKeyMember.name();
                        if (memberName.indexOf('.') > 0) {
                            memberName = memberName.substring(memberName.lastIndexOf('.') + 1);
                        }
                        AbstractMemberMetaData embfmd = getFieldMetaDataForPersistent(embmd, embeddedKeyMember, isMemberOfClassAField(mapKeyType, memberName));
                        embmd.addMember(embfmd);
                    }
                }
            }
            if ((embeddedKeyMembers != null || "true".equalsIgnoreCase(embeddedKey)) && valuemd == null) {
                valuemd = new ValueMetaData();
                mmd.setValueMetaData(valuemd);
            }
            if (valuemd != null) {
                if (embeddedValueMembers != null) {
                    // Add any embedded value mappings
                    EmbeddedMetaData embmd = valuemd.getEmbeddedMetaData();
                    if ("true".equalsIgnoreCase(embeddedValue) && valuemd.getEmbeddedMetaData() == null) {
                        // Create EmbeddedMetaData for value since not existing
                        embmd = valuemd.newEmbeddedMetaData();
                    }
                    for (Persistent embeddedValueMember : embeddedValueMembers) {
                        // Add the metadata for the embedded value to the embedded metadata
                        String memberName = embeddedValueMember.name();
                        if (memberName.indexOf('.') > 0) {
                            memberName = memberName.substring(memberName.lastIndexOf('.') + 1);
                        }
                        AbstractMemberMetaData embfmd = getFieldMetaDataForPersistent(embmd, embeddedValueMember, isMemberOfClassAField(mapValueType, memberName));
                        embmd.addMember(embfmd);
                    }
                }
            }
        }
        if (contmd != null) {
            mmd.setContainer(contmd);
            if (elemmd != null) {
                elemmd.setParent(mmd);
                mmd.setElementMetaData(elemmd);
                if (elemmd.getMappedBy() != null && mmd.getMappedBy() == null) {
                    // With collection/array this is the same as mapped-by on the field
                    mmd.setMappedBy(elemmd.getMappedBy());
                }
            }
            if (keymd != null) {
                keymd.setParent(mmd);
                mmd.setKeyMetaData(keymd);
            }
            if (valuemd != null) {
                valuemd.setParent(mmd);
                mmd.setValueMetaData(valuemd);
            }
            if (ordermd != null) {
                ordermd.setParent(mmd);
                mmd.setOrderMetaData(ordermd);
            }
        }
        if (joinmd != null) {
            mmd.setJoinMetaData(joinmd);
        }
        if (colmds != null) {
            for (ColumnMetaData colmd : colmds) {
                mmd.addColumn(colmd);
            }
        }
        if (idxmd != null) {
            mmd.setIndexMetaData(idxmd);
        }
        if (unimd != null) {
            mmd.setUniqueMetaData(unimd);
        }
        if (fkmd != null) {
            mmd.setForeignKeyMetaData(fkmd);
        }
        if (cacheable != null && cacheable.equalsIgnoreCase("false")) {
            mmd.setCacheable(false);
        }
        if (extensions != null) {
            mmd.addExtensions(extensions);
        }
    }
    return mmd;
}
Also used : ElementMetaData(org.datanucleus.metadata.ElementMetaData) AnnotationObject(org.datanucleus.metadata.annotations.AnnotationObject) CollectionMetaData(org.datanucleus.metadata.CollectionMetaData) ForeignKeyAction(javax.jdo.annotations.ForeignKeyAction) ValueMetaData(org.datanucleus.metadata.ValueMetaData) UseDefault(javax.jdo.AttributeConverter.UseDefault) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) Embedded(javax.jdo.annotations.Embedded) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) EmbeddedMetaData(org.datanucleus.metadata.EmbeddedMetaData) UniqueMetaData(org.datanucleus.metadata.UniqueMetaData) PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) MapMetaData(org.datanucleus.metadata.MapMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) IndexMetaData(org.datanucleus.metadata.IndexMetaData) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) PersistenceNucleusContext(org.datanucleus.PersistenceNucleusContext) JoinMetaData(org.datanucleus.metadata.JoinMetaData) AnnotationObject(org.datanucleus.metadata.annotations.AnnotationObject) InvalidMetaDataException(org.datanucleus.metadata.InvalidMetaDataException) JDOTypeConverter(org.datanucleus.api.jdo.JDOTypeConverter) OrderMetaData(org.datanucleus.metadata.OrderMetaData) AttributeConverter(javax.jdo.AttributeConverter) FieldMetaData(org.datanucleus.metadata.FieldMetaData) Column(javax.jdo.annotations.Column) ContainerHandler(org.datanucleus.store.types.ContainerHandler) KeyMetaData(org.datanucleus.metadata.KeyMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) Persistent(javax.jdo.annotations.Persistent) Discriminator(javax.jdo.annotations.Discriminator) Extension(javax.jdo.annotations.Extension) ArrayMetaData(org.datanucleus.metadata.ArrayMetaData) FieldPersistenceModifier(org.datanucleus.metadata.FieldPersistenceModifier) TypeManager(org.datanucleus.store.types.TypeManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ContainerMetaData(org.datanucleus.metadata.ContainerMetaData)

Example 9 with MapMetaData

use of org.datanucleus.metadata.MapMetaData in project datanucleus-api-jdo by datanucleus.

the class MemberMetadataImpl method newMapMetadata.

public MapMetadata newMapMetadata() {
    MapMetaData internalMapmd = getInternal().newMapMetaData();
    MapMetadataImpl mapmd = new MapMetadataImpl(internalMapmd);
    mapmd.parent = this;
    return mapmd;
}
Also used : MapMetaData(org.datanucleus.metadata.MapMetaData)

Example 10 with MapMetaData

use of org.datanucleus.metadata.MapMetaData in project tests by datanucleus.

the class AnnotationPlusXMLTest method testOneToManyUniMapFK.

/**
 * Test of JPA 1-N unidir Map relation
 */
public void testOneToManyUniMapFK() {
    NucleusContext nucleusCtx = new PersistenceNucleusContextImpl("JPA", null);
    ClassLoaderResolver clr = nucleusCtx.getClassLoaderResolver(null);
    MetaDataManager metaDataMgr = new JPAMetaDataManager(nucleusCtx);
    PersistenceUnitMetaData pumd = getMetaDataForPersistenceUnit(nucleusCtx, "JPATest");
    metaDataMgr.loadPersistenceUnit(pumd, null);
    // owner side
    ClassMetaData cmd1 = (ClassMetaData) metaDataMgr.getMetaDataForClass(Person.class.getName(), clr);
    AbstractMemberMetaData fmd1 = cmd1.getMetaDataForMember("phoneNumbers");
    assertNotNull("Department.phoneNumbers is null!", fmd1);
    assertEquals("Department.phoneNumbers mapped-by is incorrect", fmd1.getMappedBy(), null);
    assertEquals("Department.phoneNumbers relationType is incorrect", fmd1.getRelationType(clr), RelationType.ONE_TO_MANY_UNI);
    assertEquals("Department.phoneNumbers jointable name is incorrect", fmd1.getTable(), null);
    MapMetaData mmd = fmd1.getMap();
    assertNotNull("Department.phoneNumbers has no Map metadata!", mmd);
    KeyMetaData keymd = fmd1.getKeyMetaData();
    assertNotNull("Department.phoneNumbers has no Key metadata!", keymd);
    assertEquals("Department.phoneNumbers has incorrect key mapped-by", keymd.getMappedBy(), "name");
}
Also used : JPAMetaDataManager(org.datanucleus.api.jpa.metadata.JPAMetaDataManager) KeyMetaData(org.datanucleus.metadata.KeyMetaData) NucleusContext(org.datanucleus.NucleusContext) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) JPAMetaDataManager(org.datanucleus.api.jpa.metadata.JPAMetaDataManager) MetaDataManager(org.datanucleus.metadata.MetaDataManager) PersistenceNucleusContextImpl(org.datanucleus.PersistenceNucleusContextImpl) MapMetaData(org.datanucleus.metadata.MapMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) PersistenceUnitMetaData(org.datanucleus.metadata.PersistenceUnitMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData)

Aggregations

MapMetaData (org.datanucleus.metadata.MapMetaData)23 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)14 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)10 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)9 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)8 SQLTable (org.datanucleus.store.rdbms.sql.SQLTable)8 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)8 MapTable (org.datanucleus.store.rdbms.table.MapTable)8 NucleusException (org.datanucleus.exceptions.NucleusException)7 KeyMetaData (org.datanucleus.metadata.KeyMetaData)7 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)6 ClassMetaData (org.datanucleus.metadata.ClassMetaData)5 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)5 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)5 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)4 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)4 SelectStatement (org.datanucleus.store.rdbms.sql.SelectStatement)4 NucleusContext (org.datanucleus.NucleusContext)3 PersistenceNucleusContextImpl (org.datanucleus.PersistenceNucleusContextImpl)3 MetaDataManager (org.datanucleus.metadata.MetaDataManager)3