alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Glassfish example source code file (MappingFile.java)

This example Glassfish source code file (MappingFile.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Glassfish tags/keywords

columnelement, columnpair, conversionexception, conversionexception, dbexception, io, list, map, modelexception, modelexception, noi18n, noi18n, string, string, tableelement, text, util

The Glassfish MappingFile.java source code

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

/*
 * MappingFile.java
 *
 * Created on February 1, 2002, 9:47 PM
 */

package com.sun.jdo.api.persistence.mapping.ejb;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.File;

import java.util.Collection;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.ResourceBundle;
import java.util.Iterator;
import java.io.IOException;

import java.text.MessageFormat;

import org.netbeans.modules.dbschema.*;

import com.sun.jdo.api.persistence.mapping.ejb.beans.*;
import com.sun.jdo.spi.persistence.utility.StringHelper;
import com.sun.jdo.api.persistence.model.*;
import com.sun.jdo.api.persistence.model.mapping.*;
import com.sun.jdo.api.persistence.model.mapping.impl.*;
import com.sun.jdo.api.persistence.model.jdo.*;
import com.sun.jdo.api.persistence.model.jdo.impl.*;
import com.sun.jdo.spi.persistence.utility.logging.Logger;
import org.glassfish.persistence.common.I18NHelper;

import org.netbeans.modules.schema2beans.Schema2BeansException;

/** This class supports the conversion between the iAS mapping file
 * format and the object used to represent that mapping to support
 * the iAS EJBC process and iAS CMP run-time.
 *
 * @author vbk
 * @version 1.0
 */
public class MappingFile {

    private static final String JAVA_TYPE_SET = "java.util.Set"; //NOI18N
    private static final String JAVA_TYPE_COLLECTION = "java.util.Collection"; //NOI18N
    private static final List types = new ArrayList();

    /** Definitive location for a  mapping file in an ejb-jar file. */
    public static final String DEFAULT_LOCATION_IN_EJB_JAR;

    /** The logger */
    private static final Logger logger =
        LogHelperMappingConversion.getLogger();

    /**
     * I18N message handler
     */
    private final static ResourceBundle messages = I18NHelper.loadBundle(
            MappingFile.class);

    static {
        types.add(JAVA_TYPE_SET);
        types.add(JAVA_TYPE_COLLECTION);

        DEFAULT_LOCATION_IN_EJB_JAR = new StringBuffer(I18NHelper.getMessage(
            messages, "CONST_IAS_MAPPING_FILE_LOC")). //NOI18N
            append(File.separator).
            append(I18NHelper.getMessage(
            messages, "CONST_IAS_MAPPING_FILE")).toString(); //NOI18N
    }

    private Map inverseRelationships = null;
    private Map namedGroups = null;
    private int groupCount = MappingFieldElement.GROUP_INDEPENDENT;

    private ClassLoader classLoader = null;

    private static int MINIMUM_PRECISION = 19;

    /**
     * An object which implements ConversionHelper interface to
     * access data from other available sources to support the mapping
     * generation.
     */
    private ConversionHelper helper = null;

    private HashMap loadedSchema = new HashMap();

    /** Creates new MappingFile */
    public  MappingFile() {
        classLoader = null;
    }

    /** Creates new MappingFile */
    public  MappingFile(ClassLoader cl) {
        this();
        classLoader = cl;
    }

    /** Convert an SunCmpMapping object into the equivelent collection of
     * MappingClassElement objects
     * @param content An SunCmpMapping object that describes a mapping
     * for one or more beans
     * @param helper An object which implements ConversionHelper interface to
     * access data from other available sources to support the mapping
     * generation
     * @return A Collection of MappingClassElement objects
     * @throws DBException
     * @throws ModelException
     * @throws ConversionException 
     */
    public Map intoMappingClasses(SunCmpMappings content,
        ConversionHelper helper)
        throws DBException, ModelException, ConversionException {
        Map mces = new java.util.HashMap();
        this.helper = helper;
        boolean ensureValidation = helper.ensureValidation();

        for (int i = 0; i < content.sizeSunCmpMapping(); i++) {
            SunCmpMapping beanSet = content.getSunCmpMapping(i);
            inverseRelationships = new HashMap();
            namedGroups = new HashMap();
            String schema = beanSet.getSchema();

            if (helper.generateFields()) {

                // sweep through the mappings to complete them
                completeCmrMappings(beanSet);
            }

            // process bean mapping and fields mapping
            for (int k = 0; k < beanSet.sizeEntityMapping(); k++) {
                EntityMapping beanMapping = beanSet.getEntityMapping(k);
                MappingClassElement aTpMapping = null;
                if (ensureValidation) {
                    aTpMapping = mapFieldsOfBean(beanMapping, schema);
                }
                else {
                    try {
                        aTpMapping = mapFieldsOfBean(beanMapping, schema);
                    }
                    catch (ConversionException t) {
                        if (logger.isLoggable(Logger.FINE))
                            logger.fine(
                                I18NHelper.getMessage(
                                messages,
                                "MESSAGE_CONV_EXC", //NOI18N
                                t.toString()));
                    }
                }

                mces.put(beanMapping.getEjbName(), aTpMapping);
            }
        }
        return mces;
    }

    /** Convert an SunCmpMapping object into the equivelent collection of
     * MappingClassElement objects
     * @param content An InputStream that contains an xml data stream that
     * conforms to the sun-cmp-mapping.dtd
     * @param helper An object which implements ConversionHelper interface to
     * access data from other available sources to support the mapping
     * generation
     * @return A Collection of MappingClassElement objects
     * @throws DBException
     * @throws ModelException
     * @throws ConversionException
     */
    public Map intoMappingClasses(InputStream content, ConversionHelper helper)
        throws DBException, ModelException, ConversionException {
        SunCmpMappings foo = null;
        try {
            foo = SunCmpMappings.createGraph(content);
        }
        catch (Schema2BeansException t) {
            if (helper.ensureValidation()) {
                throw new ConversionException(
                    I18NHelper.getMessage(messages,
                    "XML_ERROR_IN_MAPPING_FILE", //NOI18N
                    DEFAULT_LOCATION_IN_EJB_JAR));
            }
            foo = SunCmpMappings.createGraph();
        }

        return intoMappingClasses(foo, helper);
    }

    /** Creates an SunCmpMapping object from a Collection of
     * MappingClassElement objects
     * @param dest The output for processing
     * @param mappingClasses The Collection of MappingClassElements
     * @param helper An object which implements ConversionHelper interface to
     * access data from other available sources to support the mapping
     * generation
     * @throws IOException Thrown if there is a problem
     * sending the data out on <CODE>dest.
     * @throws Schema2BeansException
     */
    public void fromMappingClasses(OutputStream dest, Map mappingClasses,
        ConversionHelper helper)
        throws IOException, Schema2BeansException {
        SunCmpMappings tmp = fromMappingClasses(mappingClasses, helper);
        tmp.write(dest);
    }

    /** Creates an SunCmpMapping object from a Collection of
     * MappingClassElement objects
     * @param mappingClasses The Collection of MappingClassElements
     * @param helper An object which implements ConversionHelper interface to
     * access data from other available sources to support the mapping
     * generation.
     * @return The SunCmpMapping object that is equivelent to the
     * collection of MappingClassElements.
     * throws Schema2BeansException
     */
    public SunCmpMappings fromMappingClasses(Map mappingClasses,
        ConversionHelper helper) throws Schema2BeansException {
        Iterator keyIter = mappingClasses.keySet().iterator();
        Map mapOfMapping = new java.util.HashMap();
        while (keyIter.hasNext()) {
            String ejbName = (String) keyIter.next();
            MappingClassElement mce = (MappingClassElement)
                mappingClasses.get(ejbName);
            EntityMapping beanMapping = new EntityMapping();

            if (null != mce) {
                setConsistency(mce, beanMapping);

                String schemaName = mce.getDatabaseRoot();
                SunCmpMapping aMapping = (SunCmpMapping) mapOfMapping.get(
                    schemaName);
                if (null == aMapping) {
                    aMapping = new SunCmpMapping();
                    aMapping.setSchema(schemaName);
                    mapOfMapping.put(schemaName, aMapping);
                }
                List tables = mce.getTables();
                MappingTableElement primary = null;
                if (tables.size() > 0) {
                    primary = (MappingTableElement) tables.get(0);
                    beanMapping.setTableName(primary.getName());
                }
                beanMapping.setEjbName(ejbName);
                if (null != primary) {
                    List refKeys = primary.getReferencingKeys();
                    for (int i = 0; refKeys != null && i < refKeys.size(); i++) {
                        SecondaryTable sT = new SecondaryTable();
                        MappingReferenceKeyElement mrke =
                            (MappingReferenceKeyElement) refKeys.get(i);
                        MappingTableElement mte = mrke.getTable();
                        if (null != mte) {
                            sT.setTableName(mte.getName());
                            List cpnames = mrke.getColumnPairNames();
                            boolean hasPairs = false;
                            for (int j = 0; cpnames != null &&
                                j < cpnames.size(); j++) {
                                List token =
                                    StringHelper.separatedListToArray((String)cpnames.get(j),";"); //NOI18N
                                ColumnPair cp = new ColumnPair();
                                Iterator iter = token.iterator();
                                while (iter.hasNext()) {
                                    String columnName = (String)iter.next();
                                    cp.addColumnName(columnName);
                                }
                                sT.addColumnPair(cp);
                                hasPairs = true;
                            }
                            if (hasPairs)
                                beanMapping.addSecondaryTable(sT);
                            else
                                if (logger.isLoggable(Logger.FINE))
                                    logger.fine( 
                                        I18NHelper.getMessage(
                                        messages,
                                        "WARN_ILLEGAL_PAIR", //NOI18N
                                        new Object [] {ejbName, mte.getName(), cpnames}));
                        }
                        else {
                            if (logger.isLoggable(Logger.FINE))
                                logger.fine(
                                    I18NHelper.getMessage(
                                    messages,
                                    "WARN_MISSING_TABLE", //NOI18N
                                    new Object [] {ejbName, primary.getName()}));
                        }
                    }
                }
                else {
                    if (logger.isLoggable(Logger.FINE))
                        logger.fine(
                            I18NHelper.getMessage(
                            messages,
                            "WARN_NO_PRIMARY", //NOI18N
                            ejbName));
                }

                // transform the field mappings
                PersistenceClassElement pce = null;
                PersistenceFieldElement pfields[] = null;
                if (mce instanceof MappingClassElementImpl) {
                    MappingClassElementImpl mcei =
                        (MappingClassElementImpl) mce;
                    pce = mcei.getPersistenceElement();
                    pfields = pce.getFields();
                }
                int len = 0;
                if (null != pfields)
                    len = pfields.length;
                for (int i = 0; i < len; i++) {
                    PersistenceFieldElement pfield = pfields[i];
                    String fieldName = pfield.getName();
                    if (helper.isGeneratedField(ejbName, fieldName)) {
                        continue;
                    }
                    if (pfield instanceof RelationshipElement) {
                        MappingRelationshipElement mre =
                            (MappingRelationshipElement) mce.getField(fieldName);
                        MappingFieldElement mfe = mre;
                        CmrFieldMapping cfm = new CmrFieldMapping();
                        cfm.setCmrFieldName(fieldName);
                        List cols = null;
                        if (null != mfe) {
                            cols = mfe.getColumns();
                            int fgVal = mfe.getFetchGroup();
                            setFetchedWith(cfm, fgVal);
                        }
                        for (int j = 0; null != cols && j < cols.size(); j++) {
                            String cpstring = (String) cols.get(j);
                            int slen = cpstring.indexOf(';');
                            ColumnPair cp = new ColumnPair();
                            cp.addColumnName(cpstring.substring(0,slen));
                            cp.addColumnName(cpstring.substring(slen+1));
                            cfm.addColumnPair(cp);
                        }
                        if (null != mre)
                            cols = mre.getAssociatedColumns();
                        for (int j = 0; null != cols && j < cols.size(); j++) {
                            String cpstring = (String) cols.get(j);
                            int slen = cpstring.indexOf(';');
                            ColumnPair cp = new ColumnPair();
                            cp.addColumnName(cpstring.substring(0,slen));
                            cp.addColumnName(cpstring.substring(slen+1));
                            cfm.addColumnPair(cp);
                        }
                        beanMapping.addCmrFieldMapping(cfm);
                    }
                    else {
                        MappingFieldElement mfe = mce.getField(fieldName);
                        CmpFieldMapping cfm = new CmpFieldMapping();
                        cfm.setFieldName(fieldName);
                        List cols = null;
                        if (null != mfe) {
                            cols = mfe.getColumns();
                            for (int j = 0; null != cols &&
                                j < cols.size(); j++) {
                                cfm.addColumnName((String)cols.get(j));
                            }
                            int fgVal = mfe.getFetchGroup();
                            setFetchedWith(cfm,fgVal);
                        }
                        beanMapping.addCmpFieldMapping(cfm);
                    }
                }
                aMapping.addEntityMapping(beanMapping);
            }
        }
        SunCmpMappings retVal = null;
        retVal = new SunCmpMappings();
        Iterator mapOfMappingIter = mapOfMapping.values().iterator();
        while (mapOfMappingIter.hasNext()) {
            SunCmpMapping aVal = (SunCmpMapping) mapOfMappingIter.next();
            retVal.addSunCmpMapping(aVal);
        }
        return retVal;
    }

    /** Set fetchgroup in schema2beans FetchedWith bean
     * @param cfm An object that represents HasFetchedWith object
     * in schema2beans
     * @param fgVal integer that represents fetch group value
     */
    private void setFetchedWith(HasFetchedWith cfm, int fgVal) {
        FetchedWith fw = new FetchedWith();
        if (fgVal <= MappingFieldElement.GROUP_INDEPENDENT) {
            String key = "IndependentFetchGroup"+fgVal; //NOI18N
            fw.setNamedGroup(key);
        }
        else if (fgVal == MappingFieldElement.GROUP_DEFAULT) {
            fw.setDefault(true);
        }
        else if (fgVal > MappingFieldElement.GROUP_DEFAULT) {
            fw.setLevel(fgVal-1);
        }
        else if (fgVal == MappingFieldElement.GROUP_NONE) {
            fw.setNone(true);
        }
        cfm.setFetchedWith(fw);
    }

    /** Convert a bean's cmp-field-mapping and cmr-field-mapping elements into
     * mapping model objects.
     *
     * The method can be called in two distinct cases:
     *
     * 1. At deployment time. The mapping must be complete enough to create a
     * valid mapping model, in order to support execution.
     *
     * 2. During mapping development.  The mapping may be incomplete, but the
     * model objects that are created need to be as consistent as possible.
     * The absence of data should not be fatal, if possible.
     *
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param schemaArg The name of the schema that the bean is mapped against.
     * @return The MappingClassElement that corresponds to the
     * schema2beans object.
     * @throws DBException
     * @throws ModelException
     * @throws ConversionException
     */
    private MappingClassElement mapFieldsOfBean(EntityMapping mapping,
                                                String schemaArg)
        throws DBException, ModelException, ConversionException {

        String beanName = mapping.getEjbName();
        MappingClassElement mce = null;
        List tablesOfBean = new ArrayList();
        Map knownTables = new HashMap();

        if (logger.isLoggable(Logger.FINE))
            logger.fine(
                I18NHelper.getMessage(
                messages,
                "MESSAGE_START_BEAN", //NOI18N
                beanName));

        String jdoClassName = helper.getMappedClassName(beanName);
        if (logger.isLoggable(Logger.FINE))
            logger.fine(
                I18NHelper.getMessage(
                messages,
                "MESSAGE_JDOCLASS_NAME", //NOI18N
                beanName, jdoClassName));

        if (null == jdoClassName) {
            throw new ConversionException(
                I18NHelper.getMessage(
                messages,
                "ERR_INVALID_CLASS", //NOI18N
                beanName));
        }

        // create the mapping class element and its children
        PersistenceClassElementImpl persistElImpl =
            new PersistenceClassElementImpl(jdoClassName);
        persistElImpl.setKeyClass(jdoClassName+".Oid"); //NOI18N
        mce = new MappingClassElementImpl(
            new PersistenceClassElement(persistElImpl));

        SchemaElement schema = null;

        // Assign the schema
        if (!StringHelper.isEmpty(schemaArg))
            schema = setDatabaseRoot(mce, schemaArg,
                helper.ensureValidation());

        // Map the table information
        // Ensure the bean is mapped to a primary table.
        if (!StringHelper.isEmpty(mapping.getTableName())) {

            mapPrimaryTable(mapping, mce,
                schema, knownTables, tablesOfBean);
            mapSecondaryTables(mapping, mce,
                schema, knownTables, tablesOfBean);
        }

        ColumnElement candidatePK = null;

        // map the simple fields.
        candidatePK = mapNonRelationshipFields(mapping, mce,
            beanName, schema, knownTables);

        createMappingForUnknownPKClass(mapping, mce,
            beanName, candidatePK);

        createMappingForConsistency(mapping, mce,
            beanName, knownTables);

        // map the relationship fields.
        mapRelationshipFields(mapping, mce,
            beanName, schema, knownTables, tablesOfBean);

        // map any unmapped fields.
        mapUnmappedFields(mce, beanName);

        return mce;
    }

    /** Create field mapping for unknown primary key
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce Mapping class element
     * @param beanName Bean name
     * @param candidatePK A ColumnElement object which is a candidate column for
     * mapping to primary key field if it is unknown primary key
     * @throws ModelException
     * @throws ConversionException
     */
    private void createMappingForUnknownPKClass(EntityMapping mapping,
                                                MappingClassElement mce,
                                                String beanName,
                                                ColumnElement candidatePK)
        throws ModelException, ConversionException {
        String primaryTableName = mapping.getTableName();

        if (helper.generateFields()
            && helper.applyDefaultUnknownPKClassStrategy(beanName)) {
            if (null != candidatePK) {
                String fieldName = helper.getGeneratedPKFieldName();

                // Fix later. Since mapping and persistence classes in the
                // cache are only skeletons and not the one we want,
                // put pce in a map at pce creation time for persistence
                // class look up later to avoid a cast
                // to MappingClassElementImpl.
                PersistenceFieldElement pfe = createPersistenceField(mce,
                    fieldName);
                pfe.setKey(true);
                MappingFieldElement mfe = createMappingField(mce, fieldName,
                    candidatePK);
            }
            else {
                // There is no column which meets primary key criteria.
                // Report error.
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "WARN_NO_PKCOLUMN", //NOI18N
                    primaryTableName));
            }
        }
    }

    /** Load the consistency information. if it is version consistency, create
     * field mapping for version columns.
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce Mapping class element
     * @param beanName Bean name
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @throws ModelException
     * @throws DBException
     * @throws ConversionException
     */
    private void createMappingForConsistency(EntityMapping mapping,
                                             MappingClassElement mce,
                                             String beanName,
                                             Map knownTables)
        throws ModelException, DBException, ConversionException {

        // load the consistency information
        List versionColumns = loadConsistency(mapping, mce);

        // If the consistency level is version consistency, the version field
        // is always created, independent of the ConversionHelper's value for
        // generateFields.  This is because a generated version field is
        // needed to hold the version column information.
        if (versionColumns != null) {

            String primaryTableName = mapping.getTableName();

            // For 8.1 release, we only support one version column per bean
            if (versionColumns.size() > 1) {
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "ERR_INVALID_VERSION_COLUMNS")); //NOI18N
            }
            String versionColumn = (String)versionColumns.get(0);

            String sourceTableName = getTableName(versionColumn,
                    primaryTableName);

            // we do not support version column from secondary table
            // in 8.1 release
            if (!sourceTableName.equals(primaryTableName)) {
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "WARN_VERSION_COLUMN_INVALID_TABLE", //NOI18N
                    primaryTableName, beanName, versionColumn));
            }

            TableElement sourceTableEl = (TableElement) knownTables.get(
                    sourceTableName);
            String versionColumnName = getColumnName(versionColumn);
            ColumnElement versionCol = getColumnElement(sourceTableEl,
                    DBIdentifier.create(versionColumnName), helper);

            if (null != versionCol) {

                // Since 8.1 release only support one version column per bean,
                // use prefix as the version  field name
                String fieldName = helper.getGeneratedVersionFieldNamePrefix();
                PersistenceFieldElement pfe = createPersistenceField(mce,
                    fieldName);
                MappingFieldElement mfe = createMappingField(mce, fieldName,
                    versionCol);
                mfe.setVersion(true);
            }
            else {
                // There is no version column.
                // Report error.
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "WARN_VERSION_COLUMN_MISSING", //NOI18N
                    primaryTableName, beanName));
            }
        }
    }

    /** Map simple cmp field to MappingFieldElement
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce Mapping class element
     * @param beanName Bean name
     * @param schema dbschema information for all beans
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @return candidate primary key column for unknown
     * primary key class mapping, if applicable
     * @throws DBException
     * @throws ModelException
     * @throws ConversionException
     */
    private ColumnElement mapNonRelationshipFields(EntityMapping mapping,
                                                   MappingClassElement mce,
                                                   String beanName,
                                                   SchemaElement schema,
                                                   Map knownTables)
        throws DBException, ModelException, ConversionException {

        CmpFieldMapping [] mapOfFields = mapping.getCmpFieldMapping();
        String primaryTableName = mapping.getTableName();
        ColumnElement candidatePK = null;

        // get candidate column only used for unknown primary key
        if (helper.generateFields()
            && helper.applyDefaultUnknownPKClassStrategy(beanName)) {

            candidatePK = getCandidatePK(schema, primaryTableName);
        }

        for (int i = 0; i < mapOfFields.length; i++) {
            CmpFieldMapping mapForOneField = mapOfFields[i];

            String fieldName = mapForOneField.getFieldName();
            if (!validateField(mce, beanName, fieldName,
                helper.ensureValidation())) {
                if (logger.isLoggable(Logger.FINE))
                    logger.fine(
                        I18NHelper.getMessage(
                        messages,
                        "WARN_INVALID_FIELD", //NOI18N
                        beanName, fieldName));

                continue;
            }

            String columnNames[] = mapForOneField.getColumnName();
            MappingFieldElement mfe = createUnmappedField(mce, beanName,
                fieldName);
            boolean fieldMappedToABlob = false;

            for (int j = 0; j < columnNames.length; j++) {
                String sourceTableName = getTableName(columnNames[j],
                    primaryTableName);
                if (null == sourceTableName) {
                    throw new ConversionException(
                        I18NHelper.getMessage(
                        messages,
                        "ERR_UNDEFINED_TABLE")); //NOI18N
                }

                String sourceColumnName = getColumnName(columnNames[j]);

                // get the table element
                TableElement sourceTableEl = getTableElement(sourceTableName,
                    knownTables, schema);
                ColumnElement aCol = getColumnElement(sourceTableEl,
                    DBIdentifier.create(sourceColumnName), helper);
                if (logger.isLoggable(Logger.FINE))
                    logger.fine(
                        I18NHelper.getMessage(
                        messages,
                        "MESSAGE_ADD_COLUMN", //NOI18N
                        new Object [] {aCol, fieldName}));

                // If candidatePK is mapped to a field, then it can not
                // treated as a primary key for unknown primary key
                if (helper.generateFields()
                    && helper.applyDefaultUnknownPKClassStrategy(beanName)) {
                    if (candidatePK != null && candidatePK.equals(aCol)) {
                        candidatePK = null;
                    }
                }

                fieldMappedToABlob |= aCol.isBlobType();
                mfe.addColumn(aCol);
            }

            FetchedWith fw = mapForOneField.getFetchedWith();
            setFetchGroup(fw, mfe, beanName, fieldMappedToABlob);
            mce.addField(mfe);
        }

        return candidatePK;
    }

    /**
     * Converts entity mapping relationship information from sun-cmp-mappings.xml
     * into JDO mapping file information.
     *
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce Mapping class element being populated corresponding to the bean.
     * @param beanName Bean name.
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @param tablesOfBean contains primary table and
     * secondary tables of the bean <code>beanName.
     * @throws ModelException
     * @throws DBException
     * @throws ConversionException
     */
    private void mapRelationshipFields(EntityMapping mapping,
                                       MappingClassElement mce,
                                       String beanName,
                                       SchemaElement schema,
                                       Map knownTables,
                                       List tablesOfBean)
        throws ModelException, DBException, ConversionException {

        String primaryTableName = mapping.getTableName();
        CmrFieldMapping mapOfRelations[] = mapping.getCmrFieldMapping();
        PersistenceClassElement pce = ((MappingClassElementImpl)mce).getPersistenceElement();

        for (int i = 0; mapOfRelations != null && i < mapOfRelations.length;
                i++) {
            CmrFieldMapping aRelation = mapOfRelations[i];
            String fieldName = aRelation.getCmrFieldName();

            if (!validateField(mce, beanName, fieldName, helper.ensureValidation())) {
                if (logger.isLoggable(Logger.FINE))
                    logger.fine(
                        I18NHelper.getMessage(
                        messages,
                        "WARN_INVALID_CMRFIELD", //NOI18N
                        beanName, fieldName));
                continue;
            }

            RelationshipElement rel = new RelationshipElement(
                new RelationshipElementImpl(fieldName), pce);
            MappingRelationshipElement mre =
                new MappingRelationshipElementImpl(fieldName, mce);

            // Register the inverse RelationshipElement
            registerInverseRelationshipElement(rel, beanName, fieldName);

            final ColumnPair pairs[] = aRelation.getColumnPair();
            final String relationId = mapping.getEjbName() + "_Relationship_" + i; //NOI18N
            Collection primaryTableColumns = convertToColumnPairElements(
                    pairs,
                    primaryTableName, schema, knownTables, tablesOfBean,
                    relationId,
                    mre);

            setUpperBound(rel, beanName, fieldName);
            setCascadeDeleteAction(rel, beanName, fieldName);
            setLowerBound(rel,
                    primaryTableColumns,
                    primaryTableName,schema, knownTables,
                    beanName, fieldName);
            setFetchGroup(aRelation.getFetchedWith(), mre, beanName, false);

            pce.addField(rel);
            mce.addField(mre);
        }
    }

    /** Map unmapped field to mapping field object.
     * @param mce Mapping class element
     * @param beanName Bean name
     * @throws ModelException
     */
    private void mapUnmappedFields(MappingClassElement mce, String beanName)
        throws ModelException {

        Object[] fields = helper.getFields(beanName);
        if (!helper.ensureValidation()) {
            for (int i = 0; i < fields.length; i++) {
                String fieldName = (String) fields[i];
                MappingFieldElement mfe = mce.getField(fieldName);

                if (null == mfe) {

                    // this field needs a mapping created for it...
                    mfe = createUnmappedField(mce, beanName, fieldName);
                    mce.addField(mfe);
                }
            }
        }
    }

    /** Set consistency from MappingClassElement into schema2beans
     * Consistency bean.
     * @param mce An object that represents the mapping object
     * @param beanMapping The schema2beans object that represents the mapping
     * for a particular bean.
     */
    private void setConsistency(MappingClassElement mce,
        EntityMapping beanMapping) {
        int consistency = mce.getConsistencyLevel();
        if (MappingClassElement.NONE_CONSISTENCY != consistency) {
            Consistency c = new Consistency();
            if (MappingClassElement.LOCK_WHEN_MODIFIED_CHECK_ALL_AT_COMMIT_CONSISTENCY == consistency) {
                c.setLockWhenModified(true);
                c.setCheckAllAtCommit(true);
            }
            if (MappingClassElement.LOCK_WHEN_MODIFIED_CONSISTENCY == consistency)
                c.setLockWhenModified(true);
            if (MappingClassElement.CHECK_ALL_AT_COMMIT_CONSISTENCY == consistency)
                c.setCheckAllAtCommit(true);
            if (MappingClassElement.LOCK_WHEN_LOADED_CONSISTENCY  == consistency)
                c.setLockWhenLoaded(true);
            if (MappingClassElement.CHECK_MODIFIED_AT_COMMIT_CONSISTENCY == consistency)
                c.setCheckModifiedAtCommit(true);
            if (MappingClassElement.VERSION_CONSISTENCY == consistency) {
                CheckVersionOfAccessedInstances versionIns =
                    new CheckVersionOfAccessedInstances();
                Iterator iter = mce.getVersionFields().iterator();
                while (iter.hasNext()) {
                    List columnNames = ((MappingFieldElement)iter.next()).
                        getColumns();

                    // vesion field only allow to map to one column
                    if (columnNames != null && columnNames.size() > 0)
                        versionIns.addColumnName((String)columnNames.get(0));
                }
                c.setCheckVersionOfAccessedInstances(versionIns);
            }
            beanMapping.setConsistency(c);
        }
    }

    /** Load consistency from schema2beans into MappingClassElement
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce An object that represents mapping object
     * @return a list of version column names if applicable; return null
     * otherwise.
     * @throws ModelException
     * @throws ConversionException
     */
    private List loadConsistency(EntityMapping mapping, MappingClassElement mce)
        throws ModelException, ConversionException {
        Consistency c = mapping.getConsistency();
        if (null == c) {
            mce.setConsistencyLevel(MappingClassElement.NONE_CONSISTENCY);
        }
        else {
            CheckVersionOfAccessedInstances versionIns =
                (CheckVersionOfAccessedInstances)
                c.getCheckVersionOfAccessedInstances();

            if (c.isCheckModifiedAtCommit())
                mce.setConsistencyLevel(
                    MappingClassElement.CHECK_MODIFIED_AT_COMMIT_CONSISTENCY);
            else if(c.isLockWhenLoaded())
                mce.setConsistencyLevel(
                    MappingClassElement.LOCK_WHEN_LOADED_CONSISTENCY);
            else if(c.isCheckAllAtCommit())
                mce.setConsistencyLevel(
                    MappingClassElement.CHECK_ALL_AT_COMMIT_CONSISTENCY);
            else if(c.isLockWhenModified())
                mce.setConsistencyLevel(
                    MappingClassElement.LOCK_WHEN_MODIFIED_CONSISTENCY);
            else if(c.isLockWhenModified() && c.isCheckAllAtCommit())
                mce.setConsistencyLevel(MappingClassElement.
                    LOCK_WHEN_MODIFIED_CHECK_ALL_AT_COMMIT_CONSISTENCY);
            else if(c.isNone())
                mce.setConsistencyLevel(MappingClassElement.NONE_CONSISTENCY);
            else if (versionIns != null) {
                mce.setConsistencyLevel(MappingClassElement.VERSION_CONSISTENCY);
                List versionColumns = new ArrayList();
                for (int i = 0; i < versionIns.sizeColumnName(); i++) {
                    versionColumns.add(versionIns.getColumnName(i));
                }
                return versionColumns;
            }
            else {
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "ERR_INVALID_CONSISTENCY_VALUE", mce)); //NOI18N
            }
        }
        return null;
    }

    /** Map the primary table of the bean.
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce Mapping class element
     * @param schema dbschema information for all beans
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @param tablesOfBean contains primary table and
     * secondary tables of the bean corresponding to the <code>mapping
     * @throws DBException
     * @throws ModelException
     * @throws ConversionException
     */
    private void mapPrimaryTable(EntityMapping mapping,
                                  MappingClassElement mce,
                                  SchemaElement schema,
                                  Map knownTables,
                                  List tablesOfBean)
        throws DBException, ModelException, ConversionException {

        String primaryTableName = mapping.getTableName();
        TableElement primTabEl = getTableElement(primaryTableName, knownTables, schema);

        mce.addTable(primTabEl);
        tablesOfBean.add(primaryTableName);
    }

    /** Get the candidate pk column for unknown primary key.
     * @param schema dbschema information for all beans
     * @param primaryTableName Primary table name
     * @return candidate pk column which will be used for unknown primary key,
     * if applicable
     * @throws DBException
     * @throws ConversionException
     */
    private ColumnElement getCandidatePK(SchemaElement schema,
                                         String primaryTableName)
        throws DBException, ConversionException {
        ColumnElement candidatePK = null;

        TableElement primTabEl = getTableElement(schema,
            DBIdentifier.create(primaryTableName), helper);
        // Check if the candidatePK is really satisfying primary key
        // criteria. It will be used only for unknown primary key.
        UniqueKeyElement uke = primTabEl.getPrimaryKey();

        if (null != uke) {
            ColumnElement cols[] = uke.getColumns();
            if (null != cols && 1 == cols.length) {
                candidatePK = cols[0];
                if (logger.isLoggable(Logger.FINE))
                    logger.fine(
                        I18NHelper.getMessage(
                        messages,
                        "MESSAGE_CANDIDATE_PK", //NOI18N
                        candidatePK.getName()));

                Integer pre = candidatePK.getPrecision();
                if (null != candidatePK && !candidatePK.isNumericType()) {
                    candidatePK = null;
                }
                if (null != candidatePK && (null != pre) && pre.intValue() < MINIMUM_PRECISION) {
                    candidatePK = null;
                }
            }
        }
        return candidatePK;
    }

    /**
     * Converts column pair information from sun-cmp-mappings.xml into
     * column pair elements from the JDO mapping definition.
     *
     * @param pairs ColumnPair information from sun-cmp-mappings.xml.
     * @param primaryTableName Name of the bean's primary table.
     * @param schema dbschema information for all beans.
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @param tablesOfBean contains primary table and
     * secondary tables of the bean corresponding to the <code>mre's
     * declaring class.
     * @param relationId Relationship id used to name the ColumnPairElements.
     * @param mre Mapping relationship element (== JDO information).
     * @return Collection of column elements, including all columns from the
     * current cmr definition that are part of the primary table.
     * @throws DBException
     * @throws ModelException
     * @throws ConversionException
     */
    private Collection convertToColumnPairElements(ColumnPair pairs[],
                                                   String primaryTableName,
                                                   SchemaElement schema,
                                                   Map knownTables,
                                                   List tablesOfBean,
                                                   String relationId,
                                                   MappingRelationshipElement mre)
            throws DBException, ModelException, ConversionException {

        Collection primaryTableColumns = new ArrayList();
        boolean isJoin = false;

        for (int i = 0; null != pairs && i < pairs.length; i++) {
            ColumnPair pair = pairs[i];
            ColumnPairElement cpe = new ColumnPairElement();
            boolean localSet = false;

            cpe.setName(DBIdentifier.create(relationId + "_ColumnPair_" + i)); //NOI18N

            for (int j = 0; j < 2; j++) {
                String columnName = pair.getColumnName(j);
                String sourceTableName = getTableName(columnName,
                    primaryTableName);
                String sourceColumnName = getColumnName(columnName);
                TableElement sourceTableEl = getTableElement(sourceTableName,
                    knownTables, schema);
                ColumnElement ce = getColumnElement(sourceTableEl,
                    DBIdentifier.create(sourceColumnName), helper);
                ce.toString();

                // tablesOfBean stores the primary table and the secondary
                // tables for the bean.
                // It can be used for checking join table if sourceTableName
                // is not in the tablesOfBean.
                // If it is join table, should use addLocalColumn instead of
                // addColumn.
                if (j == 0) {
                    if (tablesOfBean.contains(sourceTableName)) {
                        localSet = true;

                        // Remember local columns for lower bound determination.
                        primaryTableColumns.add(ce);
                    }
                    else {

                        // join table
                        isJoin = true;
                        localSet = false;
                    }
                }

                if (cpe.getLocalColumn() == null) {
                    cpe.setLocalColumn(ce);
                }
                else {
                    cpe.setReferencedColumn(ce);
                }
            }

            if (localSet) {
                if (!isJoin) {
                    mre.addColumn(cpe);
                }
                else {
                    mre.addLocalColumn(cpe);
                }
            }
            else if (isJoin) {
                mre.addAssociatedColumn(cpe);
            }
        }

        return primaryTableColumns;
    }

    /**
     * If a non-collection relationship field is mapped to a
     * non-nullable column, the lower bound of the relationship might
     * be set to 1. To set the lower bound, we have to determine the
     * dependent side of the relationship. We set the lower bound to 1
     * based on the following rules:
     *
     * <ul>
     * <li>If the non-nullable column is not part of the primary key.
     * <li>If the local side has got a foreign key.
     * <li>If the local columns are a real subset of the primary key.
     * <li>If the user specified the local side for cascade delete.
     * </ul>
     *
     * @param rel JDO relationship information being constructed.
     * @param primaryTableColumns  Collection of all columns from the
     * current cmr definition that are part of the primary table.
     * @param primaryTableName Name of the bean's primary table.
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @param schema dbschema information for all beans.
     * @param beanName Bean name.
     * @param fieldName Relationship field name.
     * @throws ModelException
     * @throws DBException
     * @throws ConversionException
     */
    private void setLowerBound(RelationshipElement rel,
                               Collection primaryTableColumns,
                               String primaryTableName,
                               SchemaElement schema,
                               Map knownTables,
                               String beanName,
                               String fieldName)
                               throws ModelException, DBException,
                               ConversionException {

        rel.setLowerBound(0);
        if (logger.isLoggable(Logger.FINE))
            logger.fine(
                I18NHelper.getMessage(
                messages,
                "MESSAGE_LWB_NULL", //NOI18N
                beanName, fieldName));

        if (1 == rel.getUpperBound() && null != primaryTableName) {

            boolean isPartOfPrimaryKey = false;
            TableElement primaryTable = getTableElement(primaryTableName,
                knownTables, schema);
            UniqueKeyElement pk = primaryTable.getPrimaryKey();
            ForeignKeyElement fks[] = primaryTable.getForeignKeys();
            Iterator iter = primaryTableColumns.iterator();

            while (iter.hasNext() && 0 == rel.getLowerBound()) {
                ColumnElement ce = (ColumnElement) iter.next();
                if (!ce.isNullable()) {
                    isPartOfPrimaryKey |= isPartOfPrimaryKey(ce, pk);

                    if (!isPartOfPrimaryKey) {
                        // We suppose that all primary key columns are non-nullable.
                        // If the non-nullable column is not part of the primary key,
                        // this is the dependent side.
                        rel.setLowerBound(1);
                        if (logger.isLoggable(Logger.FINE))
                            logger.fine(
                                I18NHelper.getMessage(
                                messages,
                                "MESSAGE_LWB_NOPK", //NOI18N
                                beanName, fieldName));
                    }
                    // Check the foreign key constraint
                    else if (isPartOfForeignKey(ce, fks)) {
                        // If the non-nullable column is part of the foreign key,
                        // this is the dependent side.
                        rel.setLowerBound(1);
                        if (logger.isLoggable(Logger.FINE))
                            logger.fine(
                                I18NHelper.getMessage(
                                messages,
                                "MESSAGE_LWB_FK", //NOI18N
                                beanName, fieldName));
                    }
                }
            }

            if (0 == rel.getLowerBound() && isPartOfPrimaryKey) {
                // The lower bound is still unset and all local columns
                // are part of the primary key.
                if (primaryTableColumns.size() < pk.getColumns().length) {
                    // The local columns are a real subset of the primary key.
                    // ==> This must be the dependent side.
                    rel.setLowerBound(1);
                    if (logger.isLoggable(Logger.FINE))
                        logger.fine(
                            I18NHelper.getMessage(
                            messages,
                            "MESSAGE_LWB_PKSUBSET", //NOI18N
                            beanName, fieldName));
                }
                else if (isCascadeDelete(beanName, fieldName)) {
                    // This relationship side is marked as dependent side by the user.
                    rel.setLowerBound(1);
                    if (logger.isLoggable(Logger.FINE))
                        logger.fine(
                            I18NHelper.getMessage(
                            messages,
                            "MESSAGE_LWB_CASCADE", //NOI18N
                            beanName, fieldName));
                }
                else {
                    if (logger.isLoggable(Logger.FINE))
                        logger.fine(
                            I18NHelper.getMessage(
                            messages,
                            "MESSAGE_LWB_NODEPENDENT", //NOI18N
                            beanName, fieldName));
                }
            }
        }
    }

    /**
     * Looks up the table element for <code>tableName in the
     * table element cache <code>knownTables. If the table
     * element is not found, the table name is looked up in the
     * database schema and registered in the cache.
     *
     * @param tableName Table name.
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @param schema dbschema information for all beans.
     * @return Table element for table <code>tableName.
     * @exception DBException
     * @exception ConversionException
     */
    private TableElement getTableElement(String tableName,
                                         Map knownTables,
                                         SchemaElement schema)
        throws DBException, ConversionException {

        TableElement te = (TableElement) knownTables.get(tableName);

        if (null == te) {
            te = getTableElement(schema, DBIdentifier.create(tableName),
                helper);
            knownTables.put(tableName, te);
        }

        return te;
    }

    /**
     * Checks, if the column <code>ce is part of the
     * primary key <code>pk.
     * RESOLVE: Method isPrimaryKeyColumn in ModelValidator
     * implements similar functionality.
     *
     * @param ce Column element for the column to be tested.
     * @param pk Primary key element. The column to be tested
     * <b>must be defined in the same table.
     * @return True, if the column is part of the primary key,
     * false otherwise.
     * @see com.sun.jdo.api.persistence.model.util.ModelValidator
     */
    private boolean isPartOfPrimaryKey(ColumnElement ce, UniqueKeyElement pk) {
        return null != pk && ce.equals(pk.getColumn(ce.getName()));
    }

    /**
     * Checks, if the column <code>ce is part of one
     * of the foreign key constraints defined in <code>fks.
     * RESOLVE: Method matchesFK in ModelValidator implements similar
     * functionality.
     *
     * @param ce Column element for the column to be tested.
     * @param fks Array of foreign key elements. The column to be
     * tested <b>must be defined in the same table.
     * @return True, if the column is part of one of the foreign keys,
     * false otherwise.
     * @see com.sun.jdo.api.persistence.model.util.ModelValidator
     */
    private boolean isPartOfForeignKey(ColumnElement ce,
        ForeignKeyElement[] fks) {

        // RESOLVE: Column ce might be included in multiple foreign
        // keys. The foreign key check applies to ALL relationships
        // mapped to column ce. How can we find out, that a foreign
        // key matches exactly the relationship being checked here?

        if (fks != null) {
            for (int index = 0; index < fks.length; index++) {
                if (ce.equals(fks[index].getColumn(ce.getName()))) {
                    // The current ce is part of the foreign key.
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * Returns the cascade delete setting for the current relationship side.
     * The ConversionHelper interface provides cascade delete information
     * for the related side only.
     *
     * @param beanName Bean name.
     * @param fieldName Relationship field name.
     * @return True, if the current relationship side is marked for cascade delete,
     * false otherwise.
     */
    private boolean isCascadeDelete(String beanName, String fieldName) {
        final String beanInField = helper.getRelationshipFieldContent(beanName,             fieldName);
        final String inverseField = helper.getInverseFieldName(beanName,
            fieldName);

        return (null != beanInField && null != inverseField) ?
                helper.relatedObjectsAreDeleted(beanInField, inverseField) : false;
    }

    /**
     * Registers relationship element <code>rel in the cache
     * mapping field names to inverse relationship elements. The
     * inverse bean- and field names for the registration are
     * determined with the conversion helper.  Returns the
     * relationship element for the inverse field, if this field has
     * been already processed, null otherwise.
     *
     * @param rel JDO relationship information being constructed.
     * @param beanName Bean name.
     * @param fieldName Relationship field name.
     * @return The relationship element for the inverse field, if this field
     * has been already processed, null otherwise.
     * @throws ModelException
     */
    private RelationshipElement registerInverseRelationshipElement(
        RelationshipElement rel, String beanName, String fieldName)
        throws ModelException {

        String key = beanName + "." + fieldName; //NOI18N
        RelationshipElement inverse = (RelationshipElement) inverseRelationships.get(key);

        if (null == inverse) {
            final String beanInField = helper.getRelationshipFieldContent(
                beanName, fieldName);
            final String inverseField = helper.getInverseFieldName(beanName,
                fieldName);

            if (null != beanInField && null != inverseField) {
                key = beanInField + "." + inverseField; //NOI18N
                inverseRelationships.put(key, rel);
            }
        }
        else {
            rel.changeInverseRelationship(inverse);
            inverse.changeInverseRelationship(rel);
        }

        return inverse;
    }

    /**
     * Sets the upper bound for relationship element <code>rel
     * depending on the upper bound information from the deployment
     * descriptor and defines the element class for collection
     * relationship fields.
     *
     * @param rel JDO relationship information being constructed.
     * @param beanName Bean name.
     * @param fieldName Relationship field name.
     * @throws ModelException
     * @throws ConversionException
     */
    private void setUpperBound(RelationshipElement rel,
                               String beanName, String fieldName)
        throws ModelException, ConversionException {

        String beanInField = helper.getRelationshipFieldContent(beanName,
            fieldName);
        String classInJdoField = helper.getMappedClassName(beanInField);
        String multiplicity = helper.getMultiplicity(beanName, fieldName);

        // Set the upper bound.
        if (multiplicity.equals(helper.MANY)) {
            rel.setUpperBound(Integer.MAX_VALUE);
            rel.setElementClass(classInJdoField);
            String collectionClass = helper.getRelationshipFieldType(beanName,
                fieldName);
            if (types.contains(collectionClass)) {
                rel.setCollectionClass(collectionClass);
            }
            else {
                rel.setCollectionClass(null);
                if (logger.isLoggable(Logger.WARNING))
                    logger.warning(
                        I18NHelper.getMessage(
                        messages,
                        "WARN_INVALID_RELATIONSHIP_FIELDTYPE", //NOI18N
                        beanName, fieldName, collectionClass));
            }
        }
        else if (multiplicity.equals(helper.ONE)) {
            rel.setUpperBound(1);
            // Fix later. This code should be removed because in one side
            // setElementClass should not be called.
            // This line of code is for bug 4665051 which is plugin bug.
            // It is likely that bug 4665051 indicates that there is code
            // in the plugin which depends on the element class being set
            // for a one side relationship.
            rel.setElementClass(classInJdoField);
        }
        else {
            throw new ConversionException(
                I18NHelper.getMessage(
                messages,
                "ERR_BAD_MULTIPLICTY", //NOI18N
                multiplicity, rel.getName()));
        }
    }

    /**
     * Sets the cascade delete option for relationship element
     * <code>rel depending on the information from the
     * deployment descriptor.  While the deployment descriptor
     * specifies cascade delete option on the dependent side, JDO
     * specifies it on the primary side.  For this reason, the
     * information must be "switched".
     *
     * @param rel JDO relationship information being constructed.
     * @param beanName Bean name.
     * @param fieldName Relationship field name.
     * @throws ModelException
     */
    private void setCascadeDeleteAction(RelationshipElement rel,
                                        String beanName, String fieldName)
            throws ModelException {

        if (helper.relatedObjectsAreDeleted(beanName, fieldName)) {
            if (logger.isLoggable(Logger.FINE))
                logger.fine(
                    I18NHelper.getMessage(
                    messages,
                    "MESSAGE_REL_OBJ_DEL", //NOI18N
                    beanName, fieldName));
            rel.setDeleteAction(RelationshipElement.CASCADE_ACTION);
        }
    }

    private SchemaElement setDatabaseRoot(MappingClassElement foo,
        String schemaElementValue, boolean strict)
        throws ModelException, DBException, ConversionException {
        SchemaElement bar = null;
        if (null != classLoader) {
            if (loadedSchema.get(schemaElementValue) == null) {
                SchemaElement.removeFromCache(schemaElementValue);
                loadedSchema.put(schemaElementValue, schemaElementValue);
            }
            bar = SchemaElement.forName(schemaElementValue,classLoader);
        }
        else
            bar = SchemaElement.forName(schemaElementValue);
        if (strict) {
            if (bar == null) {
                // Prepare for a schema related error
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "ERR_CANNOT_FIND_SCHEMA", //NOI18N
                    new Object [] {schemaElementValue, classLoader}));
            }
        }
        else {
            if (null == bar) {
                // conjure up a schema element and set its name...
                // need to create a dummy for invalid mappings because the
                // mapping model setter methods don't accept strings even
                // though that is what they store.
                bar = new SchemaElement();
                DBIdentifier n = DBIdentifier.create(schemaElementValue);
                n.setFullName(schemaElementValue);
                bar.setName(n);
            }
        }
        foo.setDatabaseRoot(bar);
        return bar;
    }

    private String getTableName(String columnName, String defaultName) {
        String retVal = defaultName;
        int len = columnName.lastIndexOf('.');
        if (len > 0)
            retVal = columnName.substring(0,len);
        return retVal;
    }

    private String getColumnName(String columnName) {
        String retVal = columnName;
        int len = columnName.lastIndexOf('.');
        if (len > 0)
            retVal = columnName.substring(len+1);
        return retVal;
    }

    /** Map the secondary tables of the bean.
     * @param mapping The schema2beans object that represents the mapping
     * for a particular bean.
     * @param mce Mapping class element
     * @param schema dbschema information for all beans
     * @param knownTables A Map which contains primary and secondary tables
     * for beans in the set. Keys: table names Values: TableElement objects
     * @param tablesOfBean contains primary table and
     * secondary tables of the bean corresponding to the <code>mapping
     * @throws ModelException
     * @throws DBException
     * @throws ConversionException
     */
    private void mapSecondaryTables(EntityMapping mapping,
                                    MappingClassElement mce,
                                    SchemaElement schema,
                                    Map knownTables,
                                    List tablesOfBean)
        throws ModelException, DBException, ConversionException {

        SecondaryTable [] tableList = mapping.getSecondaryTable();
        List tl = mce.getTables();

        if (null != tl && tl.size() > 0 && null != tl.get(0)) {
            MappingTableElement primary = (MappingTableElement) tl.get(0);

            for (int i = 0; null != tableList && i < tableList.length; i++) {
                String tn = tableList[i].getTableName();
                if (StringHelper.isEmpty(tn))
                    continue;
                TableElement te = getTableElement(schema,
                    DBIdentifier.create(tn.trim()), helper);
                ColumnPair pairs[] = tableList[i].getColumnPair();
                int len = 0;
                if (null != pairs)
                    len = pairs.length;
                if (0 == len) {
                    if (logger.isLoggable(Logger.WARNING))
                        logger.warning(
                            I18NHelper.getMessage(
                            messages,
                            "WARN_NO_PAIRS", //NOI18N
                            new Object [] {mce, tn}));
                    continue;
                }
                MappingReferenceKeyElement mrke = mce.addSecondaryTable(
                    primary,te);
                for (int j = 0; null != pairs && j < pairs.length; j++) {
                    ColumnPairElement cpe = new ColumnPairElement();
                    DBIdentifier dbId = DBIdentifier.create("SecondaryTable"+j); //NOI18N
                    cpe.setName(dbId);
                    ColumnPair pair = pairs[j];
                    for (int k = 0; k < 2; k++) {
                        String nameOne = pair.getColumnName(k);
                        String sourceTableName = getTableName(
                            nameOne.trim(),
                            primary.getName().toString());
                        String sourceColumnName = getColumnName(nameOne);
                        dbId = DBIdentifier.create(sourceTableName);
                        TableElement sourceTableEl = getTableElement(schema,
                            dbId, helper);
                        dbId = DBIdentifier.create(sourceColumnName);
                        ColumnElement ce = getColumnElement(sourceTableEl,
                            dbId, helper);
                        if (k == 0)
                            cpe.setLocalColumn(ce);
                        else
                            cpe.setReferencedColumn(ce);
                    }
                    mrke.addColumnPair(cpe);
                }
                knownTables.put(tn,te);
                tablesOfBean.add(tn);
            }
        }
        else
            throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "WARN_NOT_MAPPED_TO_PRIMARY", //NOI18N
                    mce.getName()));
    }

    private boolean validateField(MappingClassElement mce, String beanName,
        String fieldName, boolean throwEx) throws ConversionException {
        MappingFieldElement mfe = mce.getField(fieldName);
        if (null != mfe) {
            if (throwEx)
                throw new ConversionException(
                    I18NHelper.getMessage(
                    messages,
                    "ERR_FIELD_MAPPED_TWICE", //NOI18N
                    beanName, fieldName));
            else
                return false;
        }
        if (!helper.hasField(beanName,fieldName)) {
            if (throwEx)
                throw new ConversionException(
                I18NHelper.getMessage(
                messages,
                "ERR_INVALID_FIELD", //NOI18N
                beanName, fieldName));
            else
                return false;
        }
        return true;
    }

    // loop through the mappings to create a hash from bean name to em objects
    private Map getBean2EntityMappingMap(SunCmpMapping beanSet) {
        Map retVal = new HashMap();
        EntityMapping [] entityMappingsInSet = beanSet.getEntityMapping();
        int len = 0;
        if (null != entityMappingsInSet)
            len = entityMappingsInSet.length;
        for (int k = 0; k < len; k++) {
            EntityMapping anEntityMapping = entityMappingsInSet[k];
            String beanName = anEntityMapping.getEjbName();
            beanName.trim().charAt(0);
            retVal.put(beanName,anEntityMapping);
        }
        return retVal;
    }

    // for each cmr field in the mapping
    // determine is the inverse is a generated field
    // create the mapping data for this generated field
    private boolean completeCmrMappings(SunCmpMapping beanSet)
        throws ConversionException {

        // loop through the mappings to create a hash from bean name to em objects
        Map beanName2EntityMapping = getBean2EntityMappingMap(beanSet);
        Iterator emIter = beanName2EntityMapping.values().iterator();
        boolean retVal = false;
        String errorMsg = I18NHelper.getMessage(
            messages,
            "ERR_BAD_CONVERSION_HELPER"); //NOI18N

        while (emIter.hasNext()) {
            EntityMapping anEM = (EntityMapping) emIter.next();
            String beanName = anEM.getEjbName();
            String pt = anEM.getTableName();
            CmrFieldMapping[]  cmrsInEM = anEM.getCmrFieldMapping();
            int len = 0;
            if (null != cmrsInEM && !StringHelper.isEmpty(beanName))
                len = cmrsInEM.length;
            for (int i = 0; i < len; i++) {
                String fieldName = cmrsInEM[i].getCmrFieldName();
                if (!helper.hasField(beanName, fieldName)) {
                    throw new ConversionException(I18NHelper.getMessage(
                        messages,
                        "WARN_INVALID_CMRFIELD", //NOI18N
                        beanName, fieldName));
                } 
                fieldName.trim().charAt(0);
                String otherField = helper.getInverseFieldName(beanName,
                    fieldName);
                if (otherField == null) {
                    throw new ConversionException(errorMsg);
                }
                String otherBean = helper.getRelationshipFieldContent(beanName,
                    fieldName);
                if (otherBean == null) {
                    throw new ConversionException(errorMsg);
                }

                if (helper.isGeneratedRelationship(otherBean,otherField)) {
                    retVal = true;
                    String otherBeanName = helper.getRelationshipFieldContent(
                        beanName, fieldName);
                    otherBeanName.trim().charAt(0);
                    EntityMapping otherEM =
                        (EntityMapping) beanName2EntityMapping.get(
                            otherBeanName);
                    CmrFieldMapping inverseMapping = new CmrFieldMapping();
                    inverseMapping.setCmrFieldName(otherField);
                    inverseMapping.setColumnPair(
                        reverseCPArray(cmrsInEM[i].getColumnPair(), pt, 
                            beanName, fieldName));
                    otherEM.addCmrFieldMapping(inverseMapping);
                }
            }
        }
        return retVal;
    }

    private ColumnPair[] reverseCPArray(ColumnPair[] cpa, String primeTable,
        String beanName, String fieldName)
        throws ConversionException {
        int len = (cpa == null) ? 0 : cpa.length;
        if (len == 0) {
            throw new ConversionException(
                I18NHelper.getMessage(
                messages,
                "ERR_COLUMN_PAIR_MISSING", //NOI18N
                beanName, fieldName));
        }
        ColumnPair [] retVal = new ColumnPair[len];
        for (int index = 0; index < len; index++) {
            retVal[index] = new ColumnPair();
            retVal[index].addColumnName(
                qualify(primeTable,cpa[index].getColumnName(1)));
            retVal[index].addColumnName(
                qualify(primeTable,cpa[index].getColumnName(0)));
        }
        return retVal;
    }

    private String qualify(String tn, String cn) {
        int tmp = cn.indexOf('.');
        String retVal = cn;
        if (-1 == tmp)
            retVal = tn + "." + cn; // NOI18N
        return retVal;
    }

    private TableElement getTableElement(SchemaElement schema,
        DBIdentifier dbId, ConversionHelper helper)
        throws DBException, ConversionException {

        TableElement retVal = ((schema != null) ? 
            schema.getTable(dbId) : null);

        if (null == retVal && !helper.ensureValidation()) {
            // Need to create a dummy for invalid mappings because
            // the mapping model setter methods don't accept
            // strings even though that is what they store.
            // Create the table and add it to the knownTables list
            // for later

            retVal = new TableElement();
            retVal.setName(dbId);
            retVal.setDeclaringSchema(schema);
            org.netbeans.modules.dbschema.UniqueKeyElement tkey =
                new org.netbeans.modules.dbschema.UniqueKeyElement();
            ColumnElement fakeKeyCol = new ColumnElement();
            fakeKeyCol.setName(DBIdentifier.create(retVal.getName().getName()+ "."+"fookeyng")); //NOI18N

            // Type numeric=2
            fakeKeyCol.setType(2);
            fakeKeyCol.setPrecision(new Integer(MINIMUM_PRECISION));
            tkey.setPrimaryKey(true);
            tkey.addColumn(fakeKeyCol);
            retVal.addColumn(fakeKeyCol);
            retVal.addKey(tkey);
        }
        if (retVal == null) {
            throw new ConversionException(
                I18NHelper.getMessage(
                messages,
                "ERR_INVALID_TABLE", //NOI18N
                new Object [] {dbId.getName(), schema}));
        }
        return retVal;
    }

    private ColumnElement getColumnElement(TableElement sourceTableEl,
        DBIdentifier sourceColumnName, ConversionHelper helper)
        throws DBException, ConversionException {

        ColumnElement aCol = sourceTableEl.getColumn(sourceColumnName);
        if (null == aCol && !helper.ensureValidation()) {
            aCol = new ColumnElement();
            aCol.setName(DBIdentifier.create(sourceTableEl.getName().toString()+"."+sourceColumnName.toString())); // NOI18N
            aCol.setDeclaringTable(sourceTableEl);
            aCol.setNullable(true);
        }
        if (aCol == null) {
            throw new ConversionException(
                I18NHelper.getMessage(
                messages,
                "ERR_INVALID_COLUMN", //NOI18N
                new Object [] {sourceColumnName, sourceTableEl}));
        }
        return aCol;
    }

    private MappingFieldElement createUnmappedField(MappingClassElement mce,
        String beanName, String fieldName)
        throws ModelException {

        PersistenceClassElement pce = ((MappingClassElementImpl)mce).
            getPersistenceElement();
        PersistenceFieldElementImpl pfei =
            new PersistenceFieldElementImpl(fieldName);
        PersistenceFieldElement pfe =
            new PersistenceFieldElement(pfei, pce);

        pfe.setKey(helper.isKey(beanName,fieldName,false));
        pce.addField(pfe);
        MappingFieldElement mfe = new MappingFieldElementImpl(fieldName, mce);
        return mfe;
    }

    /**
     * Set fetch group level for mapping field and mapping relationship
     * element. If there is fetch level information, then set mapping field
     * element with the level. If there is no fetch group level information,
     * set mapping field element to GROUP_NONE if it is mapping relationship
     * element or blob type field otherwise set to GROUP_DEFAULT.
     * @param fw An object having fetch group level information
     * @param mfe An mapping field or mapping relationship element to be set
     * fetch group level
     * @param fieldMappedToABlob boolean type to indicate that field is blob
     * type or not
     * @throws ModelException
     * @throws ConversionException 
     */
    private void setFetchGroup(FetchedWith fw, MappingFieldElement mfe,
        String beanName, boolean fieldMappedToABlob)
        throws ModelException, ConversionException {
        if (null != fw) {
            boolean tryLevel = false;
            int level = 0;
            try {
                level = fw.getLevel();
                tryLevel = true;
            }
            catch (RuntimeException e) {
                // If there is no level set, schema2beans throws 
                // RuntimeException.
                // Need to do more investigation on why throws this exception. 
                // it is very likely that there is no level set, which would
                // throw an exception here..  Which we are going to ignore
            }
            if (tryLevel) {
                if (level < 1) {
                    throw new ConversionException(
                        I18NHelper.getMessage(
                        messages,
                        "ERR_INVALID_FG_LEVEL", //NOI18N
                        beanName, mfe.getName(), ""+level)); //NOI18N
                }
                mfe.setFetchGroup(level+1);
            }
            String ig = fw.getNamedGroup();
            if (null != ig) {
                Integer fgval = (Integer) namedGroups.get(ig);
                if (null == fgval) {
                    fgval = new Integer(groupCount--);
                    namedGroups.put(ig,fgval);
                }
                mfe.setFetchGroup(fgval.intValue());
            }
            if (fw.isNone())
                mfe.setFetchGroup(MappingFieldElement.GROUP_NONE);
            if (fw.isDefault())
                mfe.setFetchGroup(MappingFieldElement.GROUP_DEFAULT);
        }
        else {
            if (mfe instanceof MappingRelationshipElement)
                mfe.setFetchGroup(MappingFieldElement.GROUP_NONE);
            else {
                if (fieldMappedToABlob)
                    mfe.setFetchGroup(MappingFieldElement.GROUP_NONE);
                else
                    mfe.setFetchGroup(MappingFieldElement.GROUP_DEFAULT);
            }
        }
    }

    private PersistenceFieldElement createPersistenceField(
        MappingClassElement mce, String fieldName) throws ModelException {
        PersistenceClassElement pce =
            ((MappingClassElementImpl)mce).getPersistenceElement();
        PersistenceFieldElementImpl pfei =
            new PersistenceFieldElementImpl(fieldName);
        PersistenceFieldElement pfe =
            new PersistenceFieldElement(pfei, pce);
        pce.addField(pfe);
        return pfe;
    }

    private MappingFieldElement createMappingField(MappingClassElement mce,
        String fieldName, ColumnElement col) throws ModelException {
        MappingFieldElement mfe =
            new MappingFieldElementImpl(fieldName, mce);
        mce.addField(mfe);
        if (col != null)
            mfe.addColumn(col);
        return mfe;
    }
}

Other Glassfish examples (source code examples)

Here is a short list of links related to this Glassfish MappingFile.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.