Package org.jpox.store.mapped.mapping

Source Code of org.jpox.store.mapped.mapping.InterfaceMapping

/**********************************************************************
Copyright (c) 2004 Barry Haddow and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
2004 Erik Bengtson - nearly all
2007 Andy Jefferson - bypass getObject for normal persistence cases
***********************************************************************/
package org.jpox.store.mapped.mapping;

import org.jpox.ClassLoaderResolver;
import org.jpox.ObjectManager;
import org.jpox.exceptions.JPOXObjectNotFoundException;
import org.jpox.identity.OID;
import org.jpox.identity.OIDFactory;
import org.jpox.metadata.AbstractMemberMetaData;
import org.jpox.store.exceptions.NullValueException;
import org.jpox.store.mapped.DatastoreAdapter;
import org.jpox.store.mapped.DatastoreContainerObject;
import org.jpox.store.mapped.MappedStoreManager;
import org.jpox.util.StringUtils;

/**
* Mapping for Interface fields.
*
* @version $Revision: 1.38 $
*/
public class InterfaceMapping extends ReferenceMapping
{
    /** JPOX extension - if a field is declared with implementation-classes. Comma-separated list of implementation classes. **/
    private String implementationClasses;

    /**
     * Initialisation.
     * @param dba Datastore adapter
     * @param fmd MetaData for the field/property
     * @param container datastore container (table)
     * @param clr ClassLoader resolver
     */
    public void initialize(DatastoreAdapter dba, AbstractMemberMetaData fmd, DatastoreContainerObject container, ClassLoaderResolver clr)
    {
        super.initialize(dba, fmd, container, clr);

        if (fmd.getType().isInterface() && fmd.getFieldTypes() != null && fmd.getFieldTypes().length == 1)
        {
            // Field is an interface but field-type is specified with one value only so try to impose that
            // This is of particular use where the JDO2 TCK has fields defined as interfaces and the field-type
            // as the persistent-interface type, forcing the persistence of the property.
            Class fieldTypeCls = clr.classForName(fmd.getFieldTypes()[0]);
            if (fieldTypeCls.isInterface())
            {
                type = fmd.getFieldTypes()[0];
            }
        }
    }

    /**
     * Set the implementation classes. If the field defined what the implementation
     * classes are, this mapping will only use it
     * @param implementationClasses the implementation classes string
     */
    public void setImplementationClasses(String implementationClasses)
    {
        this.implementationClasses = implementationClasses;
    }

    /**
     * Method to retrieve an object of this type from the ResultSet.
     * @param om ObjectManager
     * @param rs The ResultSet
     * @param pos The parameter positions
     * @return The object
     */
    public Object getObject(ObjectManager om, final Object rs, int[] pos)
    {
        if (om.getMetaDataManager().isPersistentInterface(type))
        {
            // ********* This code is for the "persistent-interfaces" JDO feature **********
            // It does not work for normal interfaces and should be left well alone IMHO
            // The method MultiMapping.getObject() should be used for all normal persistence cases
            // and one day someone needs to comment on why this code exists and what it is trying to do that is
            // different from MultiMapping.getObject()
            String[] implTypes = null;
            if (this.implementationClasses != null)
            {
                // Use the implementations specified by the user for this field
                implTypes = StringUtils.split(implementationClasses, ",");
            }
            else
            {
                // Use the available implementation types
                implTypes = om.getMetaDataManager().getClassesImplementingInterface(getType(), om.getClassLoaderResolver());
            }

            // Go through the possible types for this field and find a non-null value (if there is one)
            int n = 0;
            for (int i=0; i<implTypes.length; i++)
            {
                JavaTypeMapping mapping;
                if (implTypes.length > javaTypeMappings.length)
                {
                    // all mappings stored to the same column(s), so same FK
                    PersistenceCapableMapping m = ((PersistenceCapableMapping) javaTypeMappings[0]);
                    MappedStoreManager storeMgr = (MappedStoreManager)om.getStoreManager();
                    mapping = dba.getMapping(om.getClassLoaderResolver().classForName(implTypes[i]), storeMgr);
                    for (int j = 0; j < m.getDataStoreMappings().length; j++)
                    {
                        mapping.addDataStoreMapping(m.getDataStoreMappings()[j]);
                    }
                    for (int j = 0; j < m.getJavaTypeMapping().length; j++)
                    {
                        ((PersistenceCapableMapping) mapping).addJavaTypeMapping(m.getJavaTypeMapping()[j]);
                    }
                    ((PersistenceCapableMapping) mapping).setReferenceMapping(m.getReferenceMapping());
                }
                else
                {
                    mapping = javaTypeMappings[i];
                }
                int[] posMapping;
                if (n >= pos.length)
                {
                    // this means we store all implementations to the same columns,
                    // so we reset the index
                    n = 0;
                }
                if (mapping.getReferenceMapping() != null)
                {
                    posMapping = new int[mapping.getReferenceMapping().getNumberOfDatastoreFields()];
                }
                else
                {
                    posMapping = new int[mapping.getNumberOfDatastoreFields()];
                }
                for (int j = 0; j < posMapping.length; j++)
                {
                    posMapping[j] = pos[n++];
                }           
                Object value = null;
                try
                {
                    // Retrieve the value (PC object) for this mappings' object
                    value = mapping.getObject(om, rs, posMapping);
                }
                catch (NullValueException e)
                {
                    // expected if implementation object is null and has primitive
                    // fields in the primary key
                }
                catch (JPOXObjectNotFoundException onfe)
                {
                    // expected, will try next implementation
                }
                if (value != null)
                {
                    if (value instanceof OID)
                    {
                        // What situation is this catering for exactly ?
                        String className;
                        if (mapping.getReferenceMapping() != null)
                        {
                            className = mapping.getReferenceMapping().getDataStoreMapping(0).getDatastoreField().getStoredJavaType();
                        }
                        else
                        {
                            className = mapping.getDataStoreMapping(0).getDatastoreField().getStoredJavaType();
                        }
                        value = OIDFactory.getInstance(om, className, ((OID)value).getKeyValue());
                        return om.findObject(value, false, true, null);
                    }
                    else if (om.getClassLoaderResolver().classForName(getType()).isAssignableFrom(value.getClass()))                
                    {
                        return value;
                    }
                }
            }
            return null;
        }
        else
        {
            // Normal persistence goes via MultiMapping.getObject()
            return super.getObject(om, rs, pos);
        }
    }
}
TOP

Related Classes of org.jpox.store.mapped.mapping.InterfaceMapping

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.