Groovy++ error when adding #Typed - groovy

I was interested in testing performance gain for groovy++ over plain groovy.
I found the script to test
class Chain
{
def size
def first
def init(siz)
{
def last
size = siz
for(def i = 0 ; i < siz ; i++)
{
def current = new Person()
current.count = i
if (i == 0) first = current
if (last != null)
{
last.next = current
}
current.prev = last
last = current
}
first.prev = last
last.next = first
}
def kill(nth)
{
def current = first
def shout = 1
while(current.next != current)
{
shout = current.shout(shout,nth)
current = current.next
}
first = current
}
}
class Person
{
def count
def prev
def next
def shout(shout,deadif)
{
if (shout < deadif)
{
return (shout + 1)
}
prev.next = next
next.prev = prev
return 1
}
}
def main(args)
{
println "Starting"
def ITER = 100000
def start = System.nanoTime()
for(def i = 0 ; i < ITER ; i++)
{
def chain = new Chain()
chain.init(40)
chain.kill(3)
}
def end = System.nanoTime()
println "Total time = " + ((end - start)/(ITER * 1000)) + " microseconds"
}
It works. But if I try to add
#Typed
before first class name and run I'm getting error:
#groovy groovy.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/home/melco/test/groovy.groovy: 18: Cannot find property next of class Object
# line 18, column 22.
last.next = current
^
1 error
# groovy -version
Groovy Version: 1.7.5 JVM: 1.6.0_18
Any ideas why?

To enjoy statically typed compilation you need to provide at least some amount of type information.
Normally it is enough to define types of properties (next, prev in your case) and types of method parameters.

All the variables you declare are of type java.lang.Object (Or grovy.lang.Object in this case). So they don't have the methods "next" etc.
Try to use Person current = new Person() and Cain current = first etc.

Related

how to write a .csv file in "groovy" with multiple lines and no header is there(Expected to avoid append) in it?

class csv {
static void main(String[] args) {
def itemName
def itemPrice
def itemQty
def list3 = []
BufferedReader br = new BufferedReader(new InputStreamReader(System.in))
File file = new File("/Users/m_328522/Desktop/" + "invoicedetails.csv")
file.createNewFile()
println("Enter the number of items:")
def noOfItems = br.readLine().toInteger()
for (int i = 0; i < noOfItems; i++) {
println("Enter item " + (i + 1) + " details:")
itemName = br.readLine()
list3 << itemName
itemPrice = br.readLine().toDouble()
list3 << itemPrice
itemQty = br.readLine().toInteger()
list3 << itemQty
//println(list3)
def asString = list3.join(",")
file.append(asString +"\n")
//println(asString)
list3.remove(2)
list3.remove(1)
list3.remove(0)
//println(list3)
}
println("invoicedetails.csv")
println(file.text)
}
}
The following code:
def home = System.properties['user.home']
def file = new File("${home}/Desktop/invoicedetails.csv")
if (!file.isFile() && !file.createNewFile()) {
println "Failed to create file: $file"
return
}
int lineCount = prompt("Enter the number of items") as Integer
file.withPrintWriter { pw ->
lineCount.times { i ->
readRecord(i, pw)
}
}
def readRecord(i, pw) {
println "- enter details for item ${i+1} -"
def line = []
line << prompt("name")
line << prompt("price").toDouble()
line << prompt("quantity").toInteger()
pw.println(line.join(','))
}
def prompt(question) {
System.console().readLine("${question} > ")
}
should solve your problem. Below a sample run:
~>  groovy solution.groovy
Enter the number of items > 2
- enter details for item 1 -
name > Jet Pack
price > 9999.99
quantity > 2
- enter details for item 2 -
name > Plane Desnaking Kit
price > 24999.99
quantity > 1
~> cat ~/Desktop/invoicedetails.csv
Jet Pack,9999.99,2
Plane Desnaking Kit,24999.99,1
~>
It should be noted that if anybody other than yourself is going to run this, you should probably include error handling for things like people entering one when asked for quantity etc. This could be accomplished with something like the following (rest of the code remains the same):
def readRecord(i, pw) {
println "- enter details for item ${i+1} -"
def line = []
line << prompt("name")
line << prompt("price", Double)
line << prompt("quantity", Integer)
pw.println(line.join(','))
}
def prompt(question, clazz=String) {
boolean valid = false
def answer
while (!valid) {
try {
answer = System.console().readLine("${question} > ").asType(clazz)
valid = true
} catch (Exception e) {
println "-> invalid answer format for type ${clazz.simpleName}"
println "-> please try again!"
}
}
answer
}
with a sample run:
~> groovy solution.groovy
Enter the number of items > 1
- enter details for item 1 -
name > Jet Pack
price > a million bucks
-> invalid answer format for type Double
-> please try again!
price > 1234.23343434
quantity > a lot
-> invalid answer format for type Integer
-> please try again!
quantity > 10
~>

Cannot find matching method - JIRA/Groovy

