Search

January 12, 2020

Groovy Goodness: Transform Elements While Flattening

We can use the flatten method in Groovy to flatten a collection that contains other collections into a single collection with all elements. We can pass a closure as extra argument to the flatten method to transform each element that is flattened. The argument of the closure is the element from the original collection.

In the following example we first use the flatten method without a closure argument. Then we pass a closure argument and transform the element:

def list = [1, [2, 3], [[4]]]

// Simple flatten the nested collections.
assert list.flatten() == [1, 2, 3, 4]

// We can use a closure to transform
// the elements in the resulting collection.
assert list.flatten { it * 2 } == [2, 4, 6, 8]

Written with Groovy 2.5.7.

January 10, 2020

Clojure Goodness: Flatten Collections

We can use the flatten function when we have a collection with nested sequential collections as elements and create a new sequence with the elements from all nested collections.

In the following example we use the flatten function:

(ns mrhaki.sample
  (:require [clojure.test :refer [is]]))

;; Elements from nested sequential collections are flattend into new sequence.
(is (= [1 2 3 4 5] (flatten [1 [2 3] [[4]] 5])))
(is (sequential? (flatten [1 [2 3] [[4]] 5])))
(is (= [1 2 3 4 5] (flatten [[1] [2 3] [[4 5]]])))

;; We can use different sequential collection types.
;; We might have to force a type to a sequential collection with seq.
(is (= '(1 2 3 4 5) (flatten [1 (seq (java.util.List/of 2 3)) ['(4 5)]])))
(is (= (quote (1 2 3 4 5)) (flatten [[1] [(range 2 6)]])))

;; flatten on nil returns empty sequence.
(is (= () (flatten nil)))

Written with Clojure 1.10.1.

January 8, 2020

Clojure Goodness: Getting Intersections Between Sets

In the clojure.set namespace we can find the intersection function. This functions accepts one or more sets as arguments and return a new set with all elements that are present in the sets that are passed as arguments to the intersection function. The argument must be a set, so we need to convert other collection or seq values to a set first before we use it as an argument for the function.

In the following example we use one, two or three arguments for the intersection function and also convert other types to a set to be used as argument:

(ns mrhaki.sample
  (:require [clojure.set :refer [intersection]]
            [clojure.test :refer [is]]))

