Search in sources :

Example 1 with TypeManager

use of org.datanucleus.store.types.TypeManager in project datanucleus-rdbms by datanucleus.

the class PersistableMapping method postInsert.

/**
 * Method executed just after the insert of the owning object, allowing any necessary action
 * to this field and the object stored in it.
 * @param op ObjectProvider for the owner
 */
public void postInsert(ObjectProvider op) {
    Object pc = op.provideField(mmd.getAbsoluteFieldNumber());
    TypeManager typeManager = op.getExecutionContext().getTypeManager();
    pc = mmd.isSingleCollection() ? singleCollectionValue(typeManager, pc) : pc;
    if (pc == null) {
        // Has been set to null so nothing to do
        return;
    }
    ClassLoaderResolver clr = op.getExecutionContext().getClassLoaderResolver();
    AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
    RelationType relationType = mmd.getRelationType(clr);
    if (relationType == RelationType.ONE_TO_ONE_BI) {
        ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
        if (otherOP == null) {
            return;
        }
        AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, op.getObject(), pc);
        if (relatedMmd == null) {
            // Fsck knows why
            throw new NucleusUserException("You have a field " + mmd.getFullFieldName() + " that is 1-1 bidir yet cannot find the equivalent field at the other side. Why is that?");
        }
        Object relatedValue = otherOP.provideField(relatedMmd.getAbsoluteFieldNumber());
        relatedValue = relatedMmd.isSingleCollection() ? singleCollectionValue(typeManager, relatedValue) : relatedValue;
        if (relatedValue == null) {
            // Managed Relations : Other side not set so update it in memory
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("041018", op.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmd.getFullFieldName()));
            }
            Object replaceValue = op.getObject();
            if (relatedMmd.isSingleCollection()) {
                ElementContainerHandler containerHandler = typeManager.getContainerHandler(relatedMmd.getType());
                replaceValue = containerHandler.newContainer(relatedMmd, op.getObject());
            }
            otherOP.replaceField(relatedMmd.getAbsoluteFieldNumber(), replaceValue);
        } else if (relatedValue != op.getObject()) {
            // Managed Relations : Other side is inconsistent so throw exception
            throw new NucleusUserException(Localiser.msg("041020", op.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), StringUtils.toJVMIDString(relatedValue)));
        }
    } else if (relationType == RelationType.MANY_TO_ONE_BI && relatedMmds[0].hasCollection()) {
        // TODO Make sure we have this PC in the collection at the other side
        ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
        if (otherOP != null) {
            // Managed Relations : add to the collection on the other side
            Collection relatedColl = (Collection) otherOP.provideField(relatedMmds[0].getAbsoluteFieldNumber());
            if (relatedColl != null && !(relatedColl instanceof SCOCollection)) {
                // TODO Make sure the collection is a wrapper
                boolean contained = relatedColl.contains(op.getObject());
                if (!contained) {
                    NucleusLogger.PERSISTENCE.info(Localiser.msg("041022", op.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmds[0].getFullFieldName()));
                // TODO Enable this. Currently causes issues with PMImplTest, InheritanceStrategyTest, TCK "inheritance1.conf"
                /*relatedColl.add(op.getObject());*/
                }
            }
        }
    } else if (relationType == RelationType.MANY_TO_ONE_UNI) {
        ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
        if (otherOP == null) {
            // Related object is not yet persisted so persist it
            Object other = op.getExecutionContext().persistObjectInternal(pc, null, -1, ObjectProvider.PC);
            otherOP = op.getExecutionContext().findObjectProvider(other);
        }
        // Add join table entry
        PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
        store.add(op, otherOP);
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) RelationType(org.datanucleus.metadata.RelationType) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) TypeManager(org.datanucleus.store.types.TypeManager) Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ElementContainerHandler(org.datanucleus.store.types.ElementContainerHandler) PersistableRelationStore(org.datanucleus.store.types.scostore.PersistableRelationStore)

Example 2 with TypeManager

use of org.datanucleus.store.types.TypeManager in project datanucleus-rdbms by datanucleus.

the class MappingManagerImpl method getDefaultJavaTypeMapping.

/**
 * Method to return the default java type mapping class for a specified java type.
 * @param javaType java type
 * @param colmds Metadata for the column(s) (optional)
 * @return The mapping class to use (by default)
 */
