I'm new to Acceleo and I'm trying to figure out some things about the file tags I can use.
The format I see most commonly is something like that:
[file (someElement.anotherElement.concat('SomeText.java'), false, 'UTF-8')]
1st Question: How can I write some text first and then the text from some element? e.g. Create a file named "SomeTextElement1.java". Where Element1 is a property(or something) from an .ecore file)
2nd Question: How can I take values from 2 different elements?
e.g. Create a file named "Element1-Element2.java". Where Element1 and Element2 taken from an .ecore file.
and 3rd Question: How can I put a file statement inside an [if] statement???
e.g.
[if (condition) /]
[file (Element1.concat('.java'),false, 'UTF-8')]
[else if (condition)]
[file (Element1.concat('.java'),false, 'UTF-8')]
[if/]
I get an error saying file tag is not terminated. But i don't want to terminate it inside the if statement because then i would have to write the same code twice... all i want is to change the filename if a condition is true.. is that possible or not?
Thanks in advance.
You generally don't want to have external "if"s for this. The file name itself is an expression, not a simple string, so you can achieve what you're trying to get with the following:
[file (if (condition) then 'somename.java' else 'someothername.java' endif, false, 'UTF-8')]
Note that in this case, the "if" structure you'll be using is the OCL "if", so you have to properly use the "if then else endif" structure. if you want multiple conditions, this will then become
if (condition) then 'somename' else
if (otherCondition) then 'someothername' else 'yetanothername' endif
endif
In order to generate two different file for a same type on a condition, you have multiple options:
You can do as proposed by #Kellindil in the [file ()] tag
You can also use your solution but by ending the [/file] tag in the [if..] like this:
[if (condition)]
[file ('name1', ...)]
...
[/file]
[elseif (condition)]
[file ('name2', ...)]
...
[/file]
[/if]
Finally, you can also use a guard on the template that owns the code:
[template public generate_stuff(p : your_type) ? (condition1)]
[file ('name1' ....)]
...
[/file]
[/template]
[comment Yep, the template name is exactly the same, only the condition change/]
[template public generate_stuff(p: your_type) ? (condition2)]
[file ('name2' ....)]
...
[/file]
[/template]
This later solution is probably the best as you can clearly 'cut' your code and write a dedicated implementation regarding the condition.
(you could also use a solution that mixes the if solutions with multiple templates)
EDIT>
The last solution can produce the same code, no issues about that
[template public generate_stuff(p : your_type) ? (condition1)]
[file ('name1' ....)]
[p.body_generation()/]
[/file]
[/template]
[comment Yep, the template name is exactly the same, only the condition change/]
[template public generate_stuff(p: your_type) ? (condition2)]
[file ('name2' ....)]
[p.body_generation()/]
[/file]
[/template]
[template public body_generation(p: your_type)]
...
[/template]
Acceleo is a really verbose language, trying to put everything on a single statement is often not a great idea for readability.
Related
I'm new to nextflow/groovy/java and i'm running into some difficulty with a simple regular expression task.
I'm trying to alter the labels of some file pairs.
It is my understanding that fromFilePairs returns a data structure of the form:
[
[common_prefix, [file1, file2]],
[common_prefix, [file3, file4]]
]
I further thought that:
The .name method when invoked on a item from this list will give the name, what I have labelled above as common_prefix
The value returned by a closure used with fromFilePairs sets the names of the file pairs.
The value of it in a closure used with fromFilePairs is a single item from the list of file pairs.
however, I have tried many variants on the following without success:
params.fastq = "$baseDir/data/fastqs/*_{1,2}_*.fq.gz"
Channel
.fromFilePairs(params.fastq, checkIfExists:true) {
file ->
// println file.name // returned the common file prefix as I expected
mt = file.name =~ /(common)_(prefix)/
// println mt
// # java.util.regex.Matcher[pattern=(common)_(prefix) region=0,47 lastmatch=]
// match objects appear empty despite testing with regexs I know to work correctly including simple stuff like (.*) to rule out issues with my regex
// println mt.group(0) // #No match found
mt.group(0) // or a composition like mt.group(0) + "-" + mt.group(1)
}
.view()
I've also tried some variant on this using the replaceAll method.
I've consulted documentation for, nextflow, groovy and java and I still can't figure out what I'm missing. I expect it's some stupid syntactic thing or a misunderstanding of the data structure but I'm tired of banging my head against it when it's probably obvious to someone who knows the language better - I'd appreciate anyone who can enlighten me on how this works.
A closure can be provided to the fromfilepairs operator to implement a custom file pair grouping strategy. It takes a file and should return the grouping key. The example in the docs just groups the files by their file extensions:
Channel
.fromFilePairs('/some/data/*', size: -1) { file -> file.extension }
.view { ext, files -> "Files with the extension $ext are $files" }
This isn't necessary if all you want to do is alter the labels of some file pairs. You can use the map operator for this. The fromFilePairs op emits tuples in which the first element is the 'grouping key' of the matching pair and the second element is the 'list of files' (sorted lexicographically):
Channel
.fromFilePairs(params.fastq, checkIfExists:true) \
.map { group_key, files ->
tuple( group_key.replaceAll(/common_prefix/, ""), files )
} \
.view()
First of all I'm very happy with Rythm! Excellent work for something that is free.
Recently I have begun internationalization of my templates with Rythm and some things seem more cumbersome than needed. I'm wondering if there is any better way of doing what I'm trying to do.
1. Chain tag onto #i18n()
This does not work:
#i18n("about.text").nl2br()
#i18n("about.text").mytransformer()
The workaround for this is:
#assign(newvar){#i18n("about.text")}
#newvar.nl2br()
This works but is is not pretty.
2. #i18n() escaped in javascript
If I have a section
<script>
var s = '#description';
</script>
then Rythm will nicely escape any ' or " in that description. However when I use:
<script>
var s = '#i18n("description")';
</script>
escaping is not done. I also tried doing:
var s = '#i18n("description").escape("js")';
and
var s = '#escapeJS(){#i18n("description")}';
but both do not work (see above). What does work again is using
#assign(desc){#i18n("description")}
...
var s = '#desc';
3. Use of tag inside #i18n() as argument
Sometimes I need a link inside a translated string like so:
about.text=See my profile here {1}
I would like to use this in the template as follows:
#i18n("about.txt",#genlink("person",person.getId()),person)
Note: person here is an template argument of type Person. #genlink is a convenience template(or tag) to generate a link using a lookup.
The solution I currently use is:
#assign(lnk){<a href='#genlink("person",person.getId())'>#person</a>}
#i18n("about.txt",lnk)
Note that the language resource has changed to: about.text=See my profile here {0}
This is probably the better way to write the resource string anyway, but it would be nice if I could get rid of the #assign() somehow and write this:
#i18n("about.text","<a href='#genlink("person",person.getId())'>#person</a>")
Edit:
I tried your suggestions and was only partially successful.
Chain tag onto #i18n()
doing #("about.text".i18n()) works whereas doing #("about.text".i18n().nl2br()) doesn't work and complains about a missing parameter for #i18n(). If I add the missing parameter like so: #("about.txt".i18n("").nl2br()) it complains that nl2br() is not defined for String
What did work for me was: #s().i18n("about.txt").nl2br()
Even weirder so, when I run your fiddle on Chrome it works perfectly. When I run it on Mac/Safari I get the same error as I just described: see screenshot:
#i18n() escaped in javascript
Works as you explained!
Use of tag inside #i18n() as argument
understood. The current solution with #assign() is fine for one-offs. Using #def() is a nicer generic solution.
Chain tag onto #i18n()
Try to use .i18n() transformer instead of #i18n() tag.
Say change #i18n("about.text").nl2br() to #("about.text".i18n().nl2br())
Note you need the () pair to enclose the entire expression if you feed into a string literal like "about.text", however if you do the same thing for a variable then that () can be opt out, e.g #foo.i18n().nl2br()
#i18n() escaped in javascript
Again, use .i18n() transformer
Use of tag inside #i18n() as argument
Tag processing is very hard to put into another tag or transformer. In your case I recommend you to use inline tag
The demonstration of all above three points could be found at http://fiddle.rythmengine.org/#/editor/0c426d5332334db3870b6bd8c0806e66
I use doxygen to generate xml which then i transform to a custom documentation.
Is there a possibility that doxygen includes the annotation of a field / class / function.
The annotation are ignored in both java and c#.
ex:
class User
{
[Required]
string UserName {get;set;}
}
the "Required" annotation is not parsed/displayed in doxygen.
What I would like to have in the xml / html output of doxygen is all the annotated Annotations of a property / field / class (in the ex. "[Required]").
EXTRACT_ALL=YES is useless in this case. Look at this answer, I think it is good idea:
Doxygen and add a value of an attribute to the output documentation
So you have to create filter (for example in phyton) which will be used by Doxygen to convert annotation to comment. Don’t forget to inform Doxygen about your filter: INPUT_FILTER = doxygenFilter.py
I have the same problem so I modified that example in this way:
#!/usr/bin/env python
import sys
import re
if (len(sys.argv) < 2):
print "No input file"
else:
f = open(sys.argv[1])
line = f.readline()
while line:
re1 = re.compile("\s*\[(.*)]\s*")
re1.search(line)
sys.stdout.write(re1.sub(r"/// <para>Annotation: [\1]</para>\n", line))
#sys.stdout.write(line)
line = f.readline()
f.close()
So code like
[AnyAnnotation()]
Will be converted to:
/// <param> Annotation [AnyAnnotation()] </param>`
So I got very nice result. Tag <param> is to avoid Doxygen put this annotation description to main description. Instead it will put it to remarks section.
I'm not sure what you're asking but I will say a few things that might help you.
Doxygen must be configured to produce documentation for code elements that have no Doxygen comments. In other words, you can tell Doxygen to produce documentation for all functions, variables, macros, etc even if they aren't documented in the code. Set EXTRACT_ALL=YES in your config file.
If you run DoxyWizard you will get a better feel for all of the available options and the effect of each option. DoxyWizard is the GUI front end to Doxygen.
And by the way, bravo for documenting your code!
I have an application that has two classes called "Service" in two different places in the package structure. The logging outputs the file and line number like this, eg: (Service.java:102)
This becomes a clickable link in the console output in Eclipse. Normally, these links are great because you can find exactly of where the output was printed from with a single click.
But now I have two Service.java files, doing two entirely different things, and they're in a different place in the package structure. I can't rename either of them.
When I click on the link, it takes me to the wrong java file, even when the correct java file is open in the editor.
I've searched around, but I can't find the answer. Is there a way to tell Eclipse which java file to consider first? Or a way to tell which package to look in first? Something, anything, to make these clickable links useful again?
I guess your logger is configured like this to ouput a log like that (Service.java:102) :
(%F:%L)
%F : Used to output the file name where the logging request was issued.
%L : Used to output the line number from where the logging request was issued.
Try to used %l instead
%l : Used to output location information of the caller which generated the logging event.
EDIT
this solution does not seem to work well, it prints
com.x.y.z.MyClass.myMethod(MyClass.java:36)
=> the link is only on the classname, same issue.
But using the following pattern will work
(%C.java:%L)
It will print a full link like this :
(com.x.y.z.MyClass.java:36)
i know three ways how to print a clickable class link in the console output.
First way:
Just print the class name inside the parentheses: System.out.println("(Service.java:42)");
This is simple method and will work if you are not using ambiguous class names. Since Eclipse console does not have informations required to decide which file should be opened, i guess it will open the first occurence.
Second way:
In your case. I would do it by using StackTraceElement to print the class name.
That way:
StackTraceElement element = new StackTraceElement(
"Service", // Class name
"myFunnyMethodName", // Method name
Service.class.getName()+".java", // Path to File
2); // line number
System.out.println(element);
Third way:
If you don't want to create StackTraceElement you can get it from you current thread.
Example:
System.out.println(Thread.currentThread().getStackTrace()[1]);
EDIT:
The other option is to try the Grep Console Plugin for Eclipse. You can define your own Expressions with Link, Color, Popup etc...
well... i have a file containing tintin-script. Now i already managed to grab all actions and substitutions from it to show them properly ordered on a website using Ruby, which helps me to keep an overview.
Example TINTIN-script
#substitution {You tell {([a-zA-Z,\-\ ]*)}, %*$}
{<279>[<269> $sysdate[1]<279>, <269>$systime<279> |<219> Tell <279>] <269>to <219>%2<279> : <219>%3}
{4}
#substitution {{([a-zA-Z,\-\ ]*)} tells you, %*$}
{<279>[<269> $sysdate[1]<279>, <269>$systime<279> |<119> Tell <279>] <269>from <119>%2<279> : <119>%3}
{2}
#action {Your muscles suddenly relax, and your nimbleness is gone.}
{
#if {$sw_keepaon}
{
aon;
};
} {5}
#action {xxxxx}
{
#if {$sw_keepfamiliar}
{
familiar $familiar;
};
} {5}
To grab them in my Ruby-App i read my script-file into a varibable 'input' and then use the following pattern to scan the 'input'
pattern = /(?<braces>{([^{}]|\g<braces>)*}){0}^#(?<type>action|substitution)\s*(?<b1>\g<braces>)\s*(?<b2>\g<braces>)\s*(?<b3>\g<braces>)/im
input = ""
File.open("/home/igambin/lmud/lmud.tt") { |file| input = file.read }
input.scan(pattern) { |prio, type, pattern, code|
## here i usually create objects, but for simplicity only output now
puts "Type : #{type}"
puts "Pattern : #{pattern}"
puts "Priority: #{prio}"
puts "Code :\n#{code}"
puts
}
Now my idea was to use the netbeans platform to write a module to not only keep an overview but also to assist editing the tintin script file. So opening the file in an Editor-Window I still need to parse the tintin-file and have all 'actions' and 'substitutions' from the file grabbed and displayed in an eTable, in wich I could dbl-click on one item to open a modification-window.
I've setup the module and got everything ready so far, i just can't figure out how to translate the ruby-regex pattern i've written to a working java-regex-pattern. It seems named-group-capturing and especially the recursive application of these groups is not supported in Java. Without that I seem to be unable to find a working solution...
Here's the ruby pattern again...
pattern = /(?<braces>{([^{}]|\g<braces>)*}){0}^#(?<type>action|substitution)\s*(?<b1>\g<braces>)\s*(?<b2>\g<braces>)\s*(?<b3>\g<braces>)/im
Can anyone help me to create a java pattern that matches the same?
Many thanks in advance for tips/hints/ideas and especially for solutions or (close-to-solution comments)!
Your text format seems pretty simple; it's possible you don't really need recursive matching. This Java-compatible regex matches your sample data correctly, as far as I can tell:
(?s)#(substitution|action)\s*\{(.*?)\}\s*\{(.*?)\}\s*\{(\d+)\}
Would that work for you? If you run Java 7, you can even name the groups. ;)
Can anyone help me to create a java pattern that matches the same?
No, no one can: Java's regex engine does not support recursive patterns (as Ruby 1.9 does).