I am trying to calculate the amount of time an issue spent in a status. But experiencing some errors. The script below goes into the scripted field. Below is my script:
import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = [0L]
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item ->
def timeDiff = System.currentTimeMillis() - item.created.getTime()
if (item.fromString == currentStatusName) {
rt = -timeDiff
}
if (item.toString == currentStatusName){
rt = timeDiff
}
}
return (Math.round(rt.sum() / 3600000)) as Double
The error is in the last line of the script(the return statement).
I'm not sure what I'm doing wrong.
The errors I get are:
Static type checking - Cannot find matching java.lang.Object#sum() and Cannot find matching method java.lang.Match#round(java.lang.Object)
You are assigning rt to a Long in your two if blocks. (Just a long, not an array of longs.) Consequently there is no .sum() method available.
You could use
rt << -timeDiff
// or
rt << timeDiff
to add your timeDiffs to the array rather than redefining it.
You also could just initialize rt as 0 and then use rt += timeDiff or rt -= timeDiff if you prefer. It doesn't look like you really need that to exist as an array at all.
Example that may work for you:
import com.atlassian.jira.component.ComponentAccessor
def changeHistoryManager = ComponentAccessor.changeHistoryManager
def currentStatusName = issue?.status?.name
def rt = 0L
changeHistoryManager.getChangeItemsForField (issue, "status").reverse().each {item ->
def timeDiff = System.currentTimeMillis() - item.created.getTime()
if (item.fromString == currentStatusName) {
rt -= timeDiff
}
if (item.toString == currentStatusName){
rt += timeDiff
}
}
return rt / 3600000
// this could still be Math.round(rt/3600000) as Double if you need that; not sure what you're trying to do with the actual result

storing standard output into list groovy

I cannot manage to store the standard output from a shell command into a list using the following code. It seems to store each character as a list element instead of the entire string produced on each line.
def implementedBranchName = []
def getImplementedBranches() {
def cmd = "/usr/bin/tool search status Pending"
Process process = cmd.execute()
def output= process .in.text;
implementedBranchName = output.each{ println it }
def size = implementedBranchName.size()
for ( int i = 0; i < size; i++) {
println(implementedBranchName[i])
}
}
Current Output:
F
O
O
B
A
R
Desired Output:
FOO
BAR
You could just change
implementedBranchName = output.each{ println it }
To:
implementedBranchName = output.split()
There is also "eachLine" in Groovy.
def getImplementedBranches() {
def cmd = "/usr/bin/tool search status Pending"
Process process = cmd.execute()
process.in.eachLine { line ->
println(line)
}
}

How I can find the contents of inner nesting?

Lets say I have a string like this :
string = [+++[>>[--]]]abced
Now I want a someway to return a list that has: [[--],[>>],[+++]]. That is the contents of the deepest [ nesting followed by other nesting. I came up with this solution like this :
def string = "[+++[>>[--]]]"
loop = []
temp = []
string.each {
bool = false
if(it == "["){
temp = []
bool = true
}
else if( it != "]")
temp << it
if(bool)
loop << temp
}
println loop.reverse()
But this indeed takes the abced string after the last ] and put into the result!. But what I want is only [[--],[>>],[+++]]
Are there any groovy way of solving this?
You can use this, if you wouldn't mind using recursion
def sub(s , list){
if(!s.contains('[') && !s.contains('['))
return list
def clipped = s.substring(s.lastIndexOf('[')+1, s.indexOf(']'))
list.add(clipped)
s = s - "[$clipped]"
sub(s , list)
}
Calling
sub('''[+++[>>[--]]]abced''' , [])
returns a list of all subportions enclosed between braces.
['--', '>>', '+++']
If your brackets are symmetrical, you could just introduce a counter variable that holds the depth of the bracket nesting. Only depth levels above 0 are allowed in the output:
def string = "[+++[>>[--]]]abc"
loop = []
temp = []
depth = 0;
string.each {
bool = false
if(it == "["){
temp = []
bool = true
depth++;
}
else if (it == "]"){
depth--;
}
else if (depth > 0){
temp << it
}
if(bool){
loop << temp
}
}
println loop.reverse()
class Main {
private static final def pattern = ~/([^\[]*)\[(.+?)\][^\]]*/
static void main(String[] args) {
def string = "[+++[>>[--]]]abced"
def result = match(string)
println result
}
static def match(String val) {
def matcher = pattern.matcher(val);
if (matcher.matches()) {
return matcher.group(1) ? match(matcher.group(2)) + matcher.group(1) : match(matcher.group(2))
}
[val]
}
}
System.out
[--, >>, +++]
The capturing of the first group in the regex pattern could probably be improved. Right now the first group is any character that is not [ and if there are nothing in front of the first [ then the first group will contain an empty string.

Groovy: indexes of substrings?

How do I find the indexes of all the occurances of a substring in a large string -
(so basically ,and extension of the "indexOf" function) . Any ideas?
Current situation:
def text = " --- --- bcd -- bcd ---"
def sub = "bcd"
text.indexOf(sub)
// = 9
I want something like:
def text = " --- --- bcd -- bcd ---"
def sub = "bcd"
text.indexesOf(sub)
// = [9,15]
Is there such a function? How should I implement it otherwise? (in a non trivial way)
You could write a new addition to the String metaClass like so:
String.metaClass.indexesOf = { match ->
def ret = []
def idx = -1
while( ( idx = delegate.indexOf( match, idx + 1 ) ) > -1 ) {
ret << idx
}
ret
}
def text = " --- --- bcd -- bcd ---"
def sub = "bcd"
text.indexesOf(sub)
There is nothing I know of that exists in groovy currently that gets you this for free though
This is a relatively easy approach:
String.metaClass.indexesOf = { arg ->
def result = []
int index = delegate.indexOf(arg)
while (index != -1) {
result.add(index);
index = delegate.indexOf(arg, index+1);
}
return result;
}
Note that this will find overlapping instances (i.e. "fooo".indexesOf("oo") will return [1, 2]). If you don't want this, replace index+1 with index+arg.length().

Resources