How does this work? Groovy Map creation with nested closures. - groovy

I'm rather new to Groovy, and recently created a canned message using a Map for testing. I created it using closures (not fully understanding, that's what I did, and changed it to the standard Map notation). Now I want to understand why the closure notation worked.
So the following two Maps get created properly. My question is how is Groovy interpreting the nested closures into a map?
Map notation:
Map m = [
person : [
first : "Flo",
middle : "Over",
last : "Stack"
],
address : [
street1 : "123 Any Street",
street2 : "2nd Floor",
city : "Anytown",
state : "YR",
zip : "99999"
]
]
Closure Notation:
Map m = {
person {
first "Flo"
middle "Over"
last "Stack"
}
address {
street1 "123 Any Street"
street2 "2nd Floor"
city "Anytown"
state "YR"
zip "99999"
}
}

Groovy has a special concept for creating tree structures called Builder. You can find more infos here: http://groovy.codehaus.org/Builders

Related

Lowercasing complex object field names in azure data factory data flow

I'm trying to lowercase the field names in a row entry in azure data flow. Inside a complex object I've got something like
{
"field": "sample",
"functions": [
{
"Name": "asdf",
"Value": "sdfsd"
},
{
"Name": "dfs",
"Value": "zxcv"
}
]
}
and basically what I want is for "Name" and "Value to be "name" and "value". However can't seem to use any expressions that will work for the nested fields of a complex object in the expression builder.
I've tried using a something like a select with a rule-based mapping that is the rule being 1 == 1 and lower($$), but with $$ it seems to only work for root columns of the complex object and not the nested fields inside.
As suggested by #Mark Kromer MSFT, for changing case of columns inside complex type select the functions in the Hierarchy level.
Please check the below for your reference:
Here, I have used both.
You can see the difference in results.

How to know how much of the same structure i have to parse

I am trying to parse this using ANTLR4 :
FSM
name type String
state type State
Relation
name type String
Mathieu
name type String
Someone helped me, corrected my grammar and i got this thanks to him
grammar Generator;
parse
: classToGenerate+ EOF;
classToGenerate
: name=Name attributes+;
attributes
: attribute=Name 'type' type=Name;
Name : [a-zA-Z]+;
Spaces : [ \t\r\n] -> skip;
I am using the parser generated by ANTLR4 this way :
GeneratorLexer l = new GeneratorLexer(new ANTLRInputStream(GeneratorFactory.class.getResourceAsStream("/example.generator")));
GeneratorParser p = new GeneratorParser(new CommonTokenStream(l));
p.addParseListener(new GeneratorBaseListener() {
#Override public void exitClassToGenerate(GeneratorParser.ClassToGenerateContext ctx) {
System.out.println(ctx.name.getText());
}
#Override
public void exitAttributes(GeneratorParser.AttributesContext ctx) {
System.out.println(ctx.type.getText());
System.out.println(ctx.attribute.getText());
}
});
Here is the result after executing
String
name
State
state
FSM
Where is the rest ?
It didn't print Relation name String // Mathieu name String
Any idea ?
EDIT : Okay it seems i was able to print the rest of the files but i've still have something to figure out.
When i do :
p.classToGenerate();
It parses the first structure which results in the print i had.
If i want to find another structure i need to do another
p.classToGenerate();
The thing is, how should i know how much structure i have to parse?
Imagine i have 5 or 20 same structures, how can i know it ?
Thanks !
In your grammar you've called your main rule parse. The rule classToGenerate only matches a single class. So in order to match all classes in the file, you should call p.parse();, not p.classToGenerate();.

Most elegant way to get two properties at the same time

