Dynamic Domain Properties

  • Tags : gorm
  • Latest : 0.2
  • Last Updated: 12 November 2010
  • Grails version : 1.2.0 > *
  • Authors : Jean Barmash
4 votes
Dependency :
compile ":dynamic-domain-properties:0.2"

Documentation

Summary

Installation

grails install-plugin dynamic-domain-properties

Description

This plugin enables domain classes to take on arbitrary properties. These properties don't have to be consistent across different instances, which lets you have (almost) arbitrary data attached to any given instance of a domain class. If you're considering spewing many child classes all over your domain to represent various different types of the same superclass, consider this plugin's approach instead.

If you're used to/excited about schema-less persistence stores like CouchDB, you can think of this plugin as giving you all that same functionality while acting within a SQL context.

This plugin also gives something vaguely akin to Rails's has_many_through via its delegating usage.

The basic implementation detail of this plugin is that there is a new domain class (DynamicProperty) which stores the dynamic properties in the database in a fairly human-readable way.

Installation

See the installation tab above.

Usage

Simple

Given this class:

class Simpleton {
  static dynamicProperties = true
}

You can then assign (almost) arbitrary values to arbitrary properties:

def me = new Simpleton()
me.foo = "Foo!"
me.baz = [ 
  list:[1,2,3],
  map:[robertFischer:'http://enfranchisedmind.com/blog/'],
  domainObject:new Simpleton()
] 
me.save() // Now persisted to the database

Delegating

Given these classes:

class Simpleton {
  static dynamicProperties = true
  String reifiedProperty
}

class Delegator { static dynamicProperties = ['delegateTo'] Simpleton delegateTo }

You can then assign (almost) arbitrary values to arbitrary properties on Simpleton and Delegator, and you can also set reifiedProperty via the parent Delegator instance.

// Retrieve delegate's dynamic property value
def me = new Delegator()
me.delegateTo = new Simpleton()
me.delegateTo.foo = "Foo!"
assertEquals "Foo!", me.foo

// Set delegate's reified property value
def me = new Delegator()
me.delegateTo = new Simpleton()
me.reifiedProperty = "Yup, reified!"
assertEquals "Yup, reified!", me.delegateTo.reifiedProperty

New GORM Methods

This plugin is primarily focused on the handling of the dynamic properties via propertyMissing. But if you're curious about more dynamic property details, there are a few new methods you can try out.

Instances of GORM classes that have a Groovy-true "dynamicProperties" property will gain the following instance methods.

  • hasDynamicProperties() — Returns true if the domain class has dynamic properties. Returns false otherwise. This method (returning false) is added to the Object class, so you can query everything.
  • getLocalDynamicProperties() — Gets the DynamicProperty instances for this instance.
  • addLocalDynamicProperty(DynamicProperty) — Adds a new DynamicProperty expressly on this instance (does not delegate, does not validate DynamicProperty).
  • addLocalDynamicProperty(String, Object) — Adds a new local dynamic property (does not delegate, does not validate).
  • getLocalDynamicProperty(String) — Gets the DynamicProperty instance for the give name, returning null if there isn't one.
  • setLocalDynamicProperty(String,Object) — Sets or adds the local dynamic property with the given name to the given value.
  • hasProperty(String) — Returns true if the instance (or its delegate) has a given property; returns false otherwise. No distinction is made between reified and dynamic properties.
  • getLocalDynamicPropertiesMap() — Provides an unmodifiable map of property names onto property values for this instance's local dynamic properties.
  • getLocalDynamicPropertyValue(String) — Gets the value of the local dynamic property with the given name (returning null if there is no property with the given name).
  • hasLocalDynamicProperty(String) — Returns true if the instance has a local dynamic property with the given name.
  • getDynamicPropertyValue(String) — Returns the value of the given dynamic property, querying delegates if need be.
  • setDynamicPropertyValue(String, Object) — Sets the value of the given dynamic property, setting on delegates if need be.

Details

Allowed Property Type Details

The following types are allowed to be dynamic properties:

  • Primitive Types and their wrappers
  • null
  • Class
  • Domain classes
  • Any implementation of Collection
  • Any implementation of Map (a Map is not a Collection in Java)
  • Any class which has a static fromString(String) method that can parse a call to toString() and return an object of the same type.

More Info

Repository

The source repository for this project is on GitHub:

https://github.com/vk77/Dynamic-Domain-Properties

Demo App

To see how this plugin in action, pull down the GitHub repository, and then look into the BasicUsage app. Take a look at the domain classes, and then see ./test/integration/BasicUsageTests.groovy for a demonstration of how the basic usage works.

Note: the original plugin code that's Grails 1.2 compatible is here http://github.com/RobertFischer/Dynamic-Domain-Properties (+)

License

Apache V2.