youjenlee
youjenlee

Reputation: 69

How to reuse code block which describe similiar ant build logic in groovy?

How to reuse code block which describe similiar ant build logic in groovy?

If we have build logic which was implemented by Groovy AntBuilder, just like code below:

ant.someTask(attr1:value1, attr2:value2) {
    configuration1(param1:args1, param2:args2){
        similiarStructure(additionalArgs:aaa){
            setting1(param5:value5) {
                //...blah blah blah
            }
            //further more settings, may be or may be not the same with similiarStructure below
        }
    }

    configuration2(param3:args3, param4:args4){
        similiarStructure(additionalArgs:aaa){
            setting1(param5:value5) {
                //...blah blah blah
            }
            //further more settings, may be or may be not the same with similiarStructure below
        }
    }
}

Are there any ways to reuse Groovy AntBuilder code block, which could brief the statment in configuration2 ?
I've try to predefine closures and inject them in both configuration,
but it fails with property not found exception while initializing closure.

Upvotes: 0

Views: 130

Answers (2)

Peter Ledbrook
Peter Ledbrook

Reputation: 4492

I'll provide two answers so you can select which one is more appropriate for your use case and test it. The solutions depend on at what level you want the shared config.

If you want a more general purpose solution that allows you to share the whole of the similarStructure block, you need to perform some more advanced work. The trick is to ensure that the delegate of the shared configuration closure is set appropriately:

def sharedConfig = {
    similarStructure(additionalArgs:aaa) {
        setting1(param5:value5) {
            //...blah blah blah
        }
    }
}

ant.someTask(attr1: value1, attr2: value2) {
    configuration1(param1:args1, param2:args2){
        applySharedConfig(delegate, sharedConfig)
    }

    configuration2(param3:args3, param4:args4){
        applySharedConfig(delegate, sharedConfig)
    }
}

void applySharedConfig(builder, config) {
    def c = config.clone()
    c.resolveStrategy = Closure.DELEGATE_FIRST
    c.delegate = builder
    c.call()
}

Although the applySharedConfig() method seems ugly, it can be used to share multiple configurations across different tasks.

One thing to bear in mind with this solution is that the resolveStrategy of the closure can be very important. I think both DELEGATE_FIRST and OWNER_FIRST (the default) will work fine here. If you run into what appear to be name resolution problems (missing methods or properties) you should try switching the resolution strategy.

Upvotes: 1

Peter Ledbrook
Peter Ledbrook

Reputation: 4492

I'll provide two answers so you can select which one is more appropriate for your use case and test it. The solutions depend on at what level you want the shared config.

If you are happy to simply share the closure that goes with similarStructure, then the solution is straightforward:

def sharedConfig = {
    setting1(param5:value5) {
        //...blah blah blah
    }
}

ant.someTask(attr1: value1, attr2: value2) {
    configuration1(param1:args1, param2:args2) {
        similarStructure(additionalArgs:aaa, sharedConfig)
    }

    configuration2(param3:args3, param4:args4) {
        similarStructure(additionalArgs:aaa, sharedConfig)
    }
}

The method that is similarStructure should ensure that the sharedConfig closure is properly configured. I haven't tested this, so I'm not entirely sure. The disadvantage of this approach is that you have to duplicate the similarStructure call with its arguments.

Upvotes: 1

Related Questions