// TODO Pass in embedded colmds if they have jdbcType info?
protected void processEmbeddedMember(List<AbstractMemberMetaData> mmds, AbstractClassMetaData embCmd, 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);
        // Go through all members of the embedded type
        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
                    }
                    // Recurse through the embedded member
                    processEmbeddedMember(embMmds, mmgr.getMetaDataForClass(mmd.getType(), clr), clr, embmdMmd != null ? embmdMmd.getEmbeddedMetaData() : null, nested);
                }
                else
                {
                    if (mmd.hasCollection())
                    {
                        // Nested embedded collection, so recurse
                        if (storeMgr.getSupportedOptions().contains(StoreManager.OPTION_ORM_EMBEDDED_COLLECTION_NESTED))
                        {
                            List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(mmds);
                            embMmds.add(mmd);
                            // Add column for the collection (since the store needs a name to reference it by)
                            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
                            // Recurse through the embedded collection element
                            processEmbeddedMember(embMmds, mmgr.getMetaDataForClass(mmd.getCollection().getElementType(), clr), clr, embmdMmd != null ? embmdMmd.getEmbeddedMetaData() : null, true);
                        }
                        else
                        {
                            NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " is a (nested) embedded collection. Not supported for this datastore so ignoring");
                            continue;
                        }
                    }
                    else if (mmd.hasMap())
                    {
                        // Nested embedded map, so recurse
                        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 a (nested) embedded map. Not yet supported so ignoring");
                        }
                        else
                        {
                            NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " is a (nested) embedded map. Not supported for this datastore so ignoring");
                            continue;
                        }
                    }
                    else if (mmd.hasArray())
                    {
                        // Nested embedded array, so recurse
                        if (storeMgr.getSupportedOptions().contains(StoreManager.OPTION_ORM_EMBEDDED_ARRAY_NESTED))
                        {
                            List<AbstractMemberMetaData> embMmds = new ArrayList<AbstractMemberMetaData>(mmds);
                            embMmds.add(mmd);
                            // Add column for the array (since the store needs a name to reference it by) TODO Extract this block out and reuse it
                            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
                            // Recurse through the embedded array element
                            processEmbeddedMember(embMmds, mmgr.getMetaDataForClass(mmd.getArray().getElementType(), clr), clr, embmdMmd != null ? embmdMmd.getEmbeddedMetaData() : null, true);
                        }
                        else
                        {
                            NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " is a (nested) embedded array. Not supported for this datastore so 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
                {
                    TypeConverter typeConv = getTypeConverterForMember(mmd, colmds, typeMgr); // TODO Pass in embedded colmds if they have jdbcType info?
                    if (typeConv != null)
                    {
                        // Create column(s) for this type using a 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);
                    }
                }
            }
        }
    }
else
{
TypeConverter typeConv = getTypeConverterForMember(mmd, colmds, typeMgr); // TODO Pass in embedded colmds if they have jdbcType info?
if (typeConv != null)
{
MemberColumnMapping mapping = new MemberColumnMappingImpl(mmd, col);
col.setMemberColumnMapping(mapping);
if (schemaVerifier != null)
{
schemaVerifier.attributeEmbeddedMember(mapping, embMmds);
}
mappingByEmbeddedMember.put(getEmbeddedMemberNavigatedPath(embMmds), mapping);
}
else
{
TypeConverter typeConv = getTypeConverterForMember(mmd, colmds, typeMgr); // TODO Pass in embedded colmds if they have jdbcType info?
if (typeConv != null)
{
// Create column(s) for this type using a 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);
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
{
TypeConverter typeConv = getTypeConverterForMember(mmd, colmds, typeMgr); // TODO Pass in embedded colmds if they have jdbcType info?
if (typeConv != null)
{
// Create column(s) for this type using a 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());
}