views:

97

answers:

2

Using ArgoUML, I very quickly created this trivial representation of a few Domain classes (Person, Store, Product) and their relationships. UML Model

I'm struggling with the implementation of the relationships. Below was my initial approach for the Person domain, but it seems that I am missing something important.

class PersonToPerson {
    Person from
    Person to
    String relation

    static constraints = {
         relation(inList:["Friend to", "Enemy of", "Likes", "Hates"])
    }
    static belongsTo = [ Person ]
}


class Person {
    String firstName
    String secondName
    .
    .
    .
    static hasMany= [ personToPerson:PersonToPerson, 
                      personToStore:PersonToStore ]
}

Edit: updated question for clarity


After thinking on the problem I think I have a better way to ask the question(s). In the implementation of PersonToPerson above I have the relation as a simple string. I want the user to be able to select from a list of unique relations, which are defined in the constraints, for the string value for PersonToPerson. So this leads to the questions...

  1. Should personToPerson and personToStore be consolidated into one list of type Relationship? Or should they stay independent lists as shown?
  2. What is the mechanism to allow the user to add new values to the relation constraint?
A: 

Look fine. You may want to consider a belongsTo in the PersonToPerson class.

Also, your has many in Person should be: [ personToPersons:PersonToPerson.... <- remove the s

Dean Del Ponte
Thanks Dean, I incorporated your recommendations then updated the question in an effort to make it clearer.
nathan
+1  A: 

1) Domain model

Keep your code simple. Don't create generic data model. It's way to hell. When you personToPerson and personToStore keep separate, it's much easier to follow your code.

Actually suggested solution makes it possible to access relations as consolidated and independent list simultaneously.

For this problem I would use inheritance feature in GORM.

Your classes would look like this:

class Person {
    String name
    static hasMany = [personToPerson:PersonToPerson,
                      personToProduct:PersonToProduct,
                      personToStore:PersonToStore]

    static mappedBy = [personToPerson:"from"]
}

class Product{
    String productName
}

class Relationship{
    String note
}

class Store{
    String storeName
}

class PersonToPerson extends Relationship{
    Person from
    Person to
    String relation

    static constraints = {
         relation(inList:["Friend to", "Enemy of", "Likes", "Hates"])
    }
    static belongsTo = [ from:Person ]
}

class PersonToProduct extends Relationship{
    Person person
    Product product
    String relation

    static constraints = {
         relation(inList:["likes", "dislikes"])
    }
    static belongsTo = [ person:Person ]
}

class PersonToStore extends Relationship{
    Person person
    Store store
    String relation

    static constraints = {
        relation(inList:["Stock person", "Owner", "Manager", "Patron"])
    }
    static belongsTo = [ person:Person ]
}

DB schema for Person, Product and Store is usual. But for Relational domains look like this:

Relationship

Field      Type         Null Default 
id         bigint(20)   No   
version    bigint(20)   No   
note       varchar(255) No   
class      varchar(255) No   
person_id  bigint(20)   Yes  NULL  
product_id bigint(20)   Yes  NULL  
relation   varchar(8)   Yes  NULL  
from_id    bigint(20)   Yes  NULL  
to_id      bigint(20)   Yes  NULL  
store_id   bigint(20)   Yes  NULL   

Relationship domain makes possible to access all relational domain throw one domain.

2) Constraint

Just switch inList to validator. Than you can store constrain in file or DB. See documentation or file example.

Example how to store constraint values in DB. First create a domain object.

class Constrain{
    String name
    String type
}

Than the domain class looks:

class PersonToPerson extends Relationship{
    Person from
    Person to
    String relation

    static constraints = {
         relation(nullable:false, validator:{val, obj ->
             def list = Constrain.findAllByType('person').collect{it.name}
             return list.contains(val)
         })
    }
    static belongsTo = [ from:Person ]
}
amra
Exactly what I was looking for, thank you.
nathan