Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**********************************************************************
Copyright (c) 2005 Andy Jefferson 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:
...
**********************************************************************/
package org.datanucleus.store.rdbms.mapping.java;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.ExecutionContext;
import org.datanucleus.api.ApiAdapter;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.ColumnMetaData;
import org.datanucleus.metadata.DiscriminatorMetaData;
import org.datanucleus.metadata.DiscriminatorStrategy;
import org.datanucleus.metadata.EmbeddedMetaData;
import org.datanucleus.metadata.FieldPersistenceModifier;
import org.datanucleus.metadata.FieldRole;
import org.datanucleus.metadata.InheritanceMetaData;
import org.datanucleus.metadata.MetaDataManager;
import org.datanucleus.state.ObjectProvider;
import org.datanucleus.store.rdbms.mapping.MappingManager;
import org.datanucleus.store.rdbms.mapping.datastore.DatastoreMapping;
import org.datanucleus.store.rdbms.table.Column;
import org.datanucleus.store.rdbms.table.Table;
import org.datanucleus.util.NucleusLogger;
/**
* Mapping for an embedded PC object.
* The PC object can be embedded directly (1-1 relation) or be the element of
* a collection, or be the key or value of a map.
*/
public abstract class EmbeddedMapping extends SingleFieldMapping
{
protected DiscriminatorMetaData discrimMetaData;
/** Mapping for a discriminator (when supporting inherited embedded objects. */
protected DiscriminatorMapping discrimMapping;
/** Mappings of the fields of the embedded PC. */
protected List javaTypeMappings;
/** ClassLoader resolver */
protected ClassLoaderResolver clr;
/** EmbeddedMetaData for the object being embedded. */
protected EmbeddedMetaData emd;
/** Type name for the object being embedded. */
protected String typeName;
/** Type of PC object. Corresponds to the values in StateManagerImpl. */
protected short objectType = -1;
/** MetaData for the embedded class. */
protected AbstractClassMetaData embCmd = null;
/**
* Initialize this JavaTypeMapping with the given DatastoreAdapter for the given FieldMetaData.
* @param table The datastore container storing this mapping (if any)
* @param clr the ClassLoaderResolver
* @param fmd FieldMetaData for the field to be mapped (if any)
*
* @throws NucleusException
*/
public void initialize(AbstractMemberMetaData fmd, Table table, ClassLoaderResolver clr)
{
throw new NucleusException("subclass must override this method").setFatal();
}
/**
* Initialize this JavaTypeMapping with the given DatastoreAdapter for the given MetaData.
* @param fmd metadata for the field
* @param table Table for persisting this field
* @param clr The ClassLoaderResolver
* @param emd Embedded MetaData for the object being embedded
* @param typeName type of the embedded PC object
* @param objectType Type of the PC object being embedded (see StateManagerImpl object types)
*/
public void initialize(AbstractMemberMetaData fmd, Table table, ClassLoaderResolver clr,
EmbeddedMetaData emd, String typeName, int objectType)
{
super.initialize(fmd, table, clr);
this.clr = clr;
this.emd = emd;
this.typeName = typeName;
this.objectType = (short) objectType;
// Find the MetaData for the embedded PC class
MetaDataManager mmgr = table.getStoreManager().getMetaDataManager();
AbstractClassMetaData rootEmbCmd = mmgr.getMetaDataForClass(typeName, clr);
if (rootEmbCmd == null)
{
// Not found so must be an interface
if (fmd != null)
{
// Try using the fieldTypes on the field/property - we support it if only 1 implementation
String[] fieldTypes = fmd.getFieldTypes();
if (fieldTypes != null && fieldTypes.length == 1)
{
rootEmbCmd = mmgr.getMetaDataForClass(fieldTypes[0], clr);
}
else if (fieldTypes != null && fieldTypes.length > 1)
{
// TODO Cater for multiple implementations
throw new NucleusUserException("Field " + fmd.getFullFieldName() +
" is a reference field that is embedded with multiple possible implementations. " +
"DataNucleus doesnt support embedded reference fields that have more than 1 implementation");
}
}
if (rootEmbCmd == null)
{
// Try a persistent interface
rootEmbCmd = mmgr.getMetaDataForInterface(clr.classForName(typeName), clr);
if (rootEmbCmd == null && fmd.getFieldTypes() != null && fmd.getFieldTypes().length == 1)
{
// No MetaData for the type so try "fieldType" specified on the field
rootEmbCmd = mmgr.getMetaDataForInterface(clr.classForName(fmd.getFieldTypes()[0]), clr);
}
}
}
embCmd = rootEmbCmd;
AbstractMemberMetaData[] embFmds;
if (emd == null && rootEmbCmd.isEmbeddedOnly())
{
// No block yet the class is defined as embedded-only so just use its own definition of fields
embFmds = rootEmbCmd.getManagedMembers();
}
else
{
// block so use those field definitions
embFmds = emd.getMemberMetaData();
}
String[] subclasses = mmgr.getSubclassesForClass(rootEmbCmd.getFullClassName(), true);
if (subclasses != null && subclasses.length > 0)
{
if (rootEmbCmd.hasDiscriminatorStrategy())
{
// Fabricate a DiscriminatorMetaData to use for the embedded object
discrimMetaData = new DiscriminatorMetaData();
InheritanceMetaData embInhMd = new InheritanceMetaData();
embInhMd.setParent(rootEmbCmd);
discrimMetaData.setParent(embInhMd);
// Set strategy based on the inheritance of the embedded object, otherwise class name.
DiscriminatorMetaData dismd = rootEmbCmd.getDiscriminatorMetaDataRoot();
if (dismd.getStrategy() != null && dismd.getStrategy() != DiscriminatorStrategy.NONE)
{
discrimMetaData.setStrategy(dismd.getStrategy());
}
else
{
discrimMetaData.setStrategy(DiscriminatorStrategy.CLASS_NAME); // Fallback to class name
}
// Set column for discriminator
ColumnMetaData disColmd = new ColumnMetaData();
disColmd.setAllowsNull(Boolean.TRUE);
DiscriminatorMetaData embDismd = emd.getDiscriminatorMetaData();
if (embDismd != null && embDismd.getColumnMetaData() != null)
{
disColmd.setName(embDismd.getColumnMetaData().getName());
}
else
{
ColumnMetaData colmd = dismd.getColumnMetaData();
if (colmd != null && colmd.getName() != null)
{
disColmd.setName(colmd.getName());
}
}
discrimMetaData.setColumnMetaData(disColmd);
discrimMapping = DiscriminatorMapping.createDiscriminatorMapping(table, discrimMetaData);
addDatastoreMapping(discrimMapping.getDatastoreMapping(0));
}
else
{
NucleusLogger.PERSISTENCE.info("Member " + mmd.getFullFieldName() + " is embedded and the type " +
"(" + rootEmbCmd.getFullClassName() + ") has potential subclasses." +
" Impossible to detect which is stored embedded. Add a discriminator to the embedded type");
}
}
// Add all fields of the embedded class (that are persistent)
int[] pcFieldNumbers = rootEmbCmd.getAllMemberPositions();
for (int i=0;i 0)
{
for (int i=0;i 0 &&
mapping.getMemberMetaData().getColumnMetaData()[0].getName().equals(nullColumn))
{
// Try to cater for user having an integer based column and value
if (mapping instanceof IntegerMapping ||
mapping instanceof BigIntegerMapping ||
mapping instanceof LongMapping ||
mapping instanceof ShortMapping)
{
Object convertedValue = null;
try
{
if (mapping instanceof IntegerMapping ||
mapping instanceof ShortMapping)
{
convertedValue = Integer.valueOf(nullValue);
}
else if (mapping instanceof LongMapping ||
mapping instanceof BigIntegerMapping)
{
convertedValue = Long.valueOf(nullValue);
}
}
catch (Exception e)
{
}
mapping.setObject(ec, ps, posMapping, convertedValue);
}
else
{
mapping.setObject(ec, ps, posMapping, nullValue);
}
}
else
{
if (mapping.getNumberOfDatastoreMappings() > 0)
{
mapping.setObject(ec, ps, posMapping, null);
}
}
}
}
else
{
ApiAdapter api = ec.getApiAdapter();
if (!api.isPersistable(value))
{
throw new NucleusException(LOCALISER_RDBMS.msg("041016", value.getClass(), value)).setFatal();
}
AbstractClassMetaData embCmd = ec.getMetaDataManager().getMetaDataForClass(value.getClass(), ec.getClassLoaderResolver());
ObjectProvider embSM = ec.findObjectProvider(value);
if (embSM == null || api.getExecutionContext(value) == null)
{
// Assign a StateManager to manage our embedded object
embSM = ec.newObjectProviderForEmbedded(value, false, ownerOP, ownerFieldNumber);
embSM.setPcObjectType(objectType);
}
int n = 0;
if (discrimMapping != null)
{
if (discrimMetaData.getStrategy() == DiscriminatorStrategy.CLASS_NAME)
{
discrimMapping.setObject(ec, ps, new int[]{param[n]}, value.getClass().getName());
}
else if (discrimMetaData.getStrategy() == DiscriminatorStrategy.VALUE_MAP)
{
DiscriminatorMetaData valueDismd = embCmd.getInheritanceMetaData().getDiscriminatorMetaData();
discrimMapping.setObject(ec, ps, new int[]{param[n]}, valueDismd.getValue());
}
n++;
}
for (int i=0; i= 0)
{
// Member is present in this embedded type
Object fieldValue = embSM.provideField(embAbsFieldNum);
if (mapping instanceof EmbeddedPCMapping)
{
mapping.setObject(ec, ps, posMapping, fieldValue, embSM, embAbsFieldNum);
}
else
{
if (mapping.getNumberOfDatastoreMappings() > 0)
{
mapping.setObject(ec, ps, posMapping, fieldValue);
}
}
}
else
{
mapping.setObject(ec, ps, posMapping, null);
}
}
}
}
/**
* Accessor for the embedded object from the result set
* @param ec ExecutionContext
* @param rs The ResultSet
* @param param Array of param numbers in the ResultSet for the fields of this object
* @return The embedded object
*/
public Object getObject(ExecutionContext ec, ResultSet rs, int[] param)
{
return getObject(ec, rs, param, null, -1);
}
/**
* Accessor for the embedded object from the result set
* @param ec ExecutionContext
* @param rs The ResultSet
* @param param Array of param numbers in the ResultSet for the fields of this object
* @param ownerOP ObjectProvider of the owning object containing this embedded object
* @param ownerFieldNumber Field number in the owning object where this is stored
* @return The embedded object
*/
public Object getObject(ExecutionContext ec, ResultSet rs, int[] param, ObjectProvider ownerOP, int ownerFieldNumber)
{
Object value = null;
int n = 0;
// Determine the type of the embedded object
AbstractClassMetaData embCmd = this.embCmd;
if (discrimMapping != null)
{
Object discrimValue = discrimMapping.getObject(ec, rs, new int[]{param[n]});
String className = ec.getMetaDataManager().getClassNameFromDiscriminatorValue((String)discrimValue, discrimMetaData);
embCmd = storeMgr.getMetaDataManager().getMetaDataForClass(className, clr);
n++;
}
// Create a PersistenceCapable to put the values into
Class embeddedType = clr.classForName(embCmd.getFullClassName());
if (mmd.getFieldTypes() != null && mmd.getFieldTypes().length > 0)
{
// Embedded type has field-type defined so use that as our embedded type
embeddedType = ec.getClassLoaderResolver().classForName(mmd.getFieldTypes()[0]);
}
ObjectProvider embOP = ec.newObjectProviderForHollow(embeddedType, (Object)null);
embOP.setPcObjectType(objectType);
value = embOP.getObject();
String nullColumn = null;
String nullValue = null;
if (emd != null)
{
nullColumn = emd.getNullIndicatorColumn();
nullValue = emd.getNullIndicatorValue();
}
// Populate the field values
for (int i=0; i= 0)
{
// Mapping for field that is present in this embedded type, so set the field
if (mapping instanceof EmbeddedPCMapping)
{
// We have a nested embedded
int numSubParams = mapping.getNumberOfDatastoreMappings();
int[] subParam = new int[numSubParams];
int k = 0;
for (int j=n;j= 0)
{
embOP.replaceField(ownerFieldNumberInElement, ownerOP.getObject());
}
}
}
// Register the owner-embedded ObjectProvider relation now we have values set
if (value != null && ownerOP != null)
{
ec.registerEmbeddedRelation(ownerOP, ownerFieldNumber, embOP);
}
return value;
}
/**
* Accessor for the Java type being represented here.
* @return The Java type
*/
public Class getJavaType()
{
return clr.classForName(typeName);
}
}