Search in sources :

Example 11 with ElementMetaData

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

the class ElementContainerTable method getExpectedIndices.

/**
 * Accessor for the indices for this table.
 * This includes both the user-defined indices (via MetaData), and the ones required by
 * foreign keys (required by relationships).
 * @param clr The ClassLoaderResolver
 * @return The indices
 */
protected Set getExpectedIndices(ClassLoaderResolver clr) {
    assertIsInitialized();
    Set<Index> indices = new HashSet();
    // Index for FK back to owner
    if (mmd.getIndexMetaData() != null) {
        Index index = TableUtils.getIndexForField(this, mmd.getIndexMetaData(), ownerMapping);
        if (index != null) {
            indices.add(index);
        }
    } else if (mmd.getJoinMetaData() != null && mmd.getJoinMetaData().getIndexMetaData() != null) {
        Index index = TableUtils.getIndexForField(this, mmd.getJoinMetaData().getIndexMetaData(), ownerMapping);
        if (index != null) {
            indices.add(index);
        }
    } else {
        // Fallback to an index for the foreign-key to the owner
        Index index = TableUtils.getIndexForField(this, null, ownerMapping);
        if (index != null) {
            indices.add(index);
        }
    }
    // Index for FK to element (if required)
    if (elementMapping instanceof EmbeddedElementPCMapping) {
        // Add all indices required by fields of the embedded element
        EmbeddedElementPCMapping embMapping = (EmbeddedElementPCMapping) elementMapping;
        for (int i = 0; i < embMapping.getNumberOfJavaTypeMappings(); i++) {
            // Add indexes for fields of this embedded PC object
            JavaTypeMapping embFieldMapping = embMapping.getJavaTypeMapping(i);
            IndexMetaData imd = embFieldMapping.getMemberMetaData().getIndexMetaData();
            if (imd != null) {
                Index index = TableUtils.getIndexForField(this, imd, embFieldMapping);
                if (index != null) {
                    indices.add(index);
                }
            }
        }
    } else {
        ElementMetaData elemmd = mmd.getElementMetaData();
        if (elemmd != null && elemmd.getIndexMetaData() != null) {
            Index index = TableUtils.getIndexForField(this, elemmd.getIndexMetaData(), elementMapping);
            if (index != null) {
                indices.add(index);
            }
        } else {
            // Fallback to an index for any foreign-key to the element
            if (elementMapping instanceof PersistableMapping) {
                Index index = TableUtils.getIndexForField(this, null, elementMapping);
                if (index != null) {
                    indices.add(index);
                }
            }
        }
    }
    if (orderMapping != null) {
        // Index for ordering?
        if (mmd.getOrderMetaData() != null && mmd.getOrderMetaData().getIndexMetaData() != null) {
            Index index = TableUtils.getIndexForField(this, mmd.getOrderMetaData().getIndexMetaData(), orderMapping);
            if (index != null) {
                indices.add(index);
            }
        }
    }
    return indices;
}
Also used : PersistableMapping(org.datanucleus.store.rdbms.mapping.java.PersistableMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ElementMetaData(org.datanucleus.metadata.ElementMetaData) Index(org.datanucleus.store.rdbms.key.Index) EmbeddedElementPCMapping(org.datanucleus.store.rdbms.mapping.java.EmbeddedElementPCMapping) HashSet(java.util.HashSet) IndexMetaData(org.datanucleus.metadata.IndexMetaData)

Example 12 with ElementMetaData

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

the class ClassTable method manageMembers.

/**
 * Goes through all specified members for the specified class and adds a mapping for each.
 * Ignores primary-key fields which are added elsewhere.
 * @param theCmd ClassMetaData for the class to be managed
 * @param clr The ClassLoaderResolver
 * @param mmds the fields/properties to manage
 */
private void manageMembers(AbstractClassMetaData theCmd, ClassLoaderResolver clr, AbstractMemberMetaData[] mmds) {
    // Go through the fields for this class and add columns for them
    for (int fieldNumber = 0; fieldNumber < mmds.length; fieldNumber++) {
        // Primary key fields are added by the initialisePK method
        AbstractMemberMetaData mmd = mmds[fieldNumber];
        if (!mmd.isPrimaryKey()) {
            if (managesMember(mmd.getFullFieldName())) {
                if (!mmd.getClassName(true).equals(theCmd.getFullClassName())) {
                    // Field already managed by this table so maybe we are overriding a superclass
                    JavaTypeMapping fieldMapping = getMappingForMemberName(mmd.getFullFieldName());
                    ColumnMetaData[] colmds = mmd.getColumnMetaData();
                    if (colmds != null && colmds.length > 0) {
                        // Apply this set of ColumnMetaData to the existing mapping
                        int colnum = 0;
                        IdentifierFactory idFactory = getStoreManager().getIdentifierFactory();
                        for (int i = 0; i < fieldMapping.getNumberOfDatastoreMappings(); i++) {
                            Column col = fieldMapping.getDatastoreMapping(i).getColumn();
                            col.setIdentifier(idFactory.newColumnIdentifier(colmds[colnum].getName()));
                            col.setColumnMetaData(colmds[colnum]);
                            colnum++;
                            if (colnum == colmds.length) {
                                // Reached end of specified metadata
                                break;
                            }
                        }
                        // TODO Change this to reflect that we have updated the previous mapping
                        logMapping(mmd.getFullFieldName(), fieldMapping);
                    }
                }
            } else {
                // Manage the field if not already managed (may already exist if overriding a superclass field)
                if (mmd.getPersistenceModifier() == FieldPersistenceModifier.PERSISTENT) {
                    boolean isPrimary = true;
                    if (mmd.getTable() != null && mmd.getJoinMetaData() == null) {
                        // Field has a table specified and is not a 1-N with join table
                        // so is mapped to a secondary table
                        isPrimary = false;
                    }
                    if (isPrimary) {
                        // Add the field to this table
                        JavaTypeMapping fieldMapping = storeMgr.getMappingManager().getMapping(this, mmd, clr, FieldRole.ROLE_FIELD);
                        if (theCmd != cmd && theCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUPERCLASS_TABLE && fieldMapping.getNumberOfDatastoreMappings() > 0) {
                            // Field is for a subclass and so column(s) has to either allow nulls, or have default
                            int numCols = fieldMapping.getNumberOfDatastoreMappings();
                            for (int colNum = 0; colNum < numCols; colNum++) {
                                Column col = fieldMapping.getDatastoreMapping(colNum).getColumn();
                                if (col.getDefaultValue() == null && !col.isNullable()) {
                                    // Column needs to be nullable
                                    NucleusLogger.DATASTORE_SCHEMA.debug("Member " + mmd.getFullFieldName() + " uses superclass-table yet the field is not marked as nullable " + " nor does it have a default value, so setting the column as nullable");
                                    col.setNullable(true);
                                }
                            }
                        }
                        addMemberMapping(fieldMapping);
                    } else {
                        // Add the field to the appropriate secondary table
                        if (secondaryTables == null) {
                            secondaryTables = new HashMap();
                        }
                        SecondaryTable secTable = secondaryTables.get(mmd.getTable());
                        if (secTable == null) {
                            // Secondary table doesnt exist yet so create it to users specifications.
                            List<JoinMetaData> joinmds = theCmd.getJoinMetaData();
                            JoinMetaData theJoinMD = null;
                            if (joinmds != null) {
                                for (JoinMetaData joinmd : joinmds) {
                                    if (joinmd.getTable().equalsIgnoreCase(mmd.getTable()) && (joinmd.getCatalog() == null || (joinmd.getCatalog() != null && joinmd.getCatalog().equalsIgnoreCase(mmd.getCatalog()))) && (joinmd.getSchema() == null || (joinmd.getSchema() != null && joinmd.getSchema().equalsIgnoreCase(mmd.getSchema())))) {
                                        theJoinMD = joinmd;
                                        break;
                                    }
                                }
                            }
                            DatastoreIdentifier secTableIdentifier = storeMgr.getIdentifierFactory().newTableIdentifier(mmd.getTable());
                            // Use specified catalog, else take catalog of the owning table
                            String catalogName = mmd.getCatalog();
                            if (catalogName == null) {
                                catalogName = getCatalogName();
                            }
                            // Use specified schema, else take schema of the owning table
                            String schemaName = mmd.getSchema();
                            if (schemaName == null) {
                                schemaName = getSchemaName();
                            }
                            secTableIdentifier.setCatalogName(catalogName);
                            secTableIdentifier.setSchemaName(schemaName);
                            secTable = new SecondaryTable(secTableIdentifier, storeMgr, this, theJoinMD, clr);
                            secTable.preInitialize(clr);
                            secTable.initialize(clr);
                            secTable.postInitialize(clr);
                            secondaryTables.put(mmd.getTable(), secTable);
                        }
                        secTable.addMemberMapping(storeMgr.getMappingManager().getMapping(secTable, mmd, clr, FieldRole.ROLE_FIELD));
                    }
                } else if (mmd.getPersistenceModifier() != FieldPersistenceModifier.TRANSACTIONAL) {
                    throw new NucleusException(Localiser.msg("057006", mmd.getName())).setFatal();
                }
                // Calculate if we need a FK adding due to a 1-N (FK) relationship
                boolean needsFKToContainerOwner = false;
                RelationType relationType = mmd.getRelationType(clr);
                if (relationType == RelationType.ONE_TO_MANY_BI) {
                    AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
                    if (mmd.getJoinMetaData() == null && relatedMmds[0].getJoinMetaData() == null) {
                        needsFKToContainerOwner = true;
                    }
                } else if (relationType == RelationType.ONE_TO_MANY_UNI && !mmd.isSingleCollection()) {
                    if (mmd.getJoinMetaData() == null) {
                        needsFKToContainerOwner = true;
                    }
                }
                if (needsFKToContainerOwner) {
                    // 1-N uni/bidirectional using FK, so update the element side with a FK
                    if ((mmd.getCollection() != null && !SCOUtils.collectionHasSerialisedElements(mmd)) || (mmd.getArray() != null && !SCOUtils.arrayIsStoredInSingleColumn(mmd, storeMgr.getMetaDataManager()))) {
                        // 1-N ForeignKey collection/array, so add FK to element table
                        AbstractClassMetaData elementCmd = null;
                        if (mmd.hasCollection()) {
                            // Collection
                            elementCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mmd.getCollection().getElementType(), clr);
                        } else {
                            // Array
                            elementCmd = storeMgr.getMetaDataManager().getMetaDataForClass(mmd.getType().getComponentType(), clr);
                        }
                        if (elementCmd == null) {
                            String[] implClassNames = storeMgr.getMetaDataManager().getClassesImplementingInterface(mmd.getCollection().getElementType(), clr);
                            if (implClassNames != null && implClassNames.length > 0) {
                                // Collection/array of interface type so apply callback to all implementation types
                                AbstractClassMetaData[] elementCmds = new AbstractClassMetaData[implClassNames.length];
                                for (int i = 0; i < implClassNames.length; i++) {
                                    elementCmds[i] = storeMgr.getMetaDataManager().getMetaDataForClass(implClassNames[i], clr);
                                }
                                // Run callbacks for each of the element classes.
                                for (int i = 0; i < elementCmds.length; i++) {
                                    storeMgr.addSchemaCallback(elementCmds[i].getFullClassName(), mmd);
                                    DatastoreClass dc = storeMgr.getDatastoreClass(elementCmds[i].getFullClassName(), clr);
                                    if (dc == null) {
                                        throw new NucleusException("Unable to add foreign-key to " + elementCmds[i].getFullClassName() + " to " + this + " since element has no table!");
                                    }
                                    if (dc instanceof ClassTable) {
                                        ClassTable ct = (ClassTable) dc;
                                        if (ct.isInitialized()) {
                                            // if the target table is already initialized, run the callbacks
                                            ct.runCallBacks(clr);
                                        }
                                    } else {
                                        NucleusLogger.DATASTORE_SCHEMA.info("Table " + toString() + " has to manage member " + mmd.getFullFieldName() + " yet the related element uses a VIEW so not remotely adding element FK owner column; assumed to be part of the VIEW definition");
                                    }
                                }
                            } else {
                                // Elements that are reference types or non-PC will come through here
                                if (mmd.hasCollection()) {
                                    NucleusLogger.METADATA.warn(Localiser.msg("057016", theCmd.getFullClassName(), mmd.getCollection().getElementType()));
                                } else {
                                    NucleusLogger.METADATA.warn(Localiser.msg("057014", theCmd.getFullClassName(), mmd.getType().getComponentType().getName()));
                                }
                            }
                        } else {
                            AbstractClassMetaData[] elementCmds = null;
                            // TODO : Cater for interface elements, and get the metadata for the implementation classes here
                            if (elementCmd.getBaseAbstractClassMetaData().getInheritanceMetaData().getStrategy() == InheritanceStrategy.COMPLETE_TABLE) {
                                // COMPLETE-TABLE inheritance in element, so really need FK in each!
                                Collection<String> elementSubclassNames = storeMgr.getSubClassesForClass(elementCmd.getFullClassName(), true, clr);
                                elementCmds = new ClassMetaData[elementSubclassNames != null ? 1 + elementSubclassNames.size() : 1];
                                int elemNo = 0;
                                elementCmds[elemNo++] = elementCmd;
                                if (elementSubclassNames != null) {
                                    for (String elementSubclassName : elementSubclassNames) {
                                        AbstractClassMetaData elemSubCmd = storeMgr.getMetaDataManager().getMetaDataForClass(elementSubclassName, clr);
                                        elementCmds[elemNo++] = elemSubCmd;
                                    }
                                }
                            } else if (elementCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
                                elementCmds = storeMgr.getClassesManagingTableForClass(elementCmd, clr);
                            } else {
                                elementCmds = new ClassMetaData[1];
                                elementCmds[0] = elementCmd;
                            }
                            ElementMetaData elemmd = mmd.getElementMetaData();
                            if (elemmd != null && !StringUtils.isWhitespace(elemmd.getTable())) {
                                DatastoreIdentifier requiredTableId = storeMgr.getIdentifierFactory().newTableIdentifier(elemmd.getTable());
                                DatastoreClass requiredTable = storeMgr.getDatastoreClass(requiredTableId);
                                if (requiredTable != null) {
                                    // TODO Respect specification of table in ElementMetaData rather than just defaulting to table of element type
                                    // Note that this will need updates to FKListStore, FKSetStore etc to look for the table
                                    NucleusLogger.GENERAL.warn("Member=" + mmd.getFullFieldName() + " has 1-N FK with required table=" + requiredTable + " : we don't currently support specification of the element table, and always take the default table for the element type");
                                /*for (int i=0;i<elementCmds.length;i++)
                                        {
                                            AbstractClassMetaData theElementCmd = elementCmds[i];
                                            while (theElementCmd != null)
                                            {
                                                if (requiredTable.managesClass(theElementCmd.getFullClassName()))
                                                {
                                                    if (theElementCmd != elementCmds[i])
                                                    {
                                                        elementCmds = new ClassMetaData[1];
                                                        elementCmds[0] = theElementCmd;
                                                        break;
                                                    }
                                                }
                                                theElementCmd = theElementCmd.getSuperAbstractClassMetaData();
                                            }
                                        }*/
                                } else {
                                    NucleusLogger.DATASTORE_SCHEMA.warn("Member " + mmd.getFullFieldName() + " specified element FK in table=" + elemmd.getTable() + " but table not known. Ignoring.");
                                }
                            }
                            // Run callbacks for each of the element classes
                            for (int i = 0; i < elementCmds.length; i++) {
                                storeMgr.addSchemaCallback(elementCmds[i].getFullClassName(), mmd);
                                DatastoreClass dc = storeMgr.getDatastoreClass(elementCmds[i].getFullClassName(), clr);
                                if (// If dc is null then we assume the (possible) element is abstract so no FK needed
                                dc != null) {
                                    if (dc instanceof ClassTable) {
                                        ClassTable ct = (ClassTable) dc;
                                        if (ct.isInitialized()) {
                                            // if the target table is already initialized, run the callbacks
                                            ct.runCallBacks(clr);
                                        }
                                    } else {
                                        NucleusLogger.DATASTORE_SCHEMA.info("Table " + toString() + " has to manage member " + mmd.getFullFieldName() + " yet the related element uses a VIEW so not remotely adding element FK owner column; assumed to be part of the VIEW definition");
                                    }
                                }
                            }
                        }
                    } else if (mmd.getMap() != null && !SCOUtils.mapHasSerialisedKeysAndValues(mmd)) {
                        // 1-N ForeignKey map, so add FK to value table
                        if (mmd.getKeyMetaData() != null && mmd.getKeyMetaData().getMappedBy() != null) {
                            // Key is stored in the value table so add the FK to the value table
                            AbstractClassMetaData valueCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getMap().getValueType(), clr);
                            if (valueCmd == null) {
                                // Interface elements will come through here and java.lang.String and others as well
                                NucleusLogger.METADATA.warn(Localiser.msg("057018", theCmd.getFullClassName(), mmd.getMap().getValueType()));
                            } else {
                                AbstractClassMetaData[] valueCmds = null;
                                // TODO : Cater for interface values, and get the metadata for the implementation classes here
                                if (valueCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
                                    valueCmds = storeMgr.getClassesManagingTableForClass(valueCmd, clr);
                                } else {
                                    valueCmds = new ClassMetaData[1];
                                    valueCmds[0] = valueCmd;
                                }
                                // Run callbacks for each of the value classes.
                                for (int i = 0; i < valueCmds.length; i++) {
                                    storeMgr.addSchemaCallback(valueCmds[i].getFullClassName(), mmd);
                                    DatastoreClass dc = storeMgr.getDatastoreClass(valueCmds[i].getFullClassName(), clr);
                                    if (dc instanceof ClassTable) {
                                        ClassTable ct = (ClassTable) dc;
                                        if (ct.isInitialized()) {
                                            // if the target table is already initialized, run the callbacks
                                            ct.runCallBacks(clr);
                                        }
                                    } else {
                                        NucleusLogger.DATASTORE_SCHEMA.info("Table " + toString() + " has to manage member " + mmd.getFullFieldName() + " yet the related value uses a VIEW so not remotely adding value owner FK column; assumed to be part of the VIEW definition");
                                    }
                                }
                            }
                        } else if (mmd.getValueMetaData() != null && mmd.getValueMetaData().getMappedBy() != null) {
                            // Value is stored in the key table so add the FK to the key table
                            AbstractClassMetaData keyCmd = storeMgr.getNucleusContext().getMetaDataManager().getMetaDataForClass(mmd.getMap().getKeyType(), clr);
                            if (keyCmd == null) {
                                // Interface elements will come through here and java.lang.String and others as well
                                NucleusLogger.METADATA.warn(Localiser.msg("057019", theCmd.getFullClassName(), mmd.getMap().getKeyType()));
                            } else {
                                AbstractClassMetaData[] keyCmds = null;
                                // TODO : Cater for interface keys, and get the metadata for the implementation classes here
                                if (keyCmd.getInheritanceMetaData().getStrategy() == InheritanceStrategy.SUBCLASS_TABLE) {
                                    keyCmds = storeMgr.getClassesManagingTableForClass(keyCmd, clr);
                                } else {
                                    keyCmds = new ClassMetaData[1];
                                    keyCmds[0] = keyCmd;
                                }
                                // Run callbacks for each of the key classes.
                                for (int i = 0; i < keyCmds.length; i++) {
                                    storeMgr.addSchemaCallback(keyCmds[i].getFullClassName(), mmd);
                                    DatastoreClass dc = storeMgr.getDatastoreClass(keyCmds[i].getFullClassName(), clr);
                                    if (dc instanceof ClassTable) {
                                        ClassTable ct = (ClassTable) dc;
                                        if (ct.isInitialized()) {
                                            // if the target table is already initialized, run the callbacks
                                            ct.runCallBacks(clr);
                                        }
                                    } else {
                                        NucleusLogger.DATASTORE_SCHEMA.info("Table " + toString() + " has to manage member " + mmd.getFullFieldName() + " yet the related key uses a VIEW so not remotely adding key FK owner column; assumed to be part of the VIEW definition");
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) HashMap(java.util.HashMap) ElementMetaData(org.datanucleus.metadata.ElementMetaData) MacroString(org.datanucleus.util.MacroString) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) RelationType(org.datanucleus.metadata.RelationType) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData) IdentifierFactory(org.datanucleus.store.rdbms.identifier.IdentifierFactory) DatastoreIdentifier(org.datanucleus.store.rdbms.identifier.DatastoreIdentifier) JoinMetaData(org.datanucleus.metadata.JoinMetaData) NucleusException(org.datanucleus.exceptions.NucleusException) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 13 with ElementMetaData

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

the class MemberMetadataImpl method newElementMetadata.

public ElementMetadata newElementMetadata() {
    ElementMetaData internalElemmd = getInternal().newElementMetaData();
    ElementMetadataImpl elemmd = new ElementMetadataImpl(internalElemmd);
    elemmd.parent = this;
    return elemmd;
}
Also used : ElementMetaData(org.datanucleus.metadata.ElementMetaData)

Example 14 with ElementMetaData

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

the class JDOMetaDataHandler method startElement.

/**
 * Handler method called at the start of an element.
 * @param uri URI of the tag
 * @param localName Local name
 * @param qName Element name
 * @param attrs Attributes for this element
 * @throws SAXException in parsing errors
 */
public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
    if (charactersBuffer.length() > 0) {
        // Cater for subelements that appear before the end of the body text (save the body text with the
        // parent)
        String currentString = getString().trim();
        if (getStack() instanceof QueryMetaData) {
            ((QueryMetaData) getStack()).setQuery(currentString.trim());
        }
    }
    if (localName.length() < 1) {
        localName = qName;
    }
    try {
        if (localName.equals("jdo")) {
            FileMetaData filemd = (FileMetaData) getStack();
            filemd.setType(MetadataFileType.JDO_FILE);
            filemd.setCatalog(getAttr(attrs, "catalog"));
            filemd.setSchema(getAttr(attrs, "schema"));
        } else if (localName.equals("orm")) {
            FileMetaData filemd = (FileMetaData) getStack();
            filemd.setType(MetadataFileType.JDO_ORM_FILE);
            filemd.setCatalog(getAttr(attrs, "catalog"));
            filemd.setSchema(getAttr(attrs, "schema"));
        } else if (localName.equals("jdoquery")) {
            FileMetaData filemd = (FileMetaData) getStack();
            filemd.setType(MetadataFileType.JDO_QUERY_FILE);
        } else if (localName.equals("fetch-plan")) {
            FileMetaData filemd = (FileMetaData) metadata;
            FetchPlanMetaData fpmd = filemd.newFetchPlanMetadata(getAttr(attrs, "name"));
            fpmd.setMaxFetchDepth(getAttr(attrs, "max-fetch-depth"));
            fpmd.setFetchSize(getAttr(attrs, "fetch-size"));
            pushStack(fpmd);
        } else if (localName.equals("package")) {
            FileMetaData filemd = (FileMetaData) getStack();
            PackageMetaData pmd = filemd.newPackageMetadata(getAttr(attrs, "name"));
            pmd.setCatalog(getAttr(attrs, "catalog"));
            pmd.setSchema(getAttr(attrs, "schema"));
            pushStack(pmd);
        } else if (localName.equals("class")) {
            PackageMetaData pmd = (PackageMetaData) getStack();
            ClassMetaData cmd = newClassObject(pmd, attrs);
            pmd.addClass(cmd);
            pushStack(cmd);
        } else if (localName.equals("interface")) {
            PackageMetaData pmd = (PackageMetaData) getStack();
            InterfaceMetaData imd = newInterfaceObject(pmd, attrs);
            pmd.addInterface(imd);
            pushStack(imd);
        } else if (localName.equals("primary-key")) {
            MetaData md = getStack();
            PrimaryKeyMetaData pkmd = new PrimaryKeyMetaData();
            pkmd.setName(getAttr(attrs, "name"));
            pkmd.setColumnName(getAttr(attrs, "column"));
            if (md instanceof AbstractClassMetaData) {
                ((AbstractClassMetaData) md).setPrimaryKeyMetaData(pkmd);
            } else if (md instanceof JoinMetaData) {
                ((JoinMetaData) md).setPrimaryKeyMetaData(pkmd);
            }
            pushStack(pkmd);
        } else if (localName.equals("implements")) {
            ClassMetaData cmd = (ClassMetaData) getStack();
            ImplementsMetaData imd = new ImplementsMetaData(getAttr(attrs, "name"));
            cmd.addImplements(imd);
            pushStack(imd);
        } else if (localName.equals("property")) {
            MetaData parent = getStack();
            if (parent instanceof AbstractClassMetaData) {
                AbstractClassMetaData acmd = (AbstractClassMetaData) parent;
                PropertyMetaData propmd = newPropertyObject(acmd, attrs);
                acmd.addMember(propmd);
                pushStack(propmd);
            } else if (parent instanceof EmbeddedMetaData) {
                EmbeddedMetaData emd = (EmbeddedMetaData) parent;
                PropertyMetaData propmd = newPropertyObject(emd, attrs);
                emd.addMember(propmd);
                pushStack(propmd);
            } else if (parent instanceof ImplementsMetaData) {
                ImplementsMetaData implmd = (ImplementsMetaData) parent;
                PropertyMetaData propmd = newPropertyObject(implmd, attrs);
                implmd.addProperty(propmd);
                pushStack(propmd);
            } else if (parent instanceof FetchGroupMetaData) {
                FetchGroupMetaData fgmd = (FetchGroupMetaData) parent;
                FetchGroupMemberMetaData fgmmd = new FetchGroupMemberMetaData(fgmd, getAttr(attrs, "name"));
                fgmmd.setRecursionDepth(getAttr(attrs, "recursion-depth"));
                fgmmd.setProperty();
                fgmd.addMember(fgmmd);
                pushStack(fgmmd);
            }
        } else if (localName.equals("datastore-identity")) {
            AbstractClassMetaData acmd = (AbstractClassMetaData) getStack();
            IdentityMetaData idmd = new IdentityMetaData();
            idmd.setColumnName(getAttr(attrs, "column"));
            idmd.setValueStrategy(ValueGenerationStrategy.getIdentityStrategy(getAttr(attrs, "strategy")));
            idmd.setSequence(getAttr(attrs, "sequence"));
            acmd.setIdentityMetaData(idmd);
            pushStack(idmd);
        } else if (localName.equals("inheritance")) {
            MetaData parent = getStack();
            AbstractClassMetaData acmd = (AbstractClassMetaData) parent;
            InheritanceMetaData inhmd = new InheritanceMetaData();
            inhmd.setStrategy(getAttr(attrs, "strategy"));
            acmd.setInheritanceMetaData(inhmd);
            pushStack(inhmd);
        } else if (localName.equals("discriminator")) {
            MetaData md = getStack();
            if (md instanceof InheritanceMetaData) {
                InheritanceMetaData inhmd = (InheritanceMetaData) md;
                DiscriminatorMetaData dismd = inhmd.newDiscriminatorMetadata();
                dismd.setColumnName(getAttr(attrs, "column"));
                dismd.setValue(getAttr(attrs, "value"));
                dismd.setStrategy(getAttr(attrs, "strategy"));
                dismd.setIndexed(getAttr(attrs, "indexed"));
                pushStack(dismd);
            } else if (md instanceof EmbeddedMetaData) {
                EmbeddedMetaData embmd = (EmbeddedMetaData) md;
                DiscriminatorMetaData dismd = embmd.newDiscriminatorMetadata();
                dismd.setColumnName(getAttr(attrs, "column"));
                dismd.setValue(getAttr(attrs, "value"));
                dismd.setStrategy(getAttr(attrs, "strategy"));
                dismd.setIndexed(getAttr(attrs, "indexed"));
                pushStack(dismd);
            }
        } else if (localName.equals("query")) {
            MetaData emd = getStack();
            String name = getAttr(attrs, "name");
            String lang = getAttr(attrs, "language");
            if (!StringUtils.isWhitespace(lang)) {
                if (// Convert to JDOQL
                lang.equals(JDOQuery.JDOQL_QUERY_LANGUAGE)) {
                    lang = QueryLanguage.JDOQL.toString();
                } else if (// Convert to SQL
                lang.equals(JDOQuery.SQL_QUERY_LANGUAGE)) {
                    lang = QueryLanguage.SQL.toString();
                } else if (// Convert to JPQL
                lang.equals(JDOQuery.JPQL_QUERY_LANGUAGE)) {
                    lang = QueryLanguage.JPQL.toString();
                }
            }
            if (emd instanceof ClassMetaData) {
                ClassMetaData cmd = (ClassMetaData) emd;
                if (StringUtils.isWhitespace(name)) {
                    throw new InvalidClassMetaDataException("044154", cmd.getFullClassName());
                }
                QueryMetaData qmd = new QueryMetaData(name);
                qmd.setScope(cmd.getFullClassName());
                qmd.setLanguage(lang);
                qmd.setUnmodifiable(getAttr(attrs, "unmodifiable"));
                qmd.setResultClass(getAttr(attrs, "result-class"));
                qmd.setUnique(getAttr(attrs, "unique"));
                qmd.setFetchPlanName(getAttr(attrs, "fetch-plan"));
                cmd.addQuery(qmd);
                pushStack(qmd);
            } else if (emd instanceof InterfaceMetaData) {
                InterfaceMetaData imd = (InterfaceMetaData) emd;
                if (StringUtils.isWhitespace(name)) {
                    throw new InvalidClassMetaDataException("044154", imd.getFullClassName());
                }
                QueryMetaData qmd = new QueryMetaData(name);
                qmd.setScope(imd.getFullClassName());
                qmd.setLanguage(lang);
                qmd.setUnmodifiable(getAttr(attrs, "unmodifiable"));
                qmd.setResultClass(getAttr(attrs, "result-class"));
                qmd.setUnique(getAttr(attrs, "unique"));
                qmd.setFetchPlanName(getAttr(attrs, "fetch-plan"));
                imd.addQuery(qmd);
                pushStack(qmd);
            } else if (emd instanceof FileMetaData) {
                FileMetaData filemd = (FileMetaData) emd;
                QueryMetaData qmd = filemd.newQueryMetadata(name);
                qmd.setLanguage(lang);
                qmd.setUnmodifiable(getAttr(attrs, "unmodifiable"));
                qmd.setResultClass(getAttr(attrs, "result-class"));
                qmd.setUnique(getAttr(attrs, "unique"));
                qmd.setFetchPlanName(getAttr(attrs, "fetch-plan"));
                pushStack(qmd);
            }
        } else if (localName.equals("sequence")) {
            PackageMetaData pmd = (PackageMetaData) getStack();
            SequenceMetaData seqmd = pmd.newSequenceMetadata(getAttr(attrs, "name"), getAttr(attrs, "strategy"));
            seqmd.setFactoryClass(getAttr(attrs, "factory-class"));
            seqmd.setDatastoreSequence(getAttr(attrs, "datastore-sequence"));
            String seqSize = getAttr(attrs, "allocation-size");
            if (seqSize != null) {
                seqmd.setAllocationSize(seqSize);
            }
            String seqStart = getAttr(attrs, "initial-value");
            if (seqStart != null) {
                seqmd.setInitialValue(seqStart);
            }
            pushStack(seqmd);
        } else if (localName.equals("field")) {
            MetaData md = getStack();
            if (md instanceof FetchGroupMetaData) {
                FetchGroupMetaData fgmd = (FetchGroupMetaData) md;
                FetchGroupMemberMetaData fgmmd = new FetchGroupMemberMetaData(md, getAttr(attrs, "name"));
                fgmmd.setRecursionDepth(getAttr(attrs, "recursion-depth"));
                fgmd.addMember(fgmmd);
                pushStack(fgmmd);
                return;
            }
            FieldMetaData fmd = newFieldObject(md, attrs);
            if (md instanceof ClassMetaData) {
                ClassMetaData cmd = (ClassMetaData) md;
                cmd.addMember(fmd);
            } else if (md instanceof EmbeddedMetaData) {
                EmbeddedMetaData emd = (EmbeddedMetaData) md;
                emd.addMember(fmd);
            } else if (md instanceof ForeignKeyMetaData) {
                ForeignKeyMetaData fkmd = (ForeignKeyMetaData) md;
                fkmd.addMember(fmd.getName());
            } else if (md instanceof IndexMetaData) {
                IndexMetaData imd = (IndexMetaData) md;
                imd.addMember(fmd.getName());
            } else if (md instanceof UniqueMetaData) {
                UniqueMetaData umd = (UniqueMetaData) md;
                umd.addMember(fmd.getName());
            }
            pushStack(fmd);
        } else if (localName.equals("join")) {
            MetaData parent = getStack();
            String tableName = getAttr(attrs, "table");
            String columnName = getAttr(attrs, "column");
            String outer = getAttr(attrs, "outer");
            IndexedValue indexed = IndexedValue.getIndexedValue(getAttr(attrs, "indexed"));
            String unique = getAttr(attrs, "unique");
            String deleteAction = getAttr(attrs, "delete-action");
            JoinMetaData joinmd = null;
            if (parent instanceof AbstractMemberMetaData) {
                AbstractMemberMetaData fmd = (AbstractMemberMetaData) parent;
                joinmd = fmd.newJoinMetaData();
            } else if (parent instanceof AbstractClassMetaData) {
                AbstractClassMetaData cmd = (AbstractClassMetaData) parent;
                joinmd = new JoinMetaData();
                cmd.addJoin(joinmd);
            } else if (parent instanceof InheritanceMetaData) {
                InheritanceMetaData inhmd = (InheritanceMetaData) parent;
                joinmd = inhmd.newJoinMetadata();
            } else {
                throw new NucleusUserException("Error processing JDO XML metadata. Found \"join\" with parent " + StringUtils.toJVMIDString(parent) + " - not supported");
            }
            joinmd.setTable(tableName);
            joinmd.setColumnName(columnName);
            joinmd.setOuter(MetaDataUtils.getBooleanForString(outer, false));
            joinmd.setIndexed(indexed);
            joinmd.setUnique(unique);
            joinmd.setDeleteAction(deleteAction);
            pushStack(joinmd);
        } else if (localName.equals("map")) {
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            MapMetaData mapmd = fmd.newMapMetaData();
            mapmd.setKeyType(getAttr(attrs, "key-type"));
            String embKeyStr = getAttr(attrs, "embedded-key");
            if (!StringUtils.isWhitespace(embKeyStr)) {
                mapmd.setEmbeddedKey(Boolean.valueOf(embKeyStr));
            }
            String serKeyStr = getAttr(attrs, "serialized-key");
            if (!StringUtils.isWhitespace(serKeyStr)) {
                mapmd.setSerializedKey(Boolean.valueOf(serKeyStr));
            }
            String depKeyStr = getAttr(attrs, "dependent-key");
            if (!StringUtils.isWhitespace(depKeyStr)) {
                mapmd.setDependentKey(Boolean.valueOf(depKeyStr));
            }
            mapmd.setValueType(getAttr(attrs, "value-type"));
            String embValStr = getAttr(attrs, "embedded-value");
            if (!StringUtils.isWhitespace(embValStr)) {
                mapmd.setEmbeddedValue(Boolean.valueOf(embValStr));
            }
            String serValStr = getAttr(attrs, "serialized-value");
            if (!StringUtils.isWhitespace(serValStr)) {
                mapmd.setSerializedValue(Boolean.valueOf(serValStr));
            }
            String depValStr = getAttr(attrs, "dependent-value");
            if (!StringUtils.isWhitespace(depValStr)) {
                mapmd.setDependentValue(Boolean.valueOf(depValStr));
            }
            pushStack(mapmd);
        } else if (localName.equals("array")) {
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            ArrayMetaData arrmd = fmd.newArrayMetaData();
            arrmd.setElementType(getAttr(attrs, "element-type"));
            String embElemStr = getAttr(attrs, "embedded-element");
            if (!StringUtils.isWhitespace(embElemStr)) {
                arrmd.setEmbeddedElement(Boolean.valueOf(embElemStr));
            }
            String serElemStr = getAttr(attrs, "serialized-element");
            if (!StringUtils.isWhitespace(serElemStr)) {
                arrmd.setSerializedElement(Boolean.valueOf(serElemStr));
            }
            String depElemStr = getAttr(attrs, "dependent-element");
            if (!StringUtils.isWhitespace(depElemStr)) {
                arrmd.setDependentElement(Boolean.valueOf(depElemStr));
            }
            pushStack(arrmd);
        } else if (localName.equals("collection")) {
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            CollectionMetaData collmd = fmd.newCollectionMetaData();
            collmd.setElementType(getAttr(attrs, "element-type"));
            String embElemStr = getAttr(attrs, "embedded-element");
            if (!StringUtils.isWhitespace(embElemStr)) {
                collmd.setEmbeddedElement(Boolean.valueOf(embElemStr));
            }
            String serElemStr = getAttr(attrs, "serialized-element");
            if (!StringUtils.isWhitespace(serElemStr)) {
                collmd.setSerializedElement(Boolean.valueOf(serElemStr));
            }
            String depElemStr = getAttr(attrs, "dependent-element");
            if (!StringUtils.isWhitespace(depElemStr)) {
                collmd.setDependentElement(Boolean.valueOf(depElemStr));
            }
            pushStack(collmd);
        } else if (localName.equals("column")) {
            MetaData md = getStack();
            ColumnMetaData colmd = new ColumnMetaData();
            colmd.setName(getAttr(attrs, "name"));
            colmd.setTarget(getAttr(attrs, "target"));
            colmd.setTargetMember(getAttr(attrs, "target-field"));
            colmd.setJdbcType(getAttr(attrs, "jdbc-type"));
            colmd.setSqlType(getAttr(attrs, "sql-type"));
            colmd.setLength(getAttr(attrs, "length"));
            colmd.setScale(getAttr(attrs, "scale"));
            colmd.setAllowsNull(getAttr(attrs, "allows-null"));
            colmd.setDefaultValue(getAttr(attrs, "default-value"));
            colmd.setInsertValue(getAttr(attrs, "insert-value"));
            // JDO 3.1+
            String pos = getAttr(attrs, "position");
            if (pos != null) {
                colmd.setPosition(pos);
            }
            if (md instanceof AbstractMemberMetaData) {
                AbstractMemberMetaData fmd = (AbstractMemberMetaData) md;
                fmd.addColumn(colmd);
            } else if (md instanceof AbstractElementMetaData) {
                AbstractElementMetaData elemd = (AbstractElementMetaData) md;
                elemd.addColumn(colmd);
            } else if (md instanceof JoinMetaData) {
                JoinMetaData jnmd = (JoinMetaData) md;
                jnmd.addColumn(colmd);
            } else if (md instanceof IdentityMetaData) {
                IdentityMetaData idmd = (IdentityMetaData) md;
                idmd.setColumnMetaData(colmd);
            } else if (md instanceof ForeignKeyMetaData) {
                ForeignKeyMetaData fkmd = (ForeignKeyMetaData) md;
                fkmd.addColumn(colmd);
            } else if (md instanceof IndexMetaData) {
                IndexMetaData idxmd = (IndexMetaData) md;
                idxmd.addColumn(colmd.getName());
            } else if (md instanceof UniqueMetaData) {
                UniqueMetaData unimd = (UniqueMetaData) md;
                unimd.addColumn(colmd.getName());
            } else if (md instanceof OrderMetaData) {
                OrderMetaData ormd = (OrderMetaData) md;
                ormd.addColumn(colmd);
            } else if (md instanceof DiscriminatorMetaData) {
                DiscriminatorMetaData dismd = (DiscriminatorMetaData) md;
                dismd.setColumnMetaData(colmd);
            } else if (md instanceof VersionMetaData) {
                VersionMetaData vermd = (VersionMetaData) md;
                vermd.setColumnMetaData(colmd);
            } else if (md instanceof AbstractClassMetaData) {
                AbstractClassMetaData cmd = (AbstractClassMetaData) md;
                cmd.addUnmappedColumn(colmd);
            } else if (md instanceof PrimaryKeyMetaData) {
                PrimaryKeyMetaData pkmd = (PrimaryKeyMetaData) md;
                pkmd.addColumn(colmd);
            }
            pushStack(colmd);
        } else if (localName.equals("element")) {
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            ElementMetaData elemmd = new ElementMetaData();
            elemmd.setTable(getAttr(attrs, "table"));
            elemmd.setColumnName(getAttr(attrs, "column"));
            elemmd.setDeleteAction(getAttr(attrs, "delete-action"));
            elemmd.setUpdateAction(getAttr(attrs, "update-action"));
            elemmd.setIndexed(IndexedValue.getIndexedValue(getAttr(attrs, "indexed")));
            elemmd.setUnique(MetaDataUtils.getBooleanForString(getAttr(attrs, "unique"), false));
            String mappedBy = getAttr(attrs, "mapped-by");
            elemmd.setMappedBy(mappedBy);
            if (!StringUtils.isWhitespace(mappedBy) && fmd.getMappedBy() == null) {
                // With collection/array this is the same as mapped-by on the field
                fmd.setMappedBy(mappedBy);
            }
            String converterAttr = getAttr(attrs, "converter");
            String disableConverterAttr = getAttr(attrs, "use-default-conversion");
            if (disableConverterAttr != null && Boolean.getBoolean(disableConverterAttr)) {
            // TODO Disable on the element?
            } else if (!StringUtils.isWhitespace(converterAttr)) {
                TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                ClassLoaderResolver clr = mmgr.getNucleusContext().getClassLoaderResolver(null);
                Class converterCls = clr.classForName(converterAttr);
                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);
                    // TODO element type
                    Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, null);
                    Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                    // Register the TypeConverter under the name of the AttributeConverter class
                    JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                    typeMgr.registerConverter(converterAttr, typeConv, attrType, dbType, false, null);
                }
                elemmd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME, converterAttr);
            }
            fmd.setElementMetaData(elemmd);
            pushStack(elemmd);
        } else if (localName.equals("key")) {
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            KeyMetaData keymd = new KeyMetaData();
            keymd.setTable(getAttr(attrs, "table"));
            keymd.setColumnName(getAttr(attrs, "column"));
            keymd.setDeleteAction(getAttr(attrs, "delete-action"));
            keymd.setUpdateAction(getAttr(attrs, "update-action"));
            keymd.setIndexed(IndexedValue.getIndexedValue(getAttr(attrs, "indexed")));
            keymd.setUnique(MetaDataUtils.getBooleanForString(getAttr(attrs, "unique"), false));
            keymd.setMappedBy(getAttr(attrs, "mapped-by"));
            String converterAttr = getAttr(attrs, "converter");
            String disableConverterAttr = getAttr(attrs, "use-default-conversion");
            if (disableConverterAttr != null && Boolean.getBoolean(disableConverterAttr)) {
            // TODO Disable on the key?
            } else if (!StringUtils.isWhitespace(converterAttr)) {
                TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                ClassLoaderResolver clr = mmgr.getNucleusContext().getClassLoaderResolver(null);
                Class converterCls = clr.classForName(converterAttr);
                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);
                    // TODO key type
                    Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, null);
                    Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                    // Register the TypeConverter under the name of the AttributeConverter class
                    JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                    typeMgr.registerConverter(converterAttr, typeConv, attrType, dbType, false, null);
                }
                keymd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME, converterAttr);
            }
            fmd.setKeyMetaData(keymd);
            pushStack(keymd);
        } else // New value
        if (localName.equals("value")) {
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            ValueMetaData valuemd = new ValueMetaData();
            valuemd.setTable(getAttr(attrs, "table"));
            valuemd.setColumnName(getAttr(attrs, "column"));
            valuemd.setDeleteAction(getAttr(attrs, "delete-action"));
            valuemd.setUpdateAction(getAttr(attrs, "update-action"));
            valuemd.setIndexed(IndexedValue.getIndexedValue(getAttr(attrs, "indexed")));
            valuemd.setUnique(MetaDataUtils.getBooleanForString(getAttr(attrs, "unique"), false));
            valuemd.setMappedBy(getAttr(attrs, "mapped-by"));
            String converterAttr = getAttr(attrs, "converter");
            String disableConverterAttr = getAttr(attrs, "use-default-conversion");
            if (disableConverterAttr != null && Boolean.getBoolean(disableConverterAttr)) {
            // TODO Disable on the value?
            } else if (!StringUtils.isWhitespace(converterAttr)) {
                TypeManager typeMgr = mmgr.getNucleusContext().getTypeManager();
                ClassLoaderResolver clr = mmgr.getNucleusContext().getClassLoaderResolver(null);
                Class converterCls = clr.classForName(converterAttr);
                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);
                    // TODO value type
                    Class attrType = JDOTypeConverterUtils.getAttributeTypeForAttributeConverter(converterCls, null);
                    Class dbType = JDOTypeConverterUtils.getDatastoreTypeForAttributeConverter(converterCls, attrType, null);
                    // Register the TypeConverter under the name of the AttributeConverter class
                    JDOTypeConverter typeConv = new JDOTypeConverter(conv);
                    typeMgr.registerConverter(converterAttr, typeConv, attrType, dbType, false, null);
                }
                valuemd.addExtension(MetaData.EXTENSION_MEMBER_TYPE_CONVERTER_NAME, converterAttr);
            }
            fmd.setValueMetaData(valuemd);
            pushStack(valuemd);
        } else // New fetch-group
        if (localName.equals("fetch-group")) {
            MetaData md = getStack();
            FetchGroupMetaData fgmd = new FetchGroupMetaData(getAttr(attrs, "name"));
            String postLoadStr = getAttr(attrs, "post-load");
            if (!StringUtils.isWhitespace(postLoadStr)) {
                fgmd.setPostLoad(Boolean.valueOf(postLoadStr));
            }
            if (md instanceof FetchGroupMetaData) {
                FetchGroupMetaData fgmdParent = (FetchGroupMetaData) md;
                fgmdParent.addFetchGroup(fgmd);
            } else if (md instanceof AbstractClassMetaData) {
                AbstractClassMetaData cmd = (AbstractClassMetaData) md;
                cmd.addFetchGroup(fgmd);
            } else if (md instanceof FetchPlanMetaData) {
                FetchPlanMetaData fpmd = (FetchPlanMetaData) md;
                fpmd.addFetchGroup(fgmd);
            }
            pushStack(fgmd);
        } else if (localName.equals("extension")) {
            MetaData md = getStack();
            String vendorName = getAttr(attrs, "vendor-name");
            if (StringUtils.isWhitespace(vendorName)) {
                throw new InvalidMetaDataException("044160", vendorName, getAttr(attrs, "key"), getAttr(attrs, "value"));
            }
            if (vendorName != null && vendorName.equalsIgnoreCase(MetaData.VENDOR_NAME)) {
                md.addExtension(getAttr(attrs, "key"), getAttr(attrs, "value"));
            }
        } else if (localName.equals("version")) {
            AbstractClassMetaData cmd = (AbstractClassMetaData) getStack();
            VersionMetaData vermd = cmd.newVersionMetadata();
            String strategy = getAttr(attrs, "strategy");
            if (!StringUtils.isWhitespace(strategy)) {
                vermd.setStrategy(strategy);
            }
            vermd.setColumnName(getAttr(attrs, "column"));
            vermd.setIndexed(IndexedValue.getIndexedValue(getAttr(attrs, "indexed")));
            pushStack(vermd);
        } else if (localName.equals("index")) {
            MetaData md = getStack();
            IndexMetaData idxmd = new IndexMetaData();
            idxmd.setName(getAttr(attrs, "name"));
            idxmd.setTable(getAttr(attrs, "table"));
            String uniStr = getAttr(attrs, "unique");
            if (!StringUtils.isWhitespace(uniStr)) {
                idxmd.setUnique(Boolean.valueOf(uniStr));
            }
            if (md instanceof AbstractClassMetaData) {
                AbstractClassMetaData cmd = (AbstractClassMetaData) md;
                cmd.addIndex(idxmd);
            } else if (md instanceof AbstractMemberMetaData) {
                AbstractMemberMetaData fmd = (AbstractMemberMetaData) md;
                fmd.setIndexMetaData(idxmd);
            } else if (md instanceof JoinMetaData) {
                JoinMetaData jmd = (JoinMetaData) md;
                jmd.setIndexMetaData(idxmd);
            } else if (md instanceof AbstractElementMetaData) {
                AbstractElementMetaData elmd = (AbstractElementMetaData) md;
                elmd.setIndexMetaData(idxmd);
            } else if (md instanceof OrderMetaData) {
                OrderMetaData omd = (OrderMetaData) md;
                omd.setIndexMetaData(idxmd);
            } else if (md instanceof VersionMetaData) {
                VersionMetaData vermd = (VersionMetaData) md;
                vermd.setIndexMetaData(idxmd);
            } else if (md instanceof DiscriminatorMetaData) {
                DiscriminatorMetaData dismd = (DiscriminatorMetaData) md;
                dismd.setIndexMetaData(idxmd);
            }
            pushStack(idxmd);
        } else if (localName.equals("unique")) {
            MetaData md = getStack();
            UniqueMetaData unimd = new UniqueMetaData();
            unimd.setName(getAttr(attrs, "name"));
            unimd.setTable(getAttr(attrs, "table"));
            String defStr = getAttr(attrs, "deferred");
            if (!StringUtils.isWhitespace(defStr)) {
                unimd.setDeferred(Boolean.valueOf(defStr));
            }
            if (md instanceof AbstractClassMetaData) {
                AbstractClassMetaData cmd = (AbstractClassMetaData) md;
                cmd.addUniqueConstraint(unimd);
            } else if (md instanceof AbstractMemberMetaData) {
                AbstractMemberMetaData fmd = (AbstractMemberMetaData) md;
                fmd.setUniqueMetaData(unimd);
            } else if (md instanceof JoinMetaData) {
                JoinMetaData jmd = (JoinMetaData) md;
                jmd.setUniqueMetaData(unimd);
            } else if (md instanceof AbstractElementMetaData) {
                AbstractElementMetaData elmd = (AbstractElementMetaData) md;
                elmd.setUniqueMetaData(unimd);
            }
            pushStack(unimd);
        } else if (localName.equals("foreign-key")) {
            MetaData md = getStack();
            ForeignKeyMetaData fkmd = new ForeignKeyMetaData();
            fkmd.setName(getAttr(attrs, "name"));
            fkmd.setTable(getAttr(attrs, "table"));
            fkmd.setUnique(getAttr(attrs, "unique"));
            fkmd.setDeferred(getAttr(attrs, "deferred"));
            fkmd.setDeleteAction(ForeignKeyAction.getForeignKeyAction(getAttr(attrs, "delete-action")));
            fkmd.setUpdateAction(ForeignKeyAction.getForeignKeyAction(getAttr(attrs, "update-action")));
            if (md instanceof AbstractClassMetaData) {
                AbstractClassMetaData cmd = (AbstractClassMetaData) md;
                cmd.addForeignKey(fkmd);
            } else if (md instanceof AbstractMemberMetaData) {
                AbstractMemberMetaData fmd = (AbstractMemberMetaData) md;
                fmd.setForeignKeyMetaData(fkmd);
            } else if (md instanceof JoinMetaData) {
                JoinMetaData jmd = (JoinMetaData) md;
                jmd.setForeignKeyMetaData(fkmd);
            } else if (md instanceof AbstractElementMetaData) {
                AbstractElementMetaData elmd = (AbstractElementMetaData) md;
                elmd.setForeignKeyMetaData(fkmd);
            }
            pushStack(fkmd);
        } else if (localName.equals("order")) {
            OrderMetaData ordmd = new OrderMetaData();
            ordmd.setIndexed(IndexedValue.getIndexedValue(getAttr(attrs, "indexed")));
            ordmd.setColumnName(getAttr(attrs, "column"));
            ordmd.setMappedBy(getAttr(attrs, "mapped-by"));
            AbstractMemberMetaData fmd = (AbstractMemberMetaData) getStack();
            fmd.setOrderMetaData(ordmd);
            pushStack(ordmd);
        } else if (localName.equals("embedded")) {
            MetaData md = getStack();
            EmbeddedMetaData embmd = new EmbeddedMetaData();
            embmd.setOwnerMember(getAttr(attrs, "owner-field"));
            embmd.setNullIndicatorColumn(getAttr(attrs, "null-indicator-column"));
            embmd.setNullIndicatorValue(getAttr(attrs, "null-indicator-value"));
            if (md instanceof AbstractMemberMetaData) {
                AbstractMemberMetaData fmd = (AbstractMemberMetaData) md;
                fmd.setEmbeddedMetaData(embmd);
            } else if (md instanceof KeyMetaData) {
                KeyMetaData kmd = (KeyMetaData) md;
                kmd.setEmbeddedMetaData(embmd);
            } else if (md instanceof ValueMetaData) {
                ValueMetaData vmd = (ValueMetaData) md;
                vmd.setEmbeddedMetaData(embmd);
            } else if (md instanceof ElementMetaData) {
                ElementMetaData elmd = (ElementMetaData) md;
                elmd.setEmbeddedMetaData(embmd);
            }
            pushStack(embmd);
        } else {
            String message = Localiser.msg("044037", qName);
            NucleusLogger.METADATA.error(message);
            throw new RuntimeException(message);
        }
    } catch (RuntimeException ex) {
        NucleusLogger.METADATA.error(Localiser.msg("044042", qName, getStack(), uri), ex);
        throw ex;
    }
}
Also used : InvalidMetaDataException(org.datanucleus.metadata.InvalidMetaDataException) VersionMetaData(org.datanucleus.metadata.VersionMetaData) ElementMetaData(org.datanucleus.metadata.ElementMetaData) AbstractElementMetaData(org.datanucleus.metadata.AbstractElementMetaData) JDOTypeConverter(org.datanucleus.api.jdo.JDOTypeConverter) FetchPlanMetaData(org.datanucleus.metadata.FetchPlanMetaData) CollectionMetaData(org.datanucleus.metadata.CollectionMetaData) ImplementsMetaData(org.datanucleus.metadata.ImplementsMetaData) IdentityMetaData(org.datanucleus.metadata.IdentityMetaData) InheritanceMetaData(org.datanucleus.metadata.InheritanceMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) SequenceMetaData(org.datanucleus.metadata.SequenceMetaData) OrderMetaData(org.datanucleus.metadata.OrderMetaData) AttributeConverter(javax.jdo.AttributeConverter) InvalidClassMetaDataException(org.datanucleus.metadata.InvalidClassMetaDataException) FieldMetaData(org.datanucleus.metadata.FieldMetaData) CollectionMetaData(org.datanucleus.metadata.CollectionMetaData) ElementMetaData(org.datanucleus.metadata.ElementMetaData) FetchPlanMetaData(org.datanucleus.metadata.FetchPlanMetaData) IdentityMetaData(org.datanucleus.metadata.IdentityMetaData) JoinMetaData(org.datanucleus.metadata.JoinMetaData) MetaData(org.datanucleus.metadata.MetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) UniqueMetaData(org.datanucleus.metadata.UniqueMetaData) KeyMetaData(org.datanucleus.metadata.KeyMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) FetchGroupMetaData(org.datanucleus.metadata.FetchGroupMetaData) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) PackageMetaData(org.datanucleus.metadata.PackageMetaData) EmbeddedMetaData(org.datanucleus.metadata.EmbeddedMetaData) InheritanceMetaData(org.datanucleus.metadata.InheritanceMetaData) OrderMetaData(org.datanucleus.metadata.OrderMetaData) FetchGroupMemberMetaData(org.datanucleus.metadata.FetchGroupMemberMetaData) FileMetaData(org.datanucleus.metadata.FileMetaData) FieldMetaData(org.datanucleus.metadata.FieldMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData) ImplementsMetaData(org.datanucleus.metadata.ImplementsMetaData) VersionMetaData(org.datanucleus.metadata.VersionMetaData) SequenceMetaData(org.datanucleus.metadata.SequenceMetaData) QueryMetaData(org.datanucleus.metadata.QueryMetaData) AbstractElementMetaData(org.datanucleus.metadata.AbstractElementMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) ArrayMetaData(org.datanucleus.metadata.ArrayMetaData) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) MapMetaData(org.datanucleus.metadata.MapMetaData) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) IndexMetaData(org.datanucleus.metadata.IndexMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) ValueMetaData(org.datanucleus.metadata.ValueMetaData) ValueMetaData(org.datanucleus.metadata.ValueMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) AbstractElementMetaData(org.datanucleus.metadata.AbstractElementMetaData) ColumnMetaData(org.datanucleus.metadata.ColumnMetaData) FileMetaData(org.datanucleus.metadata.FileMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData) KeyMetaData(org.datanucleus.metadata.KeyMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) ForeignKeyMetaData(org.datanucleus.metadata.ForeignKeyMetaData) PackageMetaData(org.datanucleus.metadata.PackageMetaData) FetchGroupMemberMetaData(org.datanucleus.metadata.FetchGroupMemberMetaData) NucleusUserException(org.datanucleus.exceptions.NucleusUserException) EmbeddedMetaData(org.datanucleus.metadata.EmbeddedMetaData) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) UniqueMetaData(org.datanucleus.metadata.UniqueMetaData) MapMetaData(org.datanucleus.metadata.MapMetaData) PrimaryKeyMetaData(org.datanucleus.metadata.PrimaryKeyMetaData) IndexedValue(org.datanucleus.metadata.IndexedValue) IndexMetaData(org.datanucleus.metadata.IndexMetaData) DiscriminatorMetaData(org.datanucleus.metadata.DiscriminatorMetaData) QueryMetaData(org.datanucleus.metadata.QueryMetaData) ArrayMetaData(org.datanucleus.metadata.ArrayMetaData) PersistenceNucleusContext(org.datanucleus.PersistenceNucleusContext) TypeManager(org.datanucleus.store.types.TypeManager) InterfaceMetaData(org.datanucleus.metadata.InterfaceMetaData) JoinMetaData(org.datanucleus.metadata.JoinMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) FetchGroupMetaData(org.datanucleus.metadata.FetchGroupMetaData)

