Search code examples
grailspluginstaxonomy

How to add a hierarchy to taxons using grails taxonomy plugin?


I would like to have some kind of hierarchy inside my taxons I added to my domain class Foo using Grails Taxonomy plugin. http://grails.org/plugin/taxonomy

Example (annotation to build something like a tree): {A:{A1:{A1I, A1II}, A2:{A2I}}, B:{B1:{B1I}, B2:{B2II}}}

foo.addToTaxonomy(['A1', 'A2'], "A") foo.addToTaxonomy(['B1', 'B2'], "B")

What is the way have children for A1, A2, B1 and B2 too?


Solution

  • Let's say your taxonomy trees are defined by

    {A:{A1:{A1I, A1II}, A2:{A2I}}, B:{B1:{B1I}, B2:{B2II}}}

    and the notation A->A1->A1I describes a path in a tree. In this case, the path is in the A tree from its root (A) to a leaf (A1I).

    If you want to add foo to the A->A1->A1I taxonomy, you would use foo.addTaxonomy(['A', 'A1', 'A1I']). The list parameter for the function addTaxonomy actually represents a path in a taxonomy tree. The second parameter accepted by addTaxonomy is optional and essentially defines the scope for your taxonomy tree. So, if I were to do

    foo.addTaxonomy(['A', 'A1', 'A1I'], 'scope1')
    foo.addTaxonomy(['A', 'A1', 'A1I'], 'scope2')
    

    This would place foo in A->A1->A1I in scope1 and in scope2. They're essentially two different trees. You probably don't need this.

    Here are some examples related to the tree structure you described in your question:

    add to A->A1->A1II

    foo.addTaxonomy(['A', 'A1', 'A1II'])
    

    add to A2->A2I

    foo.addTaxonomy(['A2', 'A2I'])
    

    add to B->B1->B1I

    foo.addTaxonomy(['B', 'B1', 'B1I'])
    

    add to B2->B2I

    foo.addTaxonomy(['B2', 'B2I'])
    

    The 4 examples above create trees rooted at A, A2, B, and B2, respectively.

    If you don't want to define the absolute path of the Taxon, you can do something like this:

    def taxonPath(taxonName) {
        def currentTaxon = Taxon.findByName(taxonName)
        def path = [currentTaxon.name]
    
        while(currentTaxon.parent) {
            currentTaxon = currentTaxon.parent
            path = [currentTaxon.name] + path
        }
    
        return path
    }
    
    taxonomyService.createTaxonomyPath(['B', 'B2', 'B2I'])
    def book = new Book(name:"hacky solution")
    book.addToTaxonomy(taxonPath('B2I'))
    

    This is equivalent to book.addToTaxonomy(['B', 'B2', 'B2I']). You will also need to import com.grailsrocks.taxonomy.Taxon and inject taxonomyService into your artifact, e.g. (def taxonomyService) for this to work.

    The solution feels a little hacky and inefficient, but it works.