;; Use intersection with sets to find common elements.
(is (= #{"Clojure"} (intersection #{"Java" "Scala" "Clojure"} #{"Clojure" "Groovy"})))

;; An empty set is returned if there is no common element.
(is (= #{} (intersection #{"Java" "Groovy" "Clojure"} #{"C++" "C#"})))

;; We can use more than two sets to find intersections.
(is (= #{"Clojure"} (intersection #{"Java" "Scala" "Clojure"} 
                                  #{"Clojure" "Groovy"} 
                                  #{"Groovy" "JRuby" "Clojure"})))

;; With one set intersections returns the set.
(is (= #{"Clojure" "Groovy"} (intersection #{"Clojure" "Groovy"})))

;; Only sets are allowed as arguments for the intersection function.
;; If one of the arguments is not a set the return value is unexpected. 
(is (= #{} (intersection #{"Clojure" "Groovy"} ["Java" "Scala" "Clojure"])))
;; But we can convert a non-set to a set with the set function.
(is (= #{"Clojure"} (intersection #{"Clojure" "Groovy"} (set ["Java" "Scala" "Clojure"]))))
(is (= #{"Clojure"} (intersection #{"Clojure" "Groovy"} (set '("Java" "Scala" "Clojure")))))
;; Or using into #{}.
(is (= #{"Clojure"} (intersection #{"Clojure" "Groovy"} 
                                  (into #{} (vals {:platform "Java" :language "Clojure"})))))

Written with Clojure 1.10.1

January 6, 2020

Clojure Goodness: Joining Elements in a Collection

We can use the join function from the clojure.string namespace to join elements from a collection into a string. We can optionally specify a separator that is used to separate each element in the string output. The separator is not used after the last element of the collection. If we don't specify a separator the elements are concatenated without separation. The string representation for each element in the collection is used in the joined end result.

In the following example code we see different usages of the join function:

(ns mrhaki.sample
  (:import [java.util Currency Locale])
  (:require [clojure.string :refer [join]]
            [clojure.test :refer [is]]))

;; Join without explicit separator simply concats values in collection.
(is (= "abc" (join ["a" "b" "c"])))

;; Join with separator uses separator between elements from collection
;; and omits the separator after the last element.
(is (= "a, b, c" (join ", " ["a" "b" "c"])))

;; Join works on multiple collection types, 
;; because each collection is transformed to a seq.
(is (= "a::b::c" (join "::" #{"a" "b" "c"})))

;; Collection with non-strings is also returned as string.
;; The string representation of each element is used.
(is (= "0 1 2 3 4 5 6 7 8 9 10" (join " " (range 11))))
(is (= "https://www.mrhaki.com:443/,EUR" (join \, [(java.net.URL. "https" "www.mrhaki.com" 443 "/")
                                                    (Currency/getInstance (Locale. "nl" "NL"))])))

;; Nil values are ignored in the join results, 
;; but separator is still used for nil element.
(is (= "Clojure--is cool--!" (join "-" ["Clojure" nil "is cool" nil "!"])))

;; Function query-params to transform a map structure with 
;; keyword keys to URL request parameters.
(defn query-params 
  "Return key/value pairs as HTTP request parameters separated by &.
   Each request parameter name and value is separated by =.
   E.g. {:q \"Clojure\" :max 10 :start 0 :format \"xml\"} is transformed
   to q=Clojure&max=10&start=0&format=xml."
  [params]
  (let [query-param (fn [[param-name param-value]] (join "=" [(name param-name) param-value]))]
    (join "&" (map query-param params))))

(is (= "q=Clojure&max=10&start=0&format=xml" (query-params {:q "Clojure" :max 10 :start 0 :format "xml"})))

Written with Clojure 1.10.1

January 3, 2020

Clojure Goodness: Trimming Strings

In the clojure.string namespace we can find several useful function for working with strings. If we want to trim a string we can choose for the trim, trial, trimr and trim-newline functions. To trim all characters before a string we must use the triml function. To remove all space characters after a string we use trimr. To remove space characters both before and after a string we can use the trim function. Finally if we only want to remove the newline and/or return characters we use the trim-newline function.

In the following example we use the different trim functions on strings:

(ns mrhaki.sample
  (:require [clojure.test :refer [is]]
            [clojure.string :refer [trim triml trimr trim-newline]]))

;; The trim function removes spaces before and after the string.
(is (= "mrhaki" (trim " mrhaki ")))
;; Tabs are also trimmed.
(is (= "mrhaki" (trim "\t mrhaki ")))
;; Return and/or newline characters are also trimmed.
(is (= "mrhaki" (trim "\tmrhaki \r\n")))
;; Character literals that should be trimmed are trimmed.
(is (= "mrhaki" (trim (str \tab \space " mrhaki " \newline))))

;; The triml function removes spaces before the string (trim left).
(is (= "mrhaki " (triml " mrhaki ")))
(is (= "mrhaki " (triml "\t mrhaki ")))
(is (= "mrhaki " (triml "\nmrhaki ")))
(is (= "mrhaki " (triml (str \return \newline " mrhaki "))))

;; The trimr function removes spaces after the string (trim right).
(is (= " mrhaki" (trimr " mrhaki ")))
(is (= " mrhaki" (trimr " mrhaki\t")))
(is (= " mrhaki" (trimr (str " mrhaki " \newline))))

;; The trim-newline function removes only newline from string.
(is (= "mrhaki " (trim-newline (str "mrhaki " \newline))))
(is (= "mrhaki " (trim-newline (str "mrhaki " \return \newline))))
(is (= "mrhaki " (trim-newline "mrhaki \r\n")))
(is (= "mrhaki " (trim-newline "mrhaki ")))

Written with Clojure 1.10.1.

December 10, 2019

Awesome Asciidoctor: Auto Number Callouts

In a previous post we learned about callouts in Asciidoctor to add explanation to source code. While surfing the Internet I came upon the following blog post by Alex Soto: Auto-numbered Callouts in Asciidoctor. I turns out that since Asciidoctor 1.5.8 we can use a dot (.) instead of explicit numbers to have automatic increasing numbering for the callouts.

Let's take our example from the earlier blog post and now use auto numbered callouts:

= Callout sample
:source-highlighter: prettify
:icons: font

[source,groovy]
----
package com.mrhaki.adoc

class Sample {
    String username // <.>

    String toString() {
        "${username?.toUpperCase() ?: 'not-defined'}" // <.>
    }
}
----
<.> Simple property definition where Groovy will generate the `setUsername` and `getUsername` methods.
<.> Return username in upper case if set, otherwise return `not-defined`.

When we convert this markup to HTML we get the following result:

This makes it very easy to add new callouts without having to change all numbers we first typed by hand.

Written with Asciidoctor 2.0.9

September 11, 2019

Quickly Find Unicode For Character On macOS

Sometimes when we are developing we might to need to lookup the unicode value for a character. If we are using macOS we can use the Character Viewer to lookup the unicode. We can open the Character Viewer using the key combination ⌃+⌘+Space (Ctrl+Cmd+Space) or open the Edit menu in our application and select Emoji & Symbols. We can type the character we want to unicode value for in the Search box or look it up in the lists. When we select the character we can see at the right the Unicode for that character:

If the Unicode value is not shown we first need to add the Unicode code table to the Character Viewer. We must select the menu at the top left and click on Customise List....:

Next we must select the Code Tables node and select Unicode:

When we search or click on a new character we get the unicode value.

September 10, 2019

Spocklight: Use Stub or Mock For Spring Component Using @SpringBean

When we write tests or specifications using Spock for our Spring Boot application, we might want to replace some Spring components with a stub or mock version. With the stub or mock version we can write expected outcomes and behaviour in our specifications. Since Spock 1.2 and the Spock Spring extension we can use the @SpringBean annotation to replace a Spring component with a stub or mock version. (This is quite similar as the @MockBean for Mockito mocks that is supported by Spring Boot). We only have to declare a variable in our specification of the type of the Spring component we want to replace. We directly use the Stub() or Mock() methods to create the stub or mock version when we define the variable. From now on we can describe expected output values or behaviour just like any Spock stub or mock implementation.

To use the @SpringBean annotation we must add a dependency on spock-spring module to our build system. For example if we use Gradle we use the following configuration:

...
dependencies {
    ...
    testImplementation("org.spockframework:spock-spring:1.3-groovy-2.5")
    ...
}
...

Let's write a very simple Spring Boot application and use the @SpringBean annotation to create a stubbed component. First we write a simple interface with a method that accepts an argument of type String and return a new String value:

package mrhaki.spock;

public interface MessageComponent {
    String hello(final String name);
}

Next we use this interface in a Spring REST controller where we use constructor dependency injection to inject the correct implementation of the MessageComponent interface into the controller:

package mrhaki.spock;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageController {

    private final MessageComponent messageComponent;

    public MessageController(final MessageComponent messageComponent) {
        this.messageComponent = messageComponent;
    }

    @GetMapping(path = "/message", produces = MediaType.TEXT_PLAIN_VALUE)
    public String message(@RequestParam final String name) {
        return messageComponent.hello(name);
    }

}

To test the controller we write a new Spock specification. We use Spring's MockMvc support to test our controller, but the most important part in the specification is the declaration of the variable messageComponent with the annotation @SpringBean. Inside the method where we invoke /message?name=mrhaki we use the stub to declare our expected output:

package mrhaki.spock

import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.test.web.servlet.MockMvc
import spock.lang.Specification

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get

@WebMvcTest(MessageController)
class MessageControllerSpec extends Specification {

    @Autowired
    private MockMvc mockMvc

    /**
     * Instead of the real MessageComponent implementation
     * in the application context we want to use our own
     * Spock Stub implementation to have control over the
     * output of the message method.
     */
    @SpringBean
    private MessageComponent messageComponent = Stub()

    void "GET /message?name=mrhaki should return result of MessageComponent using mrhaki as argument"() {
        given: 'Stub returns value if invoked with argument "mrhaki"'
        messageComponent.hello("mrhaki") >> "Hi mrhaki"

        when: 'Get response for /message?name=mrhaki'
        final response = mockMvc.perform(get("/message").param("name", "mrhaki"))
                                .andReturn()
                                .getResponse()

        then:
        response.contentAsString == "Hi mrhaki"
    }
}

Written with Spock 1.3-groovy-2.5 and Spring Boot 2.1.8.RELEASE.

Java Joy: Transform Elements In Stream Using a Collector

Using the Stream API and the map method we can transform elements in a stream to another object. Instead of using the map method we can also write a custom Collector and transform the elements when we use the collect method as terminal operation of the stream.

First we have an example where we transform String value using the map method:

package mrhaki;

import java.util.List;
import java.util.stream.Collectors;

public class CollectorString {
    public static void main(String[] args) {
        final var items = List.of("JFall", "JavaZone", "CodeOne");

        final List<String> upper =
                items.stream()
                     .map(String::toUpperCase)
                     .collect(Collectors.toUnmodifiableList());
        
        assert upper.equals(List.of("JFALL", "JAVAZONE", "CODEONE"));
    }
}

In our next example we don't use the map method, but we write a custom Collector using the Collector.of method. As first argument we must provide the data structure we want to add elements too, the so-called supplier, which is an ArrayList. The second argument is an accumulator where we add each element from the stream to the list and transform the value. The third argument is the combiner and here we combine multiple List instances to one List instance. The last argument is a finisher and we make an immutable List to be returned.

package mrhaki;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collector;

public class CollectorString1 {
    public static void main(String[] args) {
        final var items = List.of("JFall", "JavaZone", "CodeOne");

        final List<String> upper =
                items.stream()
                     // Use collector to transform values
                     // in the items List.
                     .collect(upperCollect());

        assert upper.equals(List.of("JFALL", "JAVAZONE", "CODEONE"));
    }

    private static Collector<String, ?, List<String>> upperCollect() {
        return Collector.of(
                // First we specify that we want to add
                // each element from the stream to an ArrayList.
                () -> new ArrayList<String>(),

                // Next we add each String value to the list
                // and turn it into an uppercase value.
                (list, value) -> list.add(value.toUpperCase()),

                // Next we get two lists we need to combine,
                // so we add the values of the second list
                // to the first list.
                (first, second) -> { first.addAll(second); return first; },

                // Finally (and optionally) we turn the 
                // ArrayList into an unmodfiable List.
                list -> Collections.unmodifiableList(list));
    }
}

Written with Java 12.

September 9, 2019

Java Joy: Combining Predicates

In Java we can use a Predicate to test if something is true or false. This is especially useful when we use the filter method of the Java Stream API. We can use lambda expressions to define our Predicate or implement the Predicate interface. If we want to combine different Predicate objects we can use the or, and and negate methods of the Predicate interfaces. These are default methods of the interface and will return a new Predicate.

Let's start with an example where we have a list of String values. We want to filter all values that start with Gr or with M. In our first implementation we use a lambda expression as Predicate and implements both tests in this expression:

package mrhaki;

import java.util.List;
import java.util.stream.Collectors;

public class PredicateComposition1 {
    public static void main(String[] args) {
        final var items = List.of("Groovy", "Gradle", "Grails", "Micronaut", "Java", "Kotlin");

        final List<String> gr8Stuff =
                items.stream()
                     // Use lambda expression with both tests as Predicate.
                     .filter(s -> s.startsWith("Gr") || s.startsWith("M"))
                     .collect(Collectors.toUnmodifiableList());

        assert gr8Stuff.size() == 4 : "gr8Stuff contains 4 items";
        assert gr8Stuff.contains("Groovy");
        assert gr8Stuff.contains("Gradle");
        assert gr8Stuff.contains("Grails");
        assert gr8Stuff.contains("Micronaut");
    }
}

We will rewrite the previous example and introduce the startsWith method that returns a new Predicate. Then in our filter method we use the or method of the Predicate object to combine the two Predicate objects:

package mrhaki;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateComposition2 {
    public static void main(String[] args) {
        final var items = List.of("Groovy", "Gradle", "Grails", "Micronaut", "Java", "Kotlin");

        final List<String> gr8Stuff =
                items.stream()
                     // Use the Predicate.or method to combine two Predicate objects.
                     .filter(startsWith("Gr").or(startsWith("M")))
                     .collect(Collectors.toUnmodifiableList());

        assert gr8Stuff.size() == 4 : "gr8Stuff contains 4 items";
        assert gr8Stuff.contains("Groovy");
        assert gr8Stuff.contains("Gradle");
        assert gr8Stuff.contains("Grails");
        assert gr8Stuff.contains("Micronaut");
    }

    // Create a predicate to check if String value starts with a given value.
    private static Predicate<String> startsWith(final String begin) {
        return s -> s.startsWith(begin);
    }
}

In the following example we use the negate and and method to find all values that do not start with Gr and with a length less than 8 characters:

package mrhaki;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateComposition3 {
    public static void main(String[] args) {
        final var items = List.of("Groovy", "Gradle", "Grails", "Micronaut", "Java", "Kotlin");

        final List<String> otherStuff =
                items.stream()
                     // Find all values that do not start with "Gr"
                     // and have less than 8 characters.
                     .filter(startsWith("Gr").negate().and(smallerThan(8)))
                     .collect(Collectors.toUnmodifiableList());

        assert otherStuff.size() == 2 : "otherStuff contains 2 items";
        assert otherStuff.contains("Java");
        assert otherStuff.contains("Kotlin");
    }

    // Create a predicate to check if String value starts with a given value.
    private static Predicate<String> startsWith(final String begin) {
        return s -> s.startsWith(begin);
    }

    // Create a predicate to check if String value has 
    // less characters than the given size.
    private static Predicate<String> smallerThan(final int size) {
        return s -> size >= s.length();
    }
}

In our previous example we can replace the negate method call on our predicate with the static Predicate.not method. The predicate is than an argument and is just another way to express the same predicate:

package mrhaki;

import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class PredicateComposition4 {
    public static void main(String[] args) {
        final var items = List.of("Groovy", "Gradle", "Grails", "Micronaut", "Java", "Kotlin");

        final List<String> otherStuff =
                items.stream()
                     // Find all values that do not start with "Gr",
                     // using Predicate.not instead of negate, 
                     // and have less than 8 characters.
                     .filter(Predicate.not(startsWith("Gr")).and(smallerThan(8)))
                     .collect(Collectors.toUnmodifiableList());

        assert otherStuff.size() == 2 : "otherStuff contains 2 items";
        assert otherStuff.contains("Java");
        assert otherStuff.contains("Kotlin");
    }

    // Create a predicate to check if String value starts with a given value.
    private static Predicate<String> startsWith(final String begin) {
        return s -> s.startsWith(begin);
    }

    // Create a predicate to check if String value has 
    // less characters than the given size.
    private static Predicate<String> smallerThan(final int size) {
        return s -> size >= s.length();
    }
}

Written with Java 12.