Wanted to get a thread started on ideas for how this might work.

The problem generally is that our containers internalise construction, and 
offer no way to parameterise it.

sourceSets {
        custom {}
}

The use has no way of influencing what kind of thing “custom” is. The immediate 
need for this kind of thing is with the publications container. The user needs 
to be able to add arbitrary maven, ivy etc. publication objects.

Options:

1. Add via concrete types, with rigid constructor contract

To add something of a certain type, you specify the actual type, which must 
have a 1 string arg constructor (the item name)…

publications {
        custom(DefaultMavenPublication)
}

class DefaultMavenPublication implements MavenPublication {
        DefaultMavenPublication(String name) { … }
}

2. Add via concrete types, allowing constructor params

publications {
        custom(DefaultMavenPublication, arg1, arg2)
}

class DefaultMavenPublication implements MavenPublication {
        DefaultMavenPublication(String name, Object arg1, Object arg2) { … } // 
arg1 & arg2 could be typed of course
}

3. Add via contract types, using rigid factories…

publications.registerTypeFactory(new MavenPublicationFactory())
publications {
        custom(MavenPublication) {}
}

class MavenPublicationFactory implements DomainObjectFactory<MavenPublication> {
        MavenPublication createDomainObject(String name) {
                instantiator.newInstance(DefaultMavenPublication, name)
        }
}

(not suggesting that as the DomainObjectFactory API, just illustrative)

4. Add via contract types, allowing construction params…

publications.registerTypeFactory(new MavenPublicationFactory())
publications {
        custom(MavenPublication) {}
}

class MavenPublicationFactory implements DomainObjectFactory<MavenPublication> {
        MavenPublication createDomainObject(String name, Object... 
constructionArgs) {  
                // constructionArgs doesn't necessarily need to be passed to 
the constructor
                instantiator.newInstance(DefaultMavenPublication, name, 
*constructionArgs)
        }
}

5. Add via contract types, using typed builders to parameterise

publications.registerTypeBuilder(MavenPublicationBuilder)
publications {
        custom(MavenPublication, «configure the builder by map») {
                someMethodOnMavenPublication()
        }
}

publications.registerTypeBuilder(MavenPublicationBuilder)
publications {
        custom MavenPublication), {
                « configure builder by closure »
        }, {
                someMethodOnMavenPublication()
        }
}
class MavenPublicationBuilder implements DomainObjectBuilder<MavenPublication> {
        
        MavenPublicationBuilder(String domainObjectName, Instantiator 
instantiator) { … }

        MavenPublication build() {
                instantiator.newInstance(DefaultMavenPublication, name)
        }
}


I think option 3 is the most desirable, if we can avoid the need to 
parameterise what gets created at construction time. 5 offers the most 
flexibility, but I can't think of a way to avoid making the DSL so cumbersome 
and to avoid the complexity.

Perhaps the two aren't mutually exclusive. We could start with 3, and then add 
something like 5 later if it turns out to be necessary.

1 and 2 are non starters for me. There needs to be indirection between the 
requested and concrete type.

I don't like 4 because it's so loose. There's no compile time typing and no 
good way to specify the contract.


Given those options (feel free to propose others), I'd vote for starting with 3 
I think. 

-- 
Luke Daley
Principal Engineer, Gradleware 
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to