Is there standard method for managing camel cased strings in groovy? - groovy

For example groovy converts getSomeProperty() method to someProperty.
I need the same for my string. prefixMyString converted to myString.
Is there standard way to do so?

Groovy doesn't actually convert getSomeProperty() into someProperty. It only converts the other way, turning someProperty into getSomeProperty()
It does this using the capitalize(String property) method on org.codehaus.groovy.runtime.MetaClassHelper. You can run this in the console to see it work:
org.codehaus.groovy.runtime.MetaClassHelper.capitalize('fredFlinstone')
// outputs 'FredFlintstone'
The full conversion, including adding set, get, or is, can be found in the class groovy.lang.MetaProperty, under the methods getGetterName and getSetterName.
To convert the other way, you'll have to write your own code. However, that's relatively simple:
def convertName(String fullName) {
def out = fullName.replaceAll(/^prefix/, '')
out[0].toLowerCase() + out[1..-1]
}
println convertName('prefixMyString') // outputs: myString
println convertName('prefixMyOTHERString') // outputs: myOTHERString
Just change the prefix to meet your needs. Note that it's a regex, so you have to escape it.
EDIT: I made a mistake. There actually is a built-in Java method to decapitalize, so you can use this:
def convertName(String fullName) {
java.beans.Introspector.decapitalize(fullName.replaceAll(/^prefix/, ''))
}
It works nearly the same, but uses the built-in Java class for handling the decapitalization. This method handles uppercase characters a little differently, so that prefixUPPERCASETest returns UPPERCASETest.

Related

How to generate a warning/error when using non-string-variables inside string interpolation?

TypeScript does not produce any errors for the following code:
const maybe_a_string: undefined | string = undefined;
const false_or_string: false | string = false;
// I'd like the following to produce an error/warning...
const message_string = `Some readable string info should be here: ${maybe_a_string} ${false_or_string}`;
Is there some kind of setting I can turn on, or simple alternative ways to write the last line that will warn me about trying to use non-string variables inside strings like this? (but without needing to add extra lines of code for every sub-string to be asserted individually)
I guess it treats them as fine because some types like bools, numbers and misc objects have a .toString() method...
But especially in the case of undefined (which actually doesn't have a .toString() method) - it's quite common for you to have a bug there, as the only time you really want to see the string "undefined" inside another string is for debugging purposes. But there's a lot of these bugs out there in the wild where end users are seeing stuff like "hello undefined" unintentionally.
Personally I would handle this by making the string template into a function. That way you can specify that the arguments must be strings.
const createMessageString = (first: string, second: string): string => {
return `Some readable string info should be here: ${first} ${second}`;
}
const message_string = createMessageString( maybe_a_string, false_or_string );
// will give an error unless types are refined
Vote for https://github.com/microsoft/TypeScript/issues/30239 [Restrict template literal interpolation expressions to strings]
Additionally, you can try workarounds from the issue comments.

How to check if a String contains multiple values and ignore case with StringUtils

I wrote a method to check if a string contains various values.
def validateString(metricValue: String): Boolean = {
(!StringUtils.containsIgnoreCase(metricValue, "metric_1")
&& StringUtils.containsIgnoreCase(metricValue, "metric_2")
|| StringUtils.containsIgnoreCase(metricValue, "metric_3")
}
Then I decided to reduce the last two checks to a single one but haven't found anything that may be helpful in commons-lang-2.6.
I know there is a similar method in lang 3: StringUtils.equalsAnyIgnoreCase(str, "val1", "val2", "val3")). But I need something like containsAnyIgnoreCase.
Is there a way to check if any of multiple values is present in a String ignoring the case?
Try
List("metric_2", "metric_3")
.map(_.toLowerCase)
.contains(metricValue.toLowerCase)
If you want to use StringUtils:
def validateString(metricValue: String): Boolean =
List("metric_2", "metric_3").exists(metricToCheck => StringUtils.containsIgnoreCase(metricValue, metricToCheck))

Kotlin method chaining to process strings in a list

I have a list of strings I get as a result of splitting a string. I need to remove the surrounding quotes from the strings in the list. Using method chaining how can I achieve this? I tried the below, but doesn't work.Says type interference failed.
val splitCountries: List<String> = countries.split(",").forEach{it -> it.removeSurrounding("\"")}
forEach doesn't return the value you generate in it, it's really just a replacement for a for loop that performs the given action. What you need here is map:
val splitCountries: List<String> = countries.split(",").map { it.removeSurrounding("\"") }
Also, a single parameter in a lambda is implicitly named it, you only have to name it explicitly if you wish to change that.

Convert a text file to UTF8 in D

I'm attempting to use the Phobos standard library functions to read in any valid UTF file (UTF-8, UTF-16, or UTF-32) and get it back as a UTF-8 string (aka D's string). After looking through the docs, the most concise function I could think of to do so is
using std.file, std.utf;
string readToUTF8(in string filename)
{
try {
return readText(filename);
}
catch (UTFException e) {
try {
return toUTF8(readText!wstring(filename));
}
catch (UTFException e) {
return toUTF8(readText!dstring(filename));
}
}
}
However, catching a cascading series of exceptions seems extremely hackish. Is there a "cleaner" way to go about it without relying on catching a series of exceptions?
Additionally, the above function seems to return a one-byte BOM in the resulting string if the source file was UTF-16 or UTF-32, which I would like to omit given that it's UTF-8. Is there a way to omit that besides explicitly stripping it?
One of your questions answers the other: the BOM allows you to identify the exact UTF encoding used in the file.
Ideally, readText would do this for you. Currently, it doesn't, so you'd have to implement it yourself.
I'd recommend using std.file.read, casting the returned void[] to a ubyte[], then looking at the first few bytes to see if they start with a BOM, then cast the result to the appropriate string type and convert it to a string (using toUTF8 or to!string).

What do empty square brackets after a variable name mean in Groovy?

I'm fairly new to groovy, looking at some existing code, and I see this:
def timestamp = event.timestamp[]
I don't understand what the empty square brackets are doing on this line. Note that the timestamp being def'd here should receive a long value.
In this code, event is defined somewhere else in our huge code base, so I'm not sure what it is. I thought it was a map, but when I wrote some separate test code using this notation on a map, the square brackets result in an empty value being assigned to timestamp. In the code above, however, the brackets are necessary to get correct (non-null) values.
Some quick Googling didn't help much (hard to search on "[]").
EDIT: Turns out event and event.timestamp are both zero.core.groovysupport.GCAccessor objects, and as the answer below says, the [] must be calling getAt() on these objects and returning a value (in this case, a long).
The square brackets will invoke the underlying getAt(Object) method of that object, so that line is probably invoking that one.
I made a small script:
class A {
def getAt(p) {
println "getAt: $p"
p
}
}
def a = new A()
b = a[]
println b.getClass()
And it returned the value passed as a parameter. In this case, an ArrayList. Maybe that timestamp object has some metaprogramming on it. What does def timestamp contains after running the code?
Also check your groovy version.
Empty list, found this. Somewhat related/possibly helpful question here.
Not at a computer, but that looks like it's calling the method event.timestamp and passing an empty list as a parameter.
The same as:
def timestamp = event.timestamp( [] )

Resources