Example 15 with ElementMetaData

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

the class AnnotationPlusXMLTest method testOneToManyBiJoin.

/**
 * Test of JPA 1-N unidir FK relation.
 * This is really a 1-N uni join since JPA doesnt support 1-N uni FK.
 */
/*public void testOneToManyUniFK()
    {
        NucleusContext nucleusCtx = new NucleusContext("JPA", null);
        ClassLoaderResolver clr = new ClassLoaderResolverImpl();
        MetaDataManager metaDataMgr = new JPAMetaDataManager(pmfcontext);
        PersistenceUnitMetaData pumd = metaDataMgr.getMetaDataForPersistenceUnit("JPATest");
        metaDataMgr.initialise(pumd, clr);

        // owner side
        ClassMetaData cmd1 = (ClassMetaData)metaDataMgr.getMetaDataForClass(Site.class.getName(), clr);
        AbstractMemberMetaData fmd1 = cmd1.getMetaDataForMember("offices");
        assertNotNull("Site.offices is null!", fmd1);
        assertEquals("Site.offices mapped-by is incorrect", fmd1.getMappedBy(), null);
        assertEquals("Site.offices relationType is incorrect",
            fmd1.getRelationType(clr), Relation.ONE_TO_MANY_UNI);
        assertEquals("Site.offices jointable name is incorrect", fmd1.getTable(), null);
        assertNotNull("Site.offices should have join but doesnt", fmd1.getJoinMetaData());

        ElementMetaData elemmd = fmd1.getElementMetaData();
        assertNotNull("Site.offices has no element column info but should", elemmd);
        ColumnMetaData[] colmds = elemmd.getColumnMetaData();
        assertNotNull("Site.offices has incorrect element columns", colmds);
        assertEquals("Site.offices has incorrect number of element columns", colmds.length, 1);
        assertEquals("Site.offices has incorrect element column name", colmds[0].getName(), "SITE_ID");
    }*/