Suppose you have hierarchical data and want to obtain the merged value of separate properties, what is the most elegant, or groovy, way to do so?
The following example holds information about failed and skipped tests. Of course, it does make sense, that these values are separated - but for the use case of retrieving a list of all tests, that did not run successfully, I came across two possible solutions, which both of them did not satisfy me.
def junitResultList = [
[
name: "Testsuite A",
children: [
failedTests: ["Test 1", "Test 2"],
skippedTests: []
]
],
[
name: "Testsuite B",
children: [
failedTests: ["CursorTest"],
skippedTests: ["ClickTest", "DragNDropTest"]
]
]
]
To be more specific, I want the value to be ["Test 1", "Test 2", "CursorTest", "ClickTest", "DragNDropTest"].
The first approach was simply to perform an addition of the spread test lists:
(junitResultList*.children*.failedTests +
junitResultList*.children*.skippedTests).flatten()
While this works, it appeared to me that specifying the path to these properties twice seems not to be the most groovy way, so I came up with this horrible but somehow appealing disasterpiece:
(junitResultList*.children*.findAll {
['skippedTests', 'failedTests'].contains(it.key)
})*.values().flatten()
You can simplify your initial expression to something like this:
junitResultList.children.collect { it.failedTests + it.skippedTests }.flatten()
or
junitResultList.children.collect { [it.failedTests, it.skippedTests] }.flatten()
You can just do as below:
//Define the keys to find
def requiredKeys = ['failedTests', 'skippedTests']
println requiredKeys.collect{ junitResultList.children."$it"}.flatten()
You can quickly try the same online demo
You can get the subMap()s and then the values() on that:
junitResultList*.children*.subMap(["failedTests","skippedTests"])*.values().flatten()

OrientDB: containsall operator

I have collection of documents. Document have a field which value is an array of maps (for example: map with one field name). Structure is like that:
{
arrayfield: [
{
name: "value1",
},
{
name: "value2",
}
]
}
I want to fetch documents whose arrayfieds all maps contain values from specified array. Documentation says that I can use containsall operator. I use it in this way:
select from SomeCollection where arrayfiled containsall (name in ['value1','value2'])
But this construction always returns empty result. Where I do mistake? Thanks.
PS: If my question not understandable, I can post more detailed example of the collection and and a result which I want to receive.
Found a solution to solve my issue without containsAll:
select from SomeCollection where not (arrayfield contains (fname not in ["value1", "value2"]))
Try the following query
select from SomeCollection where arrayfiled.name contains "value1" and arrayfiled.name contains "value2"

Elastic Search input analysis

Can Elastic Search split input string into categorized words? i.e. if the input is
4star wi-fi 99$
and we are searching hotels with ES, is it possible to analyze/tokenize this string as
4star - hotel level, wi-fi - hotel amenities, 99$ - price?
yep, it's a noob question :)
Yes and no.
By default, query_string searches will work against the automatically created _all field. The contents of the _all field come from literally and naively combining all fields into a single analyzed string.
As such, if you have a "4star" rating, a "wi-fi" amenity, and a "99$" price, then all of those values would be inside of the _all field and you should get relevant hits against it. For example:
{
"level" : "4star",
"amenity" : ["pool", "wi-fi"],
"price" : 99.99
}
The problem is that you will not--without client-side effort--know what field(s) matched when searching against _all. It won't tell you the breakdown of where each value came from, rather it will simply report a score that determines the overall relevance.
If you have some way of knowing which field each term (or terms) is meant to search against, then you can easily do this yourself (quotes aren't required, but they're good to have to avoid mistakes with spaces). This would be the input that you might provide to the query_string query linked above:
level:"4star" amenity:"wi-fi" price:(* TO 100)
You could further complicate this by using a spelled out query:
{
"query" : {
"bool" : {
"must" : [
{ "match" : { "level" : "4star" } },
{ "match" : { "amentiy" : "wi-fi" } },
{
"range" : {
"price" : {
"lt" : 100
}
}
}
]
}
}
}
Naturally the last two requests would require advanced knowledge about what each search term referenced. You could certainly use the $ in "99$" as a tipoff for price, but not for the others. Chances are you wouldn't have them typing in 4 stars I hope, rather having some checkboxes or other form-based selections, so this should be quite realistic.
Technically, you could create a custom analyzer that recognized each term based on their position, but that's not really a good or useful idea.

Resources