protected MappingConverterDetails getDefaultJavaTypeMapping(Class javaType, ColumnMetaData[] colmds) {
    // Check for an explicit mapping
    Class<? extends JavaTypeMapping> cls = storeMgr.getMappingManager().getMappingType(javaType.getName());
    if (cls == null) {
        // No explicit mapping for this java type, so fall back to TypeConverter if available
        TypeManager typeMgr = storeMgr.getNucleusContext().getTypeManager();
        if (colmds != null && colmds.length > 0) {
            if (colmds.length > 1) {
                // Find TypeConverter with right number of columns
                Collection<TypeConverter> converters = typeMgr.getTypeConvertersForType(javaType);
                if (converters != null && !converters.isEmpty()) {
                    for (TypeConverter conv : converters) {
                        if (conv instanceof MultiColumnConverter) {
                            if (((MultiColumnConverter) conv).getDatastoreColumnTypes().length == colmds.length) {
                                return new MappingConverterDetails(TypeConverterMultiMapping.class, conv);
                            }
                        }
                    }
                }
            } else {
                JdbcType jdbcType = colmds[0].getJdbcType();
                if (jdbcType != null) {
                    // JDBC type specified so don't just take the default
                    TypeConverter conv = null;
                    if (MetaDataUtils.isJdbcTypeString(jdbcType)) {
                        conv = typeMgr.getTypeConverterForType(javaType, String.class);
                    } else if (MetaDataUtils.isJdbcTypeNumeric(jdbcType)) {
                        conv = typeMgr.getTypeConverterForType(javaType, Long.class);
                    } else if (jdbcType == JdbcType.TIMESTAMP) {
                        conv = typeMgr.getTypeConverterForType(javaType, Timestamp.class);
                    } else if (jdbcType == JdbcType.TIME) {
                        conv = typeMgr.getTypeConverterForType(javaType, Time.class);
                    } else if (jdbcType == JdbcType.DATE) {
                        conv = typeMgr.getTypeConverterForType(javaType, Date.class);
                    }
                    if (conv != null) {
                        return new MappingConverterDetails(TypeConverterMapping.class, conv);
                    }
                }
            }
        }
        TypeConverter conv = typeMgr.getDefaultTypeConverterForType(javaType);
        if (conv != null) {
            if (conv instanceof MultiColumnConverter) {
                return new MappingConverterDetails(TypeConverterMultiMapping.class, conv);
            }
            return new MappingConverterDetails(TypeConverterMapping.class, conv);
        }
        NucleusLogger.PERSISTENCE.debug(Localiser.msg("041000", javaType.getName()));
        return null;
    }
    return new MappingConverterDetails(cls);
}
Also used : TypeConverter(org.datanucleus.store.types.converters.TypeConverter) TypeManager(org.datanucleus.store.types.TypeManager) JdbcType(org.datanucleus.metadata.JdbcType) MultiColumnConverter(org.datanucleus.store.types.converters.MultiColumnConverter) Timestamp(java.sql.Timestamp) Date(java.sql.Date)

Example 3 with TypeManager

use of org.datanucleus.store.types.TypeManager in project datanucleus-rdbms by datanucleus.

the class MappingManagerImpl method getMapping.

/**
 * Accessor for the mapping for the member of the specified table.
 * Can be used for members of a class, element of a collection of a class, element of an array of a class,
 * keys of a map of a class, values of a map of a class; this is controlled by the role argument.
 * @param table Table to add the mapping to
 * @param mmd MetaData for the member to map
 * @param clr The ClassLoaderResolver
 * @param fieldRole Role that this mapping plays for the field
 * @return The mapping for the member.
 */
