From the following code snippet I tried, This runs into an infinite loop regardless of the fact that I mark the initial ds as immutable, and looping it with an each. What am I missing? -
domObject.Whatever.'**'.findAll { it.name() == 'Node' }.asImmutable().each { node -> //Bazinga
nodes.split(/(;|,|\n|&)/).eachWithIndex { nodeName, index ->
def newNode = new Node(null, node.name(), node.attributes(), node.value())
newNode.#name = nodeName
//I'm simply adding new nodes here
node.parent().children().add(0, newNode) //bazinga
}
}
Ive used an xmlparser for the domObject.
Related
I'm trying to do something rather simple. I would like to wrap the whole method code into an additional closure block that would measure the execution time. Right now I'm getting a really not helpful error message:
Error:Groovyc: NPE while processing Test.groovy
Annotation:
#Retention(RetentionPolicy.SOURCE)
#Target([ElementType.METHOD])
#GroovyASTTransformationClass(["WithTimingASTTransformation"])
public #interface WithTiming {
}
My wrapping closure:
class Benchmark {
static def measureTime(Closure cl) {
def start = System.currentTimeMillis()
def result = cl()
def time = System.currentTimeMillis() - start
println "it took $time"
result
}
}
My Transformation:
#GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
class WithTimingASTTransformation implements ASTTransformation {
#Override
void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
MethodNode method = astNodes[1]
method.code = wrap(method)
}
private Statement wrap(MethodNode method) {
def newBlock = new BlockStatement()
newBlock.addStatement(
new ExpressionStatement(
new StaticMethodCallExpression(
new ClassNode(Benchmark),
'measureTime',
new ArgumentListExpression(
new ClosureExpression(new Parameter[0], method.code)
))))
newBlock
}
}
I'm really stuck here and don't know how can I debug the problem.
There is an answer on a similar topic (wrapping whole method body into a try/catch block here). This works fine but my case is slightly different.
In my case similar NPE was coming from:
java.lang.NullPointerException
at org.codehaus.groovy.classgen.asm.ClosureWriter.createClosureClass(ClosureWriter.java:194)
at org.codehaus.groovy.classgen.asm.ClosureWriter.getOrAddClosureClass(ClosureWriter.java:159)
at org.codehaus.groovy.classgen.asm.ClosureWriter.writeClosure(ClosureWriter.java:90)
at org.codehaus.groovy.classgen.AsmClassGenerator.visitClosureExpression(AsmClassGenerator.java:673)
Whereas:
if (parameters == null || expression.getVariableScope() == null) {
parameters = Parameter.EMPTY_ARRAY;
} else if (parameters.length == 0) {
// let's create a default 'it' parameter
Parameter it = new Parameter(ClassHelper.OBJECT_TYPE, "it", ConstantExpression.NULL);
parameters = new Parameter[]{it};
Variable ref = expression.getVariableScope().getDeclaredVariable("it");
if (ref != null) it.setClosureSharedVariable(ref.isClosureSharedVariable());
}
and line 194 (as of https://github.com/groovy/groovy-core/commit/a52d0d3c5dd1cbb342992d36235171718a563c8b) is:
Variable ref = expression.getVariableScope().getDeclaredVariable("it");
Thus you need to define a VariableScope for your ClosureExpression. I had to add tracing into org.codehaus.groovy.ast.ClosureWriter to find this, because there is an issue with exception display on stage of Class Generation - both in IntelliJ Idea and in Groovy Console - it does not show proper lines of code.
Furthermore, I think that either ClosureWriter or ClosureExpression constructor can be fixed to work aligned by default - without this NPE. I will possibly submit an issue to Groovy Jira for this.
Now I am able to inject closure expression in my code. But struggling to call this closure.
Getting:
groovy.lang.MissingMethodException: No signature of method: com.a9ae0b01f0ffc.VSMSGEN.implementation.T_visa_recon_generator$_convert_vts_log_to_ctf_closure2.call() is applicable for argument types: () values: []
Long story short, after some iterations my method-wrapping AST looks like this:
BlockStatement bs = new BlockStatement()
ClosureExpression closureExp = new ClosureExpression( methodNode.parameters, methodNode.code )
closureExp.variableScope = new VariableScope() // <- this does the trick!
bs.addStatement new ExpressionStatement( new StaticMethodCallExpression( new ClassNode( TransactionUtil ), 'wrap', new ArgumentListExpression( closureExp ) ) )
methodNode.code = bs
The line closureExp.variableScope = new VariableScope() avoids the NPE in ClosureWriter.java:194 and the whole thing runs like a charm!
Hope it helps someone...
I have the following problem definition:
Design a lock-free simple linked list with the following operations:
Add(item): add the node to the beginning (head) of the list
Remove(item): remove the given item from the list
Below is shown the code implemented so far:
public class List<T>
{
private readonly T _sentinel;
private readonly Node<T> _head;
public List()
{
_head = new Node<T>();
_sentinel = default(T);
}
public List(T item)
{
_head = new Node<T>(item);
_sentinel = item;
}
public void Add(T item)
{
Node<T> node = new Node<T>(item);
do
{
node.Next = _head.Next;
}
while (!Atomic.CAS(ref _head.Next, node.Next, node));
}
public void Remove(Node<T> item)
{
Node<T> next;
Node<T> oldItem = item;
if (item.Value.Equals(_sentinel))
return;
item.Value = _sentinel;
do
{
next = item.Next;
if (next == null)
{
Atomic.CAS(ref item.Next, null, null);
return;
}
} while (!Atomic.CAS(ref item.Next, next, next.Next));
item.Value = next.Value;
}
}
The head is actually a dummy (sentinel) node kept for ease of use. The practical head is actually _head.Next.
The problem is on the remove operation when trying to remove the last element of the list:
On the remove part there are two cases:
The node has a following not-null next pointer: then do the CAS operation and steal the value data of the next item removing actually the next item
The problematic case is when the element to remove is the last one in the list:
Do Atomically: If (item == oldItem and item.Next == null) then item = null where oldItem is a pointer to the item to remove;
So I want to do is in the case of removing C node:
if(C==old-C-reference and C.Next == null) then C = null => all atomically
The problem is that I have a CAS only on a single object.
How can I solve this problem atomically? Or is there a better way of doing this remove operation that I'm missing out here?
when removing B we do a trick by copying C's contents to B and removing C: B.Next = C.Next (in the loop) and B.Value = C.Value after the move succeeded
So you need to atomically modify two memory locations. CAS in .NET does not support that. You can, however, wrap those two values in another object that can be swapped out atomically:
class ValuePlusNext<T> {
T Value;
Node<T> Next;
}
class Node<T> {
ValuePlusNext<T> Value;
}
Now you can write to both values in one atomic operation. CAS(ref Value, new ValuePlusNext<T>(next.Value, next.Value.Next). Something like that.
It is strange that ValuePlusNext has the same structure that your old Node class had. In a sense you are now managing two physical linked list node for each logical one.
while (true) {
var old = item.Value;
var new = new ValuePlusNext(...);
if (CAS(ref Value, old, new)) break;
}
I want to store objects in a map (called result). The objects are created or updated from SQL rows.
For each row I read I access the map as follows:
def result = [:]
sql.eachRow('SELECT something') { row->
{
// check if the Entry is already existing
def theEntry = result[row.KEY]
if (theEntry == null) {
// create the entry
theEntry = new Entry(row.VALUE1, row.VALUE2)
// put the entry in the result map
result[row.KEY] = theEntry
}
// use the Entry (create or update the next hierarchie elements)
}
I want to minimize the code for checking and updating the map. How can this be done?
I know the function map.get(key, defaultValue), but I will not use it, because it is to expensive to create an instance on each iteration even if I don't need it.
What I would like to have is a get function with a closure for providing the default value. In this case I would have lazy evaluation.
Update
The solution dmahapatro provided is exactly what I want. Following an example of the usage.
// simulate the result from the select
def select = [[a:1, b:2, c:3], [a:1, b:5, c:6], [a:2, b:2, c:4], [a:2, b:3, c:5]]
// a sample class for building an object hierarchie
class Master {
int a
List<Detail> subs = []
String toString() { "Master(a:$a, subs:$subs)" }
}
// a sample class for building an object hierarchie
class Detail {
int b
int c
String toString() { "Detail(b:$b, c:$c)" }
}
// the goal is to build a tree from the SQL result with Master and Detail entries
// and store it in this map
def result = [:]
// iterate over the select, row is visible inside the closure
select.each { row ->
// provide a wrapper with a default value in a closure and get the key
// if it is not available then the closure is executed to create the object
// and put it in the result map -> much compacter than in my question
def theResult = result.withDefault {
new Master(a: row.a)
}.get(row.a)
// process the further columns
theResult.subs.add new Detail(b: row.b, c: row.c )
}
// result should be [
// 1:Master(a:1, subs:[Detail(b:2, c:3), Detail(b:5, c:6)]),
// 2:Master(a:2, subs:[Detail(b:2, c:4), Detail(b:3, c:5)])]
println result
What I learned from this sample:
withDefault returns a wrapper, so for manipulating the map use the wrapper and not the original map
row variable is visible in the closure!
create the wrapper for the map in each iteration again, since row var changed
You asked for it, Groovy has it for you. :)
def map = [:]
def decoratedMap = map.withDefault{
new Entry()
}
It works the same way you would expect it to work lazily. Have a look at withDefault API for a detailed explanation.
Is there already a way in groovy to collect objects following a property while not null ?
Object.metaClass {
collectWhileNotNull = { Closure follow ->
def result = []
def previous = null
for (def current = delegate; !current.is(previous) && (current != null); current = follow(current)){
result << current
previous = current
}
return result
}
}
It is useful for recursive data structure.
An example of usage for a groovy.util.Node :
Closure getAncestors = { Node n -> n.collectWhileNotNull{ it.parent() }.tail().reverse() }
You can use a Generator class (this is also the name of the necessary pattern) from cookbook.
It would seem that GPathResult returns a list of nodes which is the same for each iteration. How can I insert nodes from one iteration and find them in the next, as shown in the example below?
def messageNodes = [] as HashSet
def inputRoot = new XmlSlurper().parse(xmlFile)
inputRoot.testsuite.list().each { suiteNode ->
suiteNode.children().list().each { caseNode ->
caseNode.children().list().each { messageNode ->
messageNodes << messageNode
}
}
}
inputRoot.testsuite.list().each { suiteNode ->
suiteNode.children().list().each { caseNode ->
caseNode.children().list().each { messageNode ->
assert messageNodes.contains(message)
}
}
}
That code isn't inserting nodes... But as it stands (trying to find nodes are the same between scans), it won't work either due to the way XmlSlurper works...
When you call children() on a GPathResult, you end up with an iterator that returns new instances of NodeChild. Because these are new instances, they cannot be compared to the last time you saw them (as their hashcode will be different)
If you change your code to use XmlParser like so:
def messageNodes = []
def inputRoot = new XmlParser().parse(xmlFile)
inputRoot.testsuite.'*'.'*'.each { messageNode ->
messageNodes << messageNode
}
inputRoot.testsuite.'*'.'*'.each { messageNode ->
println messageNode.hashCode()
assert messageNodes.contains(messageNode)
}
I believe it works as you'd expect (I had to guess at your xml format though, as you didn't show us what it was in the question)
As an addition, you can change the lines
inputRoot.testsuite.'*'.'*'.each { messageNode ->
messageNodes << messageNode
}
to
messageNodes.addAll( inputRoot.testsuite.'*'.'*' )
for the same functionality...
It should also be noted that XmlSlurper doesn't store internal state in a navigable way, so if you add nodes, you cannot find them unless you write the xml out and read it back in. If this is the sort of thing you're aiming for, XmlParser is probably also the better route