Jive plugin implementation of Freemarker #list - freemarker

Newbie question here about the connection between FreeMarker templates and Jive plugins (written in Java).
I have inherited an existing, working project with some FTL, as follows:
<#list employeeInstances! as instance>
<tr>
...
</tr>
</#list>
I'm trying to understand how employeeInstances is actually implemented in the Java plugin. There is no reference to 'employeeInstances' anywhere else within the project. The closest is this:
public ArrayList<EmployeeInstance> getEmployeeInstances()
{
...
}
I am guessing that this is what's being called when Jive sees #list employeeInstances. Is that right? Is it basically capitalizing the first letter of the sequence name 'employeeInstances' and then prefixing it with the word 'get'? I couldn't find anything in the FreeMarker or Jive documentation that discussed this.
Thanks.

Check what data-model is passed to Template.process or Environment.process. If it's an instance of the class with the getEmployeeInstances method, then your guess was right. FreeMarker exposes JavaBean properties as variables, so getFoo() becomes to foo.

Related

What does it mean in Groovy to specify a property followed by a closure?

I am completely new to Groovy, trying to learn it, but stymied because I can't parse the syntax well enough to even know where to look in the documentation. I am using Groovy in Gradle. There are many places where examples are given, but no explanation on what it means, so I just need a few pointers.
publishing {
publications {
mavenJava(MavenPublication) {
groupId = 'com.xxx.yyy'
artifactId = 'zzz'
from components.java
}
}
repositories {
mavenLocal();
}
}
The main build code is referring to things on the project class. On that class, I can find a property called publishing, and it is a class PublishingExtension. It appears then that the curly brace starts a closure with code in it. The documentation says this syntax:
publishing { }
configures the PublishingExtension. What I want to understand is what it means (i.e. what is actually happening) when I specify what looks like a property and follow that with a Closure. In the Groovy documentation I could not find any syntax like this, nor explanation. I sure it is something simple but I don't know enough to even know what to look for.
If I visit the Project Class API Docs there is no method there named publishing. Nor is there a property defined by the method getPublishing. Apparently this magic capability is enabled by the publishing plugin. If I visit the Publishing Plugin API Doc there is no description of this publishing property either or how it modifies the base project.
Similarly, drilling down a little more, that closure starts with a symbol publications and in the documentation for the PublishingExtension I find a property which is of type PublicationContainer which is read only. I also find a method named publications which does not accept a closure, but instead a configuration of type Action<? super PublicationContainer>. Again, I don't know how the contents of the curly braces are converted to an Action class instance. How does this object get constructed? Action is an interface, and the only method is execute however it is completely unclear how this action gets constructed.
The block that defines the Action starts with symbol mavenJava that looks like a method, but actually that first symbol is declaring a name of a new object of type MavenPublication named mavenJava. Either this is magically constructed (I don't know the rules) or there is a method called, but which method? What is it about PublicationContainer that allows it to know that an arbitrary mavenJava command is supposed to create an object instance. Then again, the curly braces that follow this, is that a closure, a configuration, or something even more exotic?
So as you can see, I am missing a little info on how Groovy works. So far I can't find documentation that explains this syntax, however it might be there if I knew what to look for. Can anyone explain what the syntax is really doing, or refer me to a site that can explain it?
publishing is called to configure the PublishingExtension.
In PublishingExtension there is a publications method accepting an Action which is usually coerced from a Closure. In Groovy a Closure is automatically converted to an interface with a single method.
mavenJava is a non-existent DSL method, which is passed by Gradle DSL builder to the create method of PublicationContainer:
publishing.publications.create('mavenJava', MavenPublication) {
// Configure the maven publication here
}
groupId and artifactId are properties of MavenPublication and are being set here.
from is the from(component) of MavenPublication and is written using Groovy simplified method call literal without brackets.
In general Gradle uses a root DSL builder which calls the nested DSL builders provided by plugins. Hence sometimes it's difficuilt (also for the IDE) to find proper references of all parts of the build.gradle file.

Find out specific element with unique id from json array

I have json array & want to group weeks according to person id's as mentioned in below example. I tried code but unable to get it because i am new to free-marker code. The JSON Array as follows:-
[{"Hours":"5.500","Status":"Draft","Week":"17","person_name":"Raj","person_id":"1414"},
{"Hours":"0.500","Status":"Draft","Week":"17","person_name":"Raj","person_id":"1414"},
{"Hours":"24.500","Status":"Draft","Week":"14","person_name":"Mukesh","person_id":"1046"},
{"Hours":"7.500","Status":"Draft","Week":"15","person_name":"Mukesh","person_id":"1046"},
{"Hours":"3.000","Status":"Draft","Week":"16","person_name":"Mukesh","person_id":"1046"}]
Could please help me. The output in below foramt
for id {1046:[14,15,16], 1414:[17,17]}
Such kind of restructuring is not something that should be done inside a template. While FTL can add together map-like values and also list-like values, it would be very inefficient to hack this together with that (it's only for very simple tasks). The entries should be already grouped before passing the data to the template.
If you must initiate this from the template, then you will need a utility Java object that has a method that does this grouping, or a TemplateMethodModelEx implementation that does it. Then you call that utility object from the template (like utils.groupByPersonId(foo) or groupByPersonId(foo)). Such utility objects can be exposed to the template on various ways: as part of the data-model, globally as "shared variable" through the freemarker.tempalte.Configuration object, or by ensuring that the utility TemplateMethodModelEx (or any other TemplateModel) class is visible for Java and then do something like <#assign groupByPersonId = 'com.example.GroupByPersonIdMethod'?new()> in the template.

How can I manually compile something inside Eclipse?

One way of doing seemed to be to use the java.lang.Compiler
I tried to use the java.lang.Compiler inside Eclipse anddid not understand the Object any parameters for the methods of that class? And putting in a class did not seem to work either.
Compiler.command(any) // what is meant by any? What are valid objects to put there?
Compiler.compileClass(clazz) // Nothing happens when I out a class in there?
Compiler.compileClasses(string) // hm?
How to can I print a hello message with a Compiler inside Eclipse...?
Reading the documentation is a very important skill you need to learn.
Whenever you come across a class or a method that you don't know the functionality of, simply look at the documentation first.
Here is the docs for java.lang.Compiler: https://docs.oracle.com/javase/7/docs/api/java/lang/Compiler.html
This is the first sentence of the document:
The Compiler class is provided to support Java-to-native-code compilers and related services. By design, the Compiler class does nothing; it serves as a placeholder for a JIT compiler implementation.
So, the answer to your question is, it does nothing. According to the documentation, it does nothing. It is used to start up the Java compiler when the JVM starts. You are not meant to use this.

Cannot Access SysML stereotypes and their properties in Acceleo

I am developing a M2T generator in Acceleo (in Eclipse). The model is basically a UML model with SysML profile created in Papyrus. It includes Blocks and FlowPorts. I have to access these stereotypes but it seems that I cannot retrieve any SysML object even though they appear in list (code suggestion). Actually I have to access ‘Direction’ property of FlowPort associated with Port. I have already tried suggestions and answers from various forums (including https://www.eclipse.org/forums/index.php/t/452587/) but in vain.
The code is given below. I have created java services as suggested by https://www.eclipse.org/forums/index.php?t=msg&th=1060450&goto=1693765& but port.hasStereotype(‘FlowPort’) always return false. I have also tried ‘SysML::PortAndFlows::FlowPort’ instead of ‘FlowPort’. I use Acceleo 3.6.2 on Eclipse Mars.
...
[template public generateElement(model : Model)]
[comment #main/]
[file ('created.txt', false, 'UTF-8')]
[for(port: Port | model.eAllContents(Port))]
[if(port.hasStereotype('FlowPort'))]
OK
[else]
NOT OK
[/if]
[/for]
[/file]
[/template]
I include following metamodels in the Module at the time of creating the module:
http://www.eclipse.org/uml2/5.0.0/UML
http://www.eclipse.org/papyrus/0.7.0/SysML
http://www.eclipse.org/papyrus/0.7.0/SysML/Blocks
http://www.eclipse.org/papyrus/0.7.0/SysML/Constraints
http://www.eclipse.org/papyrus/0.7.0/SysML/PortAndFlows
http://www.eclipse.org/emf/2002/Ecore
Also, I do register required packages including following in registerPackages() of Generate.java as suggested by the link just mentioned above.
// UML2 profiles
URI uri = URI.createURI("platform:/plugin/org.eclipse.uml2.uml.resources");
uriMap.put(URI.createURI(UMLResource.LIBRARIES_PATHMAP), uri.appendSegment("libraries").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.METAMODELS_PATHMAP), uri.appendSegment("metamodels").appendSegment(""));
uriMap.put(URI.createURI(UMLResource.PROFILES_PATHMAP), uri.appendSegment("profiles").appendSegment(""));
// SysML profiles
uri = URI.createURI("platform:/plugin/org.eclipse.papyrus.sysml");
uriMap.put(URI.createURI(SysmlResource.LIBRARIES_PATHMAP), uri.appendSegment("librairies").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML_PROFILES/"), uri.appendSegment("SysML.profile.uml").appendSegment(""));
uriMap.put(URI.createURI("pathmap://SysML_PROFILES/"), uri.appendSegment("model").appendSegment(""));
Any sort of help is appreciated.
I had an identical problem, but with UML/MARTE rather than SysML.
I bet that port.getAppliedStereotypes() always returns the empty list, no matter what (even if of course, port is stereotyped). I also tried everything you did, unsuccessfully, including double-checking if there was a #generated NOT in the javadoc of the registerPackages method (to it being re-generated each time).
I fixed the issue whit a little workaround. I assume that you (like I did) use as input for the transformation the model.uml file generated by Papyrus. This might actually be the cause of the problem, even though I don't see an alternative. If you open that file with a text editor, you'll find that the <FlowPort> tags are outside the <uml:Model> tag. This means that, for reasons that I still fail to understand, the stereotype() methods cannot "see" the stereotypes and always return null, or empty lists. This is possibly because they fail to match the stereotype base_NamedElement to the xmi:id inside the <uml:Model> tag.
On the other hand, if you define a template which takes as input a FlowPort (rather than a Model) you will be able to get your stereotyped element and all of its properties.
[template public generateElement(aFlowPort: FlowPort)]
[comment #main /]
[comment here you can access to the aFlowPort fields]
[/template]
Among others, you can also access the base_NamedElement property of the stereotype (i.e., the Port that is stereotyped FlowPort in your model), and you can use the qualifiedName property of the base element to map back the stereotype to the Port in your Model. In practice, this means that you have to link the stereotypes to their stereotyped entities by hand.
Clunky and annoying, but still gets the job done until somebody comes with a less "workaroundy" solution.

Get Class of Map in FreeMarker

I want to get a variable's class type in freemarker, used var.class.simpleName;
but if var is a Map, freemarker will process class as a key to find value in var.
it throw exception. how can I do this ? thanks for any suggestion.
First I have to ask why do you need that, because FreeMarker templates aren't supposed to know even if var is Map at all. Maybe your data-model is not what the template needs.
Anyway, for now, I would write a custom TemplateMethodModelEx for this purpose, something that you can use like ${classOf(var)}. Inside the TemplateMethodModelEx implementation you will receive a TemplateModel as the argument value, and then you can check if it's an AdapterTemplateModel, and if so you can get back the original object and get its class. (If it's not a AdapterTemplateModel, then it perhaps isn't even a wrapped Java object, so it doesn't make sense to ask what the class of the original object is.) However, the DefaultObjectWrapper with incompatibleImprovements set to less than 2.3.22 doesn't give AdapterTemplateModel to wrapped Map-s... so in 2.3.21 you will still have to use BeansWrapper, but you can at least set simpleMapWrapper to true.
In 2.3.22 it will be actually possible to write ${var?api.class}... you might use the nightly build. Though it only supposed to solve the problem where you can't access business methods because the primary type of the business class is Map.

Resources