About Me

Mein Bild
Freelancing software developer / architect, mobile geek. Topics: Software technologies (java, groovy, agile), politics, web, science, green, mobile, android.
Homepage: www.tutaona.com

"The absence of limitations is the enemy of art." - Orson Welles
Posts mit dem Label groovy werden angezeigt. Alle Posts anzeigen
Posts mit dem Label groovy werden angezeigt. Alle Posts anzeigen

Montag, 25. Juni 2012

Easy JSON Building

def p = new Expando(
    name:'Mary', 
    pets:[
        new Expando(name:'Fido', species:'Dog'),
        new Expando(name:'Snickers', species:'Cat')
    ]
)

def json = new JsonBuilder()
json( {
    name p.name,
    pets( p.pets.collect {[
        name:it.name,
        species:it.species
    ]})
})
JsonOutput.prettyPrint(json.toString())

Mittwoch, 11. Mai 2011

Cloning Objects in Groovy

Cloning objects is very often useful. groovy offers excellent tools for doing this by its meta programming features.

MOP the properties 1
class User {
def String name
def Boolean id
// the list carry on .. 
def User createNewInstance(){
User.metaClass.getProperties().findAll(){it.getSetter()!=null}.inject(new User()) { user,metaProp->
metaProp.setProperty(user,metaProp.getProperty(this))
user
}
}
}

Copying JSONObject to a bean
/**
 * Copies the properties of a JSONObject to a bean.
 *
 * @param source the JSONObject
 * @param target the target bean
 * @param ignoreProperties a list of property names to be ignored
 * @return the fully qualified class name of the originally marshalled class
 */
def copyJSONObjectPropertiesToBean(JSONObject source, target, ignoreProperties) {
ignoreProperties.add "class"
target.metaClass.properties.each {
if (!ignoreProperties.contains(it.name) && source.containsKey(it.name)) {
it.setProperty(target, source[it.name])
}
}
source.class
}
Grails simple copy

/**
 * Creates a new instance of class based on it's fully qualified class name and sets it's properties.
 * The instantiation works only when instantiating a grails domain class
 *
 * @param clazzName the fully qualified class name
 * @param properties an object with the properties to copy
 * @return an instance of the specified class
 */
def newDomainClassInstance(properties) {
def clazzName = properties.remove("class")
if(!clazzName) {
throw new IllegalArgumentException("attribute 'class' is missing")
}
def clazz = grailsApplication.getDomainClass(clazzName).getClazz()
def instance = clazz.newInstance(properties)
return instance
}


/*
 * 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}")
                        newDomainInstance."${prop.name}" = newAssociationInstance
                    }
                    else {
                        domainInstanceToClone."${prop.name}".each { associationInstance ->
                            def newAssociationInstance = deepClone(associationInstance)
                            newDomainInstance."addTo${StringUtils.capitalize(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}" = domainInstanceToClone."${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}" = domainInstanceToClone."${prop.name}"
                           def owningInstance = domainInstanceToClone."${prop.name}"
                           // Need to find the collection.
                           String otherSide = StringUtils.capitalize(prop.otherSide.name)
                           owningInstance."addTo${otherSide}"(newDomainInstance)
                       }
                    }
                }
            }
            else {
                //If the property isn't an association then simply copy the value
                newDomainInstance."${prop.name}" = domainInstanceToClone."${prop.name}"
            }
        }
        return newDomainInstance
    }