Open Source: core library

Few months ago, after I moved to GitHub, one of my util projects was open sourced. It was, simply called, core: https://github.com/rkhmelyuk/core. I have written this library few years ago and was actively using on Java projects. In some places it crosses with Apache Commons Lang library, but I, actually, like my child more :)

I'd like to describe some key classes and show samples of use. Some of them are enumerated below.

StringUtils contains few oftenly used methods, like:

  • isEmpty(), isBlank(), isNotEmpty(), isNotBlank(), isBlankTrimmed(), isNotBlankTrimmed() - used to check whether string is empty or not. The difference between empty and blank, is that empty is either null or empty string, while blank is always blank string and can't be null.

  • cut() - used to cut string if length is more than specified and appends with specified suffix. The only difference is that this method tries to split by space, so don't cut the word. Sample:

    String string = "some string goes here";
    assertEquals "some string...", StringUtils.cut(string, 15, "...");

  • trimIfNotNull() - if input string is not null, then trim it and return result:

    String string = " Hello ";
    assertEqual "Hello", StringUtils.trimIfNotNull(string);
    assertNull StringUtils.trimIfNotNull(null);

  • replaceNotAlphaNumeric() - replace all characters that are not letter or digit with specified one or "_" by default.


ConversionUtils contains some simple but useful methods to convert string value to numeric and boolean types. Contains methods getInteger(), getLong(), getBoolean(), getDouble(), getDate(), getFloat():

assertEquals 1, ConversionUtils.getInteger("1");
assertNull ConversionUtils.getInteger("hello");
assertEquals 5, ConversionUtils.getInteger("hello", 5);

KeyGenerator was created to generate API keys, passwords and other random stuff. It has one highly configurable method and few helpful methods that uses it. There is a way to generate keys with alpha and/or numeric and/or special symbols.

That would be hard to write assertions for samples, but here are simple use cases:

KeyGenerator.generateKey(10, KeyGenerator.WITH_ALPHA_LOW | KeyGenerator.WITH_ALPHA_UP);
KeyGenerator.generateStrongKey(100);
KeyGenerator.generateSimpleKey(20);
KeyGenerator.generateAlphaKey(20);

After I found some issues with Apache Commons-Lang ToStringBuilder, I wrote my own replacement, and called it... ToStringBuilder :) It is very simple in use:

class Blog {
private String name;
private String author;
private int year;

public String toString() {
new ToStringBuilder(Blog.class)
.field("name", name)
.field("author", author)
.field("year", year)
.toString();
}
}

Blog blog = new Blog();
blog.setName("Java UA");
blog.setAuthor("Ruslan Khmelyuk");
blog.setYear(2010);

assertEquals "Blog[name=Java UA, author=Ruslan Khmelyuk, year=2010]", blog.toString();

There are much more interesting tools, like ArgumentAssert and StateAssert used to assert arguments and program state respectively.

CollectionUtils also contains few useful methods, and I'm not going to describe them here.

Library is open to review and use. Still it's definitely not the best one and, I think, has value only for me.

Neverending Groovy: map with default values

More and more Groovy openings for me every day!

Just today, I found that there is a way to setup default value for map entry, if absent. In some cases it may be very handy.

For example, I need to prepare a map with words counts. This simple task should be coded simple too, like:

def map = [:]
words.each { word -> map[word]++ }

But it's not working and fails with NPE exception. Why? Because it's hard to increment null.

Although, there is simple way to avoid this problem even using Groovy API:

def map = [:]
words.each { word -> map[word] = map.get('word', 0) + 1

Here 2nd parameter of map.get() method is the default value, returned if there is no value for key 'word'. And now it's working fine!
Still there is another way, and, as for me, it helps to make code clean and safe. Safe because default logic can be used elsewhere we want to use our map object.

def map = [:].withDefault { 0 }
words.each { word -> map[word]++ }


I bet there is a better way and I'm going to find it...