/**
 * Test of JPA 1-N bidir JoinTable relation
 */
public void testOneToManyBiJoin() {
    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(Manager.class.getName(), clr);
    assertEquals("Manager has incorrect table name", cmd1.getTable(), "JPA_AX_MANAGER");
    AbstractMemberMetaData fmd1 = cmd1.getMetaDataForMember("subordinates");
    assertNotNull("Manager.subordinates is null!", fmd1);
    assertEquals("Manager.subordinates mapped-by is incorrect", fmd1.getMappedBy(), "manager");
    assertEquals("Manager.subordinates relationType is incorrect", fmd1.getRelationType(clr), RelationType.ONE_TO_MANY_BI);
    assertEquals("Manager.subordinates jointable name is incorrect", fmd1.getTable(), "JPA_AX_MGR_EMPLOYEES");
    // non-owner side
    ClassMetaData cmd2 = (ClassMetaData) metaDataMgr.getMetaDataForClass(Employee.class.getName(), clr);
    assertEquals("Employee has incorrect table name", cmd2.getTable(), "JPA_AX_EMPLOYEE");
    AbstractMemberMetaData fmd2 = cmd2.getMetaDataForMember("manager");
    assertNotNull("Employee.manager is null!", fmd2);
    assertEquals("Employee.manager mapped-by is incorrect", fmd2.getMappedBy(), null);
    assertEquals("Employee.manager relationType is incorrect", fmd2.getRelationType(clr), RelationType.MANY_TO_ONE_BI);
    assertEquals("Employee.manager jointable name is incorrect", fmd2.getTable(), null);
    // join-table
    JoinMetaData joinmd = fmd1.getJoinMetaData();
    assertNotNull("Manager.subordinates has no join table!", joinmd);
    assertNotNull("Manager.subordinates has incorrect join columns", joinmd.getColumnMetaData());
    assertEquals("Manager.subordinates has incorrect number of join columns", 1, joinmd.getColumnMetaData().length);
    assertEquals("Manager.subordinates has incorrect owner join column name", "MGR_ID", joinmd.getColumnMetaData()[0].getName());
    ElementMetaData elemmd = fmd1.getElementMetaData();
    assertNotNull("Manager.subordinates has no element column info but should", elemmd);
    assertNotNull("Manager.subordinates has incorrect element columns", elemmd.getColumnMetaData());
    assertEquals("Manager.subordinates has incorrect number of element columns", 1, elemmd.getColumnMetaData().length);
    assertEquals("Manager.subordinates has incorrect element join column name", "EMP_ID", elemmd.getColumnMetaData()[0].getName());
}
Also used : JPAMetaDataManager(org.datanucleus.api.jpa.metadata.JPAMetaDataManager) ElementMetaData(org.datanucleus.metadata.ElementMetaData) NucleusContext(org.datanucleus.NucleusContext) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) JPAMetaDataManager(org.datanucleus.api.jpa.metadata.JPAMetaDataManager) MetaDataManager(org.datanucleus.metadata.MetaDataManager) PersistenceNucleusContextImpl(org.datanucleus.PersistenceNucleusContextImpl) JoinMetaData(org.datanucleus.metadata.JoinMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) PersistenceUnitMetaData(org.datanucleus.metadata.PersistenceUnitMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData)

Aggregations

ElementMetaData (org.datanucleus.metadata.ElementMetaData)22 AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)16 ClassMetaData (org.datanucleus.metadata.ClassMetaData)14 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)13 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)13 NucleusContext (org.datanucleus.NucleusContext)12 PersistenceNucleusContextImpl (org.datanucleus.PersistenceNucleusContextImpl)12 JPAMetaDataManager (org.datanucleus.api.jpa.metadata.JPAMetaDataManager)12 JoinMetaData (org.datanucleus.metadata.JoinMetaData)12 MetaDataManager (org.datanucleus.metadata.MetaDataManager)12 PersistenceUnitMetaData (org.datanucleus.metadata.PersistenceUnitMetaData)12 PrimaryKeyMetaData (org.datanucleus.metadata.PrimaryKeyMetaData)4 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)3 IndexMetaData (org.datanucleus.metadata.IndexMetaData)3 AttributeConverter (javax.jdo.AttributeConverter)2 PersistenceNucleusContext (org.datanucleus.PersistenceNucleusContext)2 JDOTypeConverter (org.datanucleus.api.jdo.JDOTypeConverter)2 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)2 ArrayMetaData (org.datanucleus.metadata.ArrayMetaData)2 CollectionMetaData (org.datanucleus.metadata.CollectionMetaData)2