[SOLVED] Substring usage problem

I think I’m being an idiot here but I can’t work out what is wrong with this bit of rule.
Basically, it take each character of a string in turn (and processes it later).
I get the log error

Rule 'gcal get events rule': String index out of range: -1

The rule (a subsection):

var String GCALstr = "*openHAB"
var Number GCALlen

rule "gcal get events rule"

when
    Item TestSwitch6 changed
then
  if(GCALstr.substring(0,1) == "*") {

        GCALlen = GCALstr.length

        logInfo("GCALlen: ", GCALlen.toString())
         var i = 0
        while ((i=i+1) < GCALlen +1)  {

            logInfo("i: ", i.toString())
                  
         var String GCALchar = GCALstr.substring(i, 1)

            logInfo("GCALchar: ", GCALchar.toString())

     }

     }
end


This is the log:

2019-10-04 16:16:49.856 [INFO ] [pse.smarthome.model.script.GCALlen: ] - 8

2019-10-04 16:16:49.867 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 1

2019-10-04 16:16:49.871 [INFO ] [se.smarthome.model.script.GCALchar: ] - 

2019-10-04 16:16:49.879 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 2

2019-10-04 16:16:49.882 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'gcal get events rule': String index out of range: -1

For interest, if I swap the substring round to

var String GCALchar = GCALstr.substring(0, i)

I get:

2019-10-04 16:19:06.251 [INFO ] [pse.smarthome.model.script.GCALlen: ] - 8

2019-10-04 16:19:06.260 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 1

2019-10-04 16:19:06.264 [INFO ] [se.smarthome.model.script.GCALchar: ] - *

2019-10-04 16:19:06.273 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 2

2019-10-04 16:19:06.278 [INFO ] [se.smarthome.model.script.GCALchar: ] - *o

2019-10-04 16:19:06.285 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 3

2019-10-04 16:19:06.290 [INFO ] [se.smarthome.model.script.GCALchar: ] - *op

2019-10-04 16:19:06.298 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 4

2019-10-04 16:19:06.302 [INFO ] [se.smarthome.model.script.GCALchar: ] - *ope

2019-10-04 16:19:06.309 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 5

2019-10-04 16:19:06.313 [INFO ] [se.smarthome.model.script.GCALchar: ] - *open

2019-10-04 16:19:06.324 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 6

2019-10-04 16:19:06.330 [INFO ] [se.smarthome.model.script.GCALchar: ] - *openH

2019-10-04 16:19:06.337 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 7

2019-10-04 16:19:06.342 [INFO ] [se.smarthome.model.script.GCALchar: ] - *openHA

2019-10-04 16:19:06.441 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 8

2019-10-04 16:19:06.475 [INFO ] [se.smarthome.model.script.GCALchar: ] - *openHAB

So I now the string values are okay.

But what I want is each character in turn in the loop.

Any ideas of what is wrong?

Thanks!

Since you want one character at a time from the string, why not use charAt and ?

    if(GCALstr.charAt(0) == '*') {
        GCALlen = GCALstr.length

        GCALstr.toCharArray.forEach[c, i |
            logInfo("i: ", c)
            logInfo("GCALchar: ", c)
        ]
    }

The above should work.

This shoud be

while ((i=i+1) < GCALlen )

The start is always at 0, e.g. if GCALlen=14, the positions are 0-13. When you add the “+1”, the positions wil be 0-14 (15 characters). That’s the String index out of range error (there is no 15th position).

I had tried that (out of desperation). I got the same error.

Thanks for the reply. It didn’t work - but I assume you wrote it on the fly.

You’re right, I should have used character manipulation but I’m still bemused as to why my rule didn’t work.
And, I don’t like the Xtend documentation.

Taking the hints from @rlkoshak, this works perfectly - but it didn’t work when GCALchar was declared as a char type explicitly. Not sure why.

var String GCALstr = "*openHAB"
var Number GCALlen
var int i = 1

rule "gcal get events rule"

when
    Item TestSwitch6 changed
then



        GCALlen = GCALstr.length

        logInfo("GCALlen: ", GCALlen.toString())


while (i < GCALstr.length())
{
   logInfo("i: ", i.toString)
  var GCALchar = GCALstr.charAt(i).toString

  logInfo("GCALchar: ", GCALchar.toString)

    i=i+1

     }
end

log:

2019-10-04 17:13:35.386 [INFO ] [pse.smarthome.model.script.GCALlen: ] - 8

2019-10-04 17:13:35.394 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 1

2019-10-04 17:13:35.400 [INFO ] [se.smarthome.model.script.GCALchar: ] - o

2019-10-04 17:13:35.429 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 2

2019-10-04 17:13:35.435 [INFO ] [se.smarthome.model.script.GCALchar: ] - p

2019-10-04 17:13:35.458 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 3

2019-10-04 17:13:35.465 [INFO ] [se.smarthome.model.script.GCALchar: ] - e

2019-10-04 17:13:35.473 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 4

2019-10-04 17:13:35.479 [INFO ] [se.smarthome.model.script.GCALchar: ] - n

2019-10-04 17:13:35.491 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 5

2019-10-04 17:13:35.497 [INFO ] [se.smarthome.model.script.GCALchar: ] - H

2019-10-04 17:13:35.506 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 6

2019-10-04 17:13:35.512 [INFO ] [se.smarthome.model.script.GCALchar: ] - A

2019-10-04 17:13:35.520 [INFO ] [g.eclipse.smarthome.model.script.i: ] - 7

2019-10-04 17:13:35.526 [INFO ] [se.smarthome.model.script.GCALchar: ] - B


I like it when things work. I also like to know why they did and also why things don’t work and here I’m none-the-wiser but at least I have a solution.