@Override
public JavaTypeMapping getMapping(Table table, AbstractMemberMetaData mmd, ClassLoaderResolver clr, FieldRole fieldRole) {
    if (fieldRole == FieldRole.ROLE_COLLECTION_ELEMENT || fieldRole == FieldRole.ROLE_ARRAY_ELEMENT) {
        // Mapping a collection/array element (in a join table)
        return getElementMapping(table, mmd, fieldRole, clr);
    } else if (fieldRole == FieldRole.ROLE_MAP_KEY) {
        // Mapping a map key (in a join table)
        return getKeyMapping(table, mmd, clr);
    } else if (fieldRole == FieldRole.ROLE_MAP_VALUE) {
        // Mapping a map value (in a join table)
        return getValueMapping(table, mmd, clr);
    }
    // Check for use of TypeConverter (either specific, or auto-apply for this type)
    TypeManager typeMgr = table.getStoreManager().getNucleusContext().getTypeManager();
    TypeConverter conv = null;
    if (!mmd.isTypeConversionDisabled()) {
        // User-specified TypeConverter defined for the whole member, or an autoApply is present for this member type
        if (mmd.getTypeConverterName() != null) {
            conv = typeMgr.getTypeConverterForName(mmd.getTypeConverterName());
            if (conv == null) {
                throw new NucleusUserException(Localiser.msg("044062", mmd.getFullFieldName(), mmd.getTypeConverterName()));
            }
        } else {
            TypeConverter autoApplyConv = typeMgr.getAutoApplyTypeConverterForType(mmd.getType());
            if (autoApplyConv != null) {
                conv = autoApplyConv;
            }
        }
        if (conv != null) {
            // Create the mapping of the selected type
            JavaTypeMapping m = null;
            if (conv instanceof MultiColumnConverter) {
                Class mc = TypeConverterMultiMapping.class;
                try {
                    m = (JavaTypeMapping) mc.getDeclaredConstructor().newInstance();
                    m.setRoleForMember(FieldRole.ROLE_FIELD);
                    ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, conv);
                    return m;
                } catch (Exception e) {
                    throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
                }
            }
            Class mc = TypeConverterMapping.class;
            try {
                m = (JavaTypeMapping) mc.getDeclaredConstructor().newInstance();
                m.setRoleForMember(FieldRole.ROLE_FIELD);
                ((TypeConverterMapping) m).initialize(mmd, table, clr, conv);
                return m;
            } catch (Exception e) {
                throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
            }
        }
    }
    AbstractMemberMetaData overrideMmd = null;
    MappingConverterDetails mcd = null;
    Class<? extends JavaTypeMapping> mc = null;
    String userMappingClassName = mmd.getValueForExtension("mapping-class");
    if (userMappingClassName != null) {
        // User has defined their own mapping class for this field so use that
        try {
            mc = clr.classForName(userMappingClassName);
        } catch (NucleusException ne) {
            throw new NucleusUserException(Localiser.msg("041014", mmd.getFullFieldName(), userMappingClassName)).setFatal();
        }
    } else {
        AbstractClassMetaData typeCmd = (mmd.getType().isInterface()) ? storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForInterface(mmd.getType(), clr) : storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getType(), clr);
        if (mmd.hasExtension(SerialisedLocalFileMapping.EXTENSION_SERIALIZE_TO_FOLDER) && Serializable.class.isAssignableFrom(mmd.getType())) {
            // Special case : use file serialization mapping
            mc = SerialisedLocalFileMapping.class;
        } else if (mmd.isSerialized()) {
            // Field is marked as serialised then we have no other option - serialise it
            mcd = getMappingClass(mmd.getType(), true, false, null, mmd.getFullFieldName());
        } else if (mmd.getEmbeddedMetaData() != null) {
            // Field has an <embedded> specification so use that
            mcd = getMappingClass(mmd.getType(), false, true, null, mmd.getFullFieldName());
        } else if (typeCmd != null && typeCmd.isEmbeddedOnly()) {
            // Reference type is declared with embedded only
            mcd = getMappingClass(mmd.getType(), false, true, null, mmd.getFullFieldName());
        } else if (// TODO Check this since it will push all basic nonPC fields through here
        mmd.isEmbedded()) {
            // Otherwise, if the field is embedded then we request that it be serialised into the owner table
            // This is particularly for java.lang.Object which should be "embedded" by default, and hence serialised
            mcd = getMappingClass(mmd.getType(), true, false, mmd.getColumnMetaData(), mmd.getFullFieldName());
        } else {
            // Non-embedded/non-serialised - Just get the basic mapping for the type
            Class memberType = mmd.getType();
            mcd = getMappingClass(memberType, false, false, mmd.getColumnMetaData(), mmd.getFullFieldName());
            if (mmd.getParent() instanceof EmbeddedMetaData && mmd.getRelationType(clr) != RelationType.NONE) {
                // See NUCCORE-697 - always need to use the real member metadata for the mapping
                // so that it can find sub-fields when persisting/querying etc
                AbstractClassMetaData cmdForFmd = table.getStoreManager().getMetaDataManager().getMetaDataForClass(mmd.getClassName(), clr);
                overrideMmd = cmdForFmd.getMetaDataForMember(mmd.getName());
            }
        }
    }
    // Create the mapping of the selected type
    if (mcd != null) {
        mc = mcd.mappingClass;
        // Allow override by Oracle
        mc = getOverrideMappingClass(mc, mmd, fieldRole);
    }
    if (mc != null && (mcd == null || mcd.typeConverter == null)) {
        try {
            JavaTypeMapping m = mc.getDeclaredConstructor().newInstance();
            m.setRoleForMember(FieldRole.ROLE_FIELD);
            m.initialize(mmd, table, clr);
            if (overrideMmd != null) {
                // Note cannot just use this overrideMmd in the initialize(...) call above, a test fails.
                m.setMemberMetaData(overrideMmd);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    } else if (mcd != null && mcd.typeConverter != null) {
        try {
            JavaTypeMapping m = mcd.mappingClass.getDeclaredConstructor().newInstance();
            m.setRoleForMember(FieldRole.ROLE_FIELD);
            if (m instanceof TypeConverterMapping) {
                ((TypeConverterMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            } else if (m instanceof TypeConverterMultiMapping) {
                ((TypeConverterMultiMapping) m).initialize(mmd, table, clr, mcd.typeConverter);
            }
            if (overrideMmd != null) {
                // Note cannot just use this overrideMmd in the initialize(...) call above, a test fails.
                m.setMemberMetaData(overrideMmd);
            }
            return m;
        } catch (Exception e) {
            throw new NucleusException(Localiser.msg("041009", mc.getName(), e), e).setFatal();
        }
    }
    throw new NucleusException("Unable to create mapping for member at " + mmd.getFullFieldName() + " - no available mapping");
}
Also used : Serializable(java.io.Serializable) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedMetaData(org.datanucleus.metadata.EmbeddedMetaData) MultiColumnConverter(org.datanucleus.store.types.converters.MultiColumnConverter) NucleusException(org.datanucleus.exceptions.NucleusException) NoTableManagedException(org.datanucleus.store.rdbms.exceptions.NoTableManagedException) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) TypeConverter(org.datanucleus.store.types.converters.TypeConverter) TypeConverterMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMapping) TypeManager(org.datanucleus.store.types.TypeManager) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) TypeConverterMultiMapping(org.datanucleus.store.rdbms.mapping.java.TypeConverterMultiMapping)

