Community
Participate
Working Groups
Build Identifier: I20100608-0911 Wrote a simple ecore-Model for property-Files, and made a simple test whether the definition and usage of variables is possible. I used Acceleo 3.1.0M5 for this. In the template I store for some reasons values temporary to access them for a later usage. If I use the java service with a static parameter, it seems like this java service call is optimized to be executed just one time. First write a simple template, where two java services are used, one is for setting, the other for reading internal values: [comment encoding = UTF-8 /] [module generate('properties')/] [query public setGlobalProperty(property: String , value: String) : Boolean = invoke('org.eclipse.acceleo.module.sample.services.GlobalProperties','setProperty(java.lang.String, java.lang.String)',Sequence{property,value})/] [query public getGlobalProperty(property: String) : String = invoke('org.eclipse.acceleo.module.sample.services.GlobalProperties','getProperty(java.lang.String)',Sequence{property})/] [template public generate(p : PropertiesType)] [file ('props.txt', false, 'UTF-8')] [for ( pp : PropertyType | p.property ) ] [setGlobalProperty('lastProperty',pp.name)/] [setGlobalProperty(pp.name, pp.value)/] Save of '[pp.name/]' with '[pp.value/]' [let last : String = pp.name ] 1.) read '[last/]' with '[getGlobalProperty(last)/]' [/let] [let last : String = getGlobalProperty('lastProperty') ] 2.) read '[last/]' with '[getGlobalProperty(last)/]' [/let] [/for] [/file] [/template] 2.) Implement the java services: public class GlobalProperties { private static Properties properties = new Properties(); public static String getProperty( String property ) { String value = properties.getProperty( property ); System.out.println( "getProperty: property '" + property + "' value '" + value + "'" ); return value; } public static void setProperty(String property,String value) { String _value = properties.getProperty( property ); System.out.println( "setProperty: property '" + property + "' value '" + value + "' replacing '" + _value + "'" ); properties.setProperty( property, value ); _value = properties.getProperty( property ); System.out.println( "setProperty: property '" + property + "' value '" + _value + "'" ); } } Under the console you see: setProperty: property 'lastProperty' value 'a' replacing 'null' setProperty: property 'lastProperty' value 'a' setProperty: property 'a' value 'b' replacing 'null' setProperty: property 'a' value 'b' getProperty: property 'a' value 'b' getProperty: property 'lastProperty' value 'a' setProperty: property 'lastProperty' value 'b' replacing 'a' setProperty: property 'lastProperty' value 'b' setProperty: property 'b' value 'c' replacing 'null' setProperty: property 'b' value 'c' getProperty: property 'b' value 'c' setProperty: property 'lastProperty' value 'd' replacing 'b' setProperty: property 'lastProperty' value 'd' setProperty: property 'd' value 'e' replacing 'null' setProperty: property 'd' value 'e' getProperty: property 'd' value 'e' As result the following is produced: Save of 'a' with 'b' 1.) read 'a' with 'b' 2.) read 'a' with 'b' Save of 'b' with 'c' 1.) read 'b' with 'c' 2.) read 'a' with 'b' Save of 'd' with 'e' 1.) read 'd' with 'e' 2.) read 'a' with 'b' Reproducible: Always Steps to Reproduce: 1.) Take some input model (independent) 2.) Build two java services, one for storing, one for accessing 3.) Write a template where the values of some variables are exchanged during the generation phase See the details for implementation ;-)
Same works, if a "random" function with no parameter is used. Only iff a service wrapper has at least one parameter, which is not constant, the service wrapper is invoked multiple times.
I haven't read in detail your example but this sentence seems to explain your whole problem: "it seems like this java service call is optimized to be executed just one time." The problem is not the Java service, the problem comes from the query. Your Java service is inside of a query. A query has its result stored in a cache, if you call it twice in a row with the same argument, we won't execute it again, we will look for the result in the cache. You should try with the [invoke(...)/] in a template like this: [template public setGlobalProperty(property: String , value: String)][invoke('org.eclipse.acceleo.module.sample.services.GlobalProperties','setProperty(java.lang.String, java.lang.String)',Sequence{property,value})/][/template] and [template public getGlobalProperty(property: String)] [invoke('org.eclipse.acceleo.module.sample.services.GlobalProperties','getProperty(java.lang.String)',Sequence{property})/][/template] With a query, "getGlobalProperty('lastProperty')" will always be evaluated only one time since it always uses the same parameter. If you want to improve the performances of a generator, you can use some well chosen queries for the big operations on your model like MyModelRoot.eAllContents() for example.