if (source == null)
{
return null;
}
Class<?> sourceObjectClass = source.getClass();
EntityMetadata metadata = KunderaMetadataManager.getEntityMetadata(kunderaMetadata, sourceObjectClass);
if (metadata == null)
{
return source;
}
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
metadata.getPersistenceUnit());
EntityType entityType = metaModel.entity(sourceObjectClass);
// May break for mapped super class.
Object id = null;
if (metadata.getRelations() != null && !metadata.getRelations().isEmpty())
{
id = PropertyAccessorHelper.getId(source, metadata);
StringBuilder keyBuilder = new StringBuilder(sourceObjectClass.getName());
keyBuilder.append("#");
keyBuilder.append(id);
Object copiedObjectInMap = copiedObjectMap.get(keyBuilder.toString());
if (copiedObjectInMap != null)
{
return copiedObjectInMap;
}
}
// Copy Columns (in a table that doesn't have any embedded objects
target = sourceObjectClass.newInstance();
Iterator<Attribute> iter = entityType.getAttributes().iterator();
while (iter.hasNext())
{
Attribute attrib = iter.next();
Field columnField = (Field) attrib.getJavaMember();
if (attrib.getPersistentAttributeType().equals(PersistentAttributeType.EMBEDDED)
|| attrib.getPersistentAttributeType().equals(PersistentAttributeType.ELEMENT_COLLECTION))
{
EmbeddableType embeddedColumn = metaModel.embeddable(((AbstractAttribute) attrib)
.getBindableJavaType());
Object sourceEmbeddedObj = PropertyAccessorHelper.getObject(source, columnField);
if (sourceEmbeddedObj != null)
{
if (metaModel.isEmbeddable(((AbstractAttribute) attrib).getBindableJavaType()))
{
if (attrib.isCollection())
{
Class<?> ecDeclaredClass = columnField.getType();
Class<?> actualEcObjectClass = sourceEmbeddedObj.getClass();
Object targetCollectionObject = actualEcObjectClass.newInstance();
// Copy element collections for List and Set
if (sourceEmbeddedObj instanceof Collection)
{
Class<?> genericClass = PropertyAccessorHelper.getGenericClass(columnField);
for (Object sourceEcObj : (Collection) sourceEmbeddedObj)
{
Object targetEcObj = null;
if (sourceEcObj != null
&& PersistenceType.BASIC.equals(embeddedColumn.getPersistenceType()))
{
PropertyAccessor accessor = PropertyAccessorFactory
.getPropertyAccessor(sourceEcObj.getClass());
if (accessor != null)
{
targetEcObj = accessor.getCopy(sourceEcObj);
}
}
else if (sourceEcObj != null
&& PersistenceType.EMBEDDABLE.equals(embeddedColumn
.getPersistenceType()))
{
targetEcObj = genericClass.newInstance();
for (Field f : genericClass.getDeclaredFields())
{
if (f != null && !Modifier.isStatic(f.getModifiers()))
{
PropertyAccessorHelper.set(targetEcObj, f,
PropertyAccessorHelper.getObjectCopy(sourceEcObj, f));
}
}
}
if (List.class.isAssignableFrom(ecDeclaredClass))
{
Method m = actualEcObjectClass.getMethod("add", Object.class);
m.invoke(targetCollectionObject, targetEcObj);
}
else if (Set.class.isAssignableFrom(ecDeclaredClass))
{
Method m = actualEcObjectClass.getMethod("add", Object.class);
m.invoke(targetCollectionObject, targetEcObj);
}
}
}
// Copy element collection for Map
else if (sourceEmbeddedObj instanceof Map)
{
for (Object sourceKey : ((Map) sourceEmbeddedObj).keySet())
{
Object targetKey = null;
Object targetValue = null;
if (PersistenceType.BASIC.equals(embeddedColumn.getPersistenceType()))
{
// Create copy of map key
if (sourceKey != null)
{
PropertyAccessor keyAccessor = PropertyAccessorFactory
.getPropertyAccessor(sourceKey.getClass());
if (keyAccessor != null)
{
targetKey = keyAccessor.getCopy(sourceKey);
}
}
else
{
targetKey = null;
}
// Create copy of map value
Object sourceValue = ((Map) sourceEmbeddedObj).get(sourceKey);
if (sourceValue != null)
{
PropertyAccessor valueAccessor = PropertyAccessorFactory
.getPropertyAccessor(sourceValue.getClass());
if (valueAccessor != null)
{
targetValue = valueAccessor.getCopy(sourceValue);
}
}
else
{
targetValue = null;
}
if (Map.class.isAssignableFrom(ecDeclaredClass))
{
Method m = actualEcObjectClass.getMethod("put", new Class[] {
Object.class, Object.class });
m.invoke(targetCollectionObject,
new Object[] { targetKey, targetValue });
}
}
}
}
PropertyAccessorHelper.set(target, columnField, targetCollectionObject);
}
else
{
// Copy embedded objects
Class<?> embeddedColumnClass = columnField.getType();
Object targetEmbeddedObj = embeddedColumnClass.newInstance();
Set<Attribute> columns = embeddedColumn.getAttributes();
for (Attribute column : columns)
{
PropertyAccessorHelper.set(
targetEmbeddedObj,
(Field) column.getJavaMember(),
PropertyAccessorHelper.getObjectCopy(sourceEmbeddedObj,
(Field) column.getJavaMember()));
}
PropertyAccessorHelper.set(target, columnField, targetEmbeddedObj);
}
}
else if (((AbstractAttribute) attrib).getJPAColumnName() != null)
{
// Copy columns
PropertyAccessorHelper.set(target, columnField, sourceEmbeddedObj);
}
}
}
else if (attrib.getPersistentAttributeType().equals(PersistentAttributeType.BASIC))
{
PropertyAccessorHelper.set(target, columnField,
PropertyAccessorHelper.getObjectCopy(source, columnField));
}
}
// Put this object into copied object map
if (id != null)
{
StringBuilder keyBuilder = new StringBuilder(sourceObjectClass.getName());
keyBuilder.append("#");
keyBuilder.append(id);
copiedObjectMap.put(keyBuilder.toString(), target);
}
// Copy Relationships recursively
for (Relation relation : metadata.getRelations())
{
if (relation != null)
{
Field relationField = relation.getProperty();
Object sourceRelationObject = PropertyAccessorHelper.getObject(source, relationField);