Example 4 with TypeManager

use of org.datanucleus.store.types.TypeManager in project datanucleus-rdbms by datanucleus.

the class PersistableMapping method postInsert.

/**
 * Method executed just after the insert of the owning object, allowing any necessary action
 * to this field and the object stored in it.
 * @param sm StateManager for the owner
 */
public void postInsert(DNStateManager sm) {
    Object pc = sm.provideField(mmd.getAbsoluteFieldNumber());
    TypeManager typeManager = sm.getExecutionContext().getTypeManager();
    pc = mmd.isSingleCollection() ? singleCollectionValue(typeManager, pc) : pc;
    if (pc == null) {
        // Has been set to null so nothing to do
        return;
    }
    ClassLoaderResolver clr = sm.getExecutionContext().getClassLoaderResolver();
    AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
    RelationType relationType = mmd.getRelationType(clr);
    if (relationType == RelationType.ONE_TO_ONE_BI) {
        DNStateManager otherSM = sm.getExecutionContext().findStateManager(pc);
        if (otherSM == null) {
            return;
        }
        AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, sm.getObject(), pc);
        if (relatedMmd == null) {
            // Fsck knows why
            throw new NucleusUserException("You have a field " + mmd.getFullFieldName() + " that is 1-1 bidir yet cannot find the equivalent field at the other side. Why is that?");
        }
        Object relatedValue = otherSM.provideField(relatedMmd.getAbsoluteFieldNumber());
        relatedValue = relatedMmd.isSingleCollection() ? singleCollectionValue(typeManager, relatedValue) : relatedValue;
        if (relatedValue == null) {
            // Managed Relations : Other side not set so update it in memory
            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                NucleusLogger.PERSISTENCE.debug(Localiser.msg("041018", sm.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmd.getFullFieldName()));
            }
            Object replaceValue = sm.getObject();
            if (relatedMmd.isSingleCollection()) {
                ElementContainerHandler containerHandler = typeManager.getContainerHandler(relatedMmd.getType());
                replaceValue = containerHandler.newContainer(relatedMmd, sm.getObject());
            }
            otherSM.replaceField(relatedMmd.getAbsoluteFieldNumber(), replaceValue);
        } else if (relatedValue != sm.getObject()) {
            // Managed Relations : Other side is inconsistent so throw exception
            throw new NucleusUserException(Localiser.msg("041020", sm.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), StringUtils.toJVMIDString(relatedValue)));
        }
    } else if (relationType == RelationType.MANY_TO_ONE_BI && relatedMmds[0].hasCollection()) {
        // TODO Make sure we have this PC in the collection at the other side
        DNStateManager otherSM = sm.getExecutionContext().findStateManager(pc);
        if (otherSM != null) {
            // Managed Relations : add to the collection on the other side
            Collection relatedColl = (Collection) otherSM.provideField(relatedMmds[0].getAbsoluteFieldNumber());
            if (relatedColl != null && !(relatedColl instanceof SCOCollection)) {
                // TODO Make sure the collection is a wrapper
                boolean contained = relatedColl.contains(sm.getObject());
                if (!contained) {
                    NucleusLogger.PERSISTENCE.info(Localiser.msg("041022", sm.getObjectAsPrintable(), mmd.getFullFieldName(), StringUtils.toJVMIDString(pc), relatedMmds[0].getFullFieldName()));
                // TODO Enable this. Currently causes issues with PMImplTest, InheritanceStrategyTest, TCK "inheritance1.conf"
                /*relatedColl.add(op.getObject());*/
                }
            }
        }
    } else if (relationType == RelationType.MANY_TO_ONE_UNI) {
        DNStateManager otherSM = sm.getExecutionContext().findStateManager(pc);
        if (otherSM == null) {
            // Related object is not yet persisted so persist it
            Object other = sm.getExecutionContext().persistObjectInternal(pc, null, -1, PersistableObjectType.PC);
            otherSM = sm.getExecutionContext().findStateManager(other);
        }
        // Add join table entry
        PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
        store.add(sm, otherSM);
    }
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) RelationType(org.datanucleus.metadata.RelationType) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) TypeManager(org.datanucleus.store.types.TypeManager) Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) DNStateManager(org.datanucleus.state.DNStateManager) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ElementContainerHandler(org.datanucleus.store.types.containers.ElementContainerHandler) PersistableRelationStore(org.datanucleus.store.types.scostore.PersistableRelationStore)

Example 5 with TypeManager

use of org.datanucleus.store.types.TypeManager in project datanucleus-core by datanucleus.

the class CompleteClassTable method processEmbeddedMember.

protected void processEmbeddedMember(List<AbstractMemberMetaData> mmds, ClassLoaderResolver clr, EmbeddedMetaData embmd, boolean ownerNested) {
    TypeManager typeMgr = storeMgr.getNucleusContext().getTypeManager();
    MetaDataManager mmgr = storeMgr.getMetaDataManager();
    NamingFactory namingFactory = storeMgr.getNamingFactory();
    AbstractMemberMetaData lastMmd = mmds.get(mmds.size() - 1);
    AbstractClassMetaData embCmd = null;
    if (lastMmd.hasCollection()) {
        // Embedded collection element
        embCmd = mmgr.getMetaDataForClass(lastMmd.getCollection().getElementType(), clr);
    } else if (lastMmd.hasArray()) {
        // Embedded array element
        embCmd = mmgr.getMetaDataForClass(lastMmd.getArray().getElementType(), clr);
    } else {
        // Embedded 1-1
        embCmd = mmgr.getMetaDataForClass(lastMmd.getType(), clr);
    }
    // Go through all members of the embedded class
    int[] memberPositions = embCmd.getAllMemberPositions();
    for (int i = 0; i < memberPositions.length; i++) {
        AbstractMemberMetaData mmd = embCmd.getMetaDataForManagedMemberAtAbsolutePosition(memberPositions[i]);
        if (mmd.getPersistenceModifier() != FieldPersistenceModifier.PERSISTENT) {
            // Don't need column if not persistent
            continue;
        }
        if (mmds.size() == 1 && embmd != null && embmd.getOwnerMember() != null && embmd.getOwnerMember().equals(mmd.getName())) {
            // Special case of this being a link back to the owner. TODO Repeat this for nested and their owners
            continue;
        }
        AbstractMemberMetaData embmdMmd = null;
        if (embmd != null) {
            AbstractMemberMetaData[] embmdMmds = embmd.getMemberMetaData();
            if (embmdMmds != null) {
                for (AbstractMemberMetaData thisMmd : embmdMmds) {
                    if (thisMmd.getName().equals(mmd.getName())) {
                        embmdMmd = thisMmd;
                        break;
                    }
                }
            }
        }
        RelationType relationType = mmd.getRelationType(clr);
        if (relationType != RelationType.NONE && MetaDataUtils.getInstance().isMemberEmbedded(mmgr, clr, mmd, relationType, lastMmd)) {
            if (RelationType.isRelationSingleValued(relationType)) {
                // Nested embedded PC, so recurse
                boolean nested = false;
                if (storeMgr.getSupportedOptions().contains(StoreManager.OPTION_ORM_EMBEDDED_PC_NESTED)) {
                    nested = !storeMgr.getNucleusContext().getConfiguration().getBooleanProperty(PropertyNames.PROPERTY_METADATA_EMBEDDED_PC_FLAT);
                    String nestedStr = mmd.getValueForExtension("nested");
                    if (nestedStr != null && nestedStr.equalsIgnoreCase("" + !nested)) {
                        nested = !nested;
                    }
                }
                List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(mmds);
                embMmds.add(mmd);
                if (nested) {
                    // Embedded object stored as nested under this in the owner table (where the datastore supports that)
                    // Add column for the owner of the embedded object, typically for the column name only
                    ColumnMetaData[] colmds = mmd.getColumnMetaData();
                    String colName = namingFactory.getColumnName(embMmds, 0);
                    ColumnImpl col = addEmbeddedColumn(colName, null);
                    col.setNested(true);
                    if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getPosition() != null) {
                        col.setPosition(embmdMmd.getColumnMetaData()[0].getPosition());
                    } else if (colmds != null && colmds.length == 1 && colmds[0].getPosition() != null) {
                        col.setPosition(colmds[0].getPosition());
                    }
                    if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getJdbcType() != null) {
                        col.setJdbcType(embmdMmd.getColumnMetaData()[0].getJdbcType());
                    } else if (colmds != null && colmds.length == 1 && colmds[0].getJdbcType() != null) {
                        col.setJdbcType(colmds[0].getJdbcType());
                    }
                    MemberColumnMapping mapping = new MemberColumnMappingImpl(mmd, col);
                    col.setMemberColumnMapping(mapping);
                    if (schemaVerifier != null) {
                        schemaVerifier.attributeEmbeddedMember(mapping, embMmds);
                    }
                    mappingByEmbeddedMember.put(getEmbeddedMemberNavigatedPath(embMmds), mapping);
                    // TODO Create mapping for the related info under the above column
                    processEmbeddedMember(embMmds, clr, embmdMmd != null ? embmdMmd.getEmbeddedMetaData() : null, true);
                } else {
                    // Embedded object stored flat into this table, with columns at same level as owner columns
                    processEmbeddedMember(embMmds, clr, embmdMmd != null ? embmdMmd.getEmbeddedMetaData() : null, false);
                }
            } else {
                if (mmd.hasCollection()) {
                    if (storeMgr.getSupportedOptions().contains(StoreManager.OPTION_ORM_EMBEDDED_COLLECTION_NESTED)) {
                    // TODO Support nested embedded collection element
                    }
                    NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " is an embedded collection. Not yet supported. Ignoring");
                    continue;
                } else if (mmd.hasMap()) {
                    if (storeMgr.getSupportedOptions().contains(StoreManager.OPTION_ORM_EMBEDDED_MAP_NESTED)) {
                    // TODO Support nested embedded map key/value
                    }
                    NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " is an embedded collection. Not yet supported. Ignoring");
                    continue;
                } else if (mmd.hasArray()) {
                    if (storeMgr.getSupportedOptions().contains(StoreManager.OPTION_ORM_EMBEDDED_ARRAY_NESTED)) {
                    // TODO Support nested embedded array element
                    }
                    NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " is an embedded array. Not yet supported. Ignoring");
                    continue;
                }
            }
        } else {
            List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(mmds);
            embMmds.add(mmd);
            ColumnMetaData[] colmds = mmd.getColumnMetaData();
            if (relationType != RelationType.NONE) {
                // 1-1/N-1 stored as single column with persistable-id
                // 1-N/M-N stored as single column with collection<persistable-id>
                // Create column for basic type
                String colName = namingFactory.getColumnName(embMmds, 0);
                ColumnImpl col = addEmbeddedColumn(colName, null);
                col.setNested(ownerNested);
                if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getPosition() != null) {
                    col.setPosition(embmdMmd.getColumnMetaData()[0].getPosition());
                } else if (colmds != null && colmds.length == 1 && colmds[0].getPosition() != null) {
                    col.setPosition(colmds[0].getPosition());
                }
                if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getJdbcType() != null) {
                    col.setJdbcType(embmdMmd.getColumnMetaData()[0].getJdbcType());
                } else if (colmds != null && colmds.length == 1 && colmds[0].getJdbcType() != null) {
                    col.setJdbcType(colmds[0].getJdbcType());
                }
                MemberColumnMapping mapping = new MemberColumnMappingImpl(mmd, col);
                col.setMemberColumnMapping(mapping);
                if (schemaVerifier != null) {
                    schemaVerifier.attributeEmbeddedMember(mapping, embMmds);
                }
                mappingByEmbeddedMember.put(getEmbeddedMemberNavigatedPath(embMmds), mapping);
            } else {
                // TODO Pass in embedded colmds if they have jdbcType info?
                TypeConverter typeConv = getTypeConverterForMember(mmd, colmds, typeMgr);
                if (typeConv != null) {
                    // Create column(s) for this TypeConverter
                    if (typeConv instanceof MultiColumnConverter) {
                        Class[] colJavaTypes = ((MultiColumnConverter) typeConv).getDatastoreColumnTypes();
                        Column[] cols = new Column[colJavaTypes.length];
                        for (int j = 0; j < colJavaTypes.length; j++) {
                            String colName = namingFactory.getColumnName(embMmds, j);
                            ColumnImpl col = addEmbeddedColumn(colName, typeConv);
                            col.setNested(ownerNested);
                            if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == colJavaTypes.length && embmdMmd.getColumnMetaData()[j].getPosition() != null) {
                                col.setPosition(embmdMmd.getColumnMetaData()[j].getPosition());
                            } else if (colmds != null && colmds.length == colJavaTypes.length && colmds[j].getPosition() != null) {
                                col.setPosition(colmds[j].getPosition());
                            }
                            if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == colJavaTypes.length && embmdMmd.getColumnMetaData()[j].getJdbcType() != null) {
                                col.setJdbcType(embmdMmd.getColumnMetaData()[j].getJdbcType());
                            } else if (colmds != null && colmds.length == colJavaTypes.length && colmds[j].getJdbcType() != null) {
                                col.setJdbcType(colmds[j].getJdbcType());
                            }
                            cols[j] = col;
                        }
                        MemberColumnMapping mapping = new MemberColumnMappingImpl(mmd, cols, typeConv);
                        for (int j = 0; j < colJavaTypes.length; j++) {
                            ((ColumnImpl) cols[j]).setMemberColumnMapping(mapping);
                        }
                        if (schemaVerifier != null) {
                            schemaVerifier.attributeEmbeddedMember(mapping, embMmds);
                        }
                        mappingByEmbeddedMember.put(getEmbeddedMemberNavigatedPath(embMmds), mapping);
                    } else {
                        String colName = namingFactory.getColumnName(embMmds, 0);
                        ColumnImpl col = addEmbeddedColumn(colName, typeConv);
                        col.setNested(ownerNested);
                        if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getPosition() != null) {
                            col.setPosition(embmdMmd.getColumnMetaData()[0].getPosition());
                        } else if (colmds != null && colmds.length == 1 && colmds[0].getPosition() != null) {
                            col.setPosition(colmds[0].getPosition());
                        }
                        if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getJdbcType() != null) {
                            col.setJdbcType(embmdMmd.getColumnMetaData()[0].getJdbcType());
                        } else if (colmds != null && colmds.length == 1 && colmds[0].getJdbcType() != null) {
                            col.setJdbcType(colmds[0].getJdbcType());
                        }
                        MemberColumnMapping mapping = new MemberColumnMappingImpl(mmd, col);
                        col.setMemberColumnMapping(mapping);
                        mapping.setTypeConverter(typeConv);
                        if (schemaVerifier != null) {
                            schemaVerifier.attributeEmbeddedMember(mapping, embMmds);
                        }
                        mappingByEmbeddedMember.put(getEmbeddedMemberNavigatedPath(embMmds), mapping);
                    }
                } else {
                    // Create column for basic type
                    String colName = namingFactory.getColumnName(embMmds, 0);
                    ColumnImpl col = addEmbeddedColumn(colName, null);
                    col.setNested(ownerNested);
                    AbstractMemberMetaData theMmd = embMmds.get(0);
                    if (theMmd.isPrimaryKey()) {
                        col.setPrimaryKey();
                    }
                    if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getPosition() != null) {
                        col.setPosition(embmdMmd.getColumnMetaData()[0].getPosition());
                    } else if (colmds != null && colmds.length == 1 && colmds[0].getPosition() != null) {
                        col.setPosition(colmds[0].getPosition());
                    }
                    if (embmdMmd != null && embmdMmd.getColumnMetaData() != null && embmdMmd.getColumnMetaData().length == 1 && embmdMmd.getColumnMetaData()[0].getJdbcType() != null) {
                        col.setJdbcType(embmdMmd.getColumnMetaData()[0].getJdbcType());
                    } else if (colmds != null && colmds.length == 1 && colmds[0].getJdbcType() != null) {
                        col.setJdbcType(colmds[0].getJdbcType());
                    }
                    MemberColumnMapping mapping = new MemberColumnMappingImpl(mmd, col);
                    col.setMemberColumnMapping(mapping);
                    if (schemaVerifier != null) {
                        schemaVerifier.attributeEmbeddedMember(mapping, embMmds);
                    }
                    mappingByEmbeddedMember.put(getEmbeddedMemberNavigatedPath(embMmds), mapping);
                }
            }
        }
    }
}
Also used : ArrayList(java.util.ArrayList) MetaDataManager(org.datanucleus.metadata.MetaDataManager) MultiColumnConverter(org.datanucleus.store.types.converters.MultiColumnConverter) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) TypeConverter(org.datanucleus.store.types.converters.TypeConverter) RelationType(org.datanucleus.metadata.RelationType) TypeManager(org.datanucleus.store.types.TypeManager) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) NamingFactory(org.datanucleus.store.schema.naming.NamingFactory) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

TypeManager (org.datanucleus.store.types.TypeManager)26 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)10 JDOTypeConverter (org.datanucleus.api.jdo.JDOTypeConverter)8 ApiAdapter (org.datanucleus.api.ApiAdapter)6 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)5 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)5 RelationType (org.datanucleus.metadata.RelationType)5 ContainerHandler (org.datanucleus.store.types.ContainerHandler)5 AttributeConverter (javax.jdo.AttributeConverter)4 PersistenceNucleusContext (org.datanucleus.PersistenceNucleusContext)4 ExecutionContext (org.datanucleus.ExecutionContext)3 NucleusException (org.datanucleus.exceptions.NucleusException)3 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)3 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)3 EmbeddedMetaData (org.datanucleus.metadata.EmbeddedMetaData)3 FieldMetaData (org.datanucleus.metadata.FieldMetaData)3 FieldPersistenceModifier (org.datanucleus.metadata.FieldPersistenceModifier)3 ObjectProvider (org.datanucleus.state.ObjectProvider)3 MultiColumnConverter (org.datanucleus.store.types.converters.MultiColumnConverter)3 TypeConverter (org.datanucleus.store.types.converters.TypeConverter)3