> Only works for basic stuff. I found this and started hacking it.
> Trying to clone as part of a test. Clone, delete, compare etc.
>
> My test still has a few problems - Probably going to wrap in
> transactions. Either way the code below does pass all but one of the
> tests I wrote.
>
> null
> java.util.ConcurrentModificationException
> at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
> at java.util.HashMap$KeyIterator.next(HashMap.java:828)
> at
> org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:577)
> at
> org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1220)
> at
> org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1196)
> at org.codehaus.groovy.runtime.dgm$110.invoke(Unknown Source)
> at
> org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:270)
> at
> org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
> at
> org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
> at
> au.com.interlated.emissionscalculator.EmissionsParentImpl$_deepClone_closure1.doCall(EmissionsParentImpl.groovy:37)
> at sun.reflect.GeneratedMethodAccessor943.invoke(Unknown Source)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at
> org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
> at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
> at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058)
> at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1070)
> at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886)
> at groovy.lang.Closure.call(Closure.java:282)
> at groovy.lang.Closure.call(Closure.java:295)
>
>
>
> public abstract class EmissionsParentImpl implements EmissionsParent {
> //
http://studio945.com/djdaugherty/?p=386> /*
> * Clones a domain object and recursively clones children, clearing
> ids and
> * attaching children to their new parents. Ownership relationships
> (indicated
> * by GORM belongsTo keyword) cause "copy as new" (a recursive deep
> clone),
> * but associations without ownership are shallow copied by reference.
> */
>
> public Object deepClone(domainInstanceToClone) {
>
> //Our target instance for the instance we want to clone
> // recursion
> def newDomainInstance =
> domainInstanceToClone.getClass().newInstance()
>
> //Returns a DefaultGrailsDomainClass (as interface
> GrailsDomainClass) for inspecting properties
> def domainClass =
> ApplicationHolder.application.getDomainClass(newDomainInstance.getClass().name)
>
> domainClass?.persistentProperties?.each {prop ->
> if (prop.association) {
> if (prop.owningSide) {
> //we have to deep clone owned associations
> if (prop.oneToOne) {
> def newAssociationInstance =
> deepClone(domainInstanceToClone?."${prop.name <
http://prop.name>}")
> newDomainInstance."${prop.name
> <
http://prop.name>}" = newAssociationInstance
> }
> else {
> domainInstanceToClone."${prop.name
> <
http://prop.name>}".each { associationInstance ->
> def newAssociationInstance =
> deepClone(associationInstance)
>
> newDomainInstance."addTo${StringUtils.capitalize(prop.name
> <
http://prop.name>)}"(newAssociationInstance)
> }
> }
> }
> else {
> if (!prop.bidirectional) {
> //If the association isn't owned or the owner,
> then we can just do a shallow copy of the reference.
> newDomainInstance."${prop.name
> <
http://prop.name>}" = domainInstanceToClone."${prop.name
> <
http://prop.name>}"
> }
> // @@JR
> // Yes bidirectional and not owning. E.g. clone
> Report, belongsTo Organisation which hasMany
> // manyToOne. Just add to the owning objects
> collection.
> else {
> if (prop.manyToOne) {
> newDomainInstance."${prop.name
> <
http://prop.name>}" = domainInstanceToClone."${prop.name
> <
http://prop.name>}"
> def owningInstance =
> domainInstanceToClone."${prop.name <
http://prop.name>}"
> // Need to find the collection.
> String otherSide =
> StringUtils.capitalize(prop.otherSide.name <
http://prop.otherSide.name>)
>
> owningInstance."addTo${otherSide}"(newDomainInstance)
> }
> }
> }
> }
> else {
> //If the property isn't an association then simply
> copy the value
> newDomainInstance."${prop.name <
http://prop.name>}" =
> domainInstanceToClone."${prop.name <
http://prop.name>}"
> }
> }
>
> return newDomainInstance
> }
>
> /**
> * Copy the object for testing purposes.
> * @return
> */
> }
>