Java

Wrapping the constant interface anti pattern into an Enum

Especially in legacy code, we sometimes come across code like this, also known as the Constant Interface Antipattern:

public interface Constants {
   static int DML_DELETE = 0x02; 
   static int DML_INSERT = 0x05;
   static int DML_UPDATE = 0x10; 
}

Since Java 5, a much better alternative is to use an enum. If possible, code like the above which only defines constants should be converted into a corresponding enum. However, sometimes this is not possible, for example when using a library where the source code is not available. Then, we can still take advantage of enums in our own code by wrapping the legacy constants into an enum type. By default, a Java enum only allows to map from the the enum name to the enum itself, but in our scenario we also need to be able to map the legacy integer constants to the corresponding enum. The following code shows how the above interface could be wrapped into an enum:

public enum ConstEnum {
   DML_DELETE(Constants.DML_DELETE),
   DML_INSERT(Constants.DML_INSERT),
   DML_UPDATE(Constants.DML_UPDATE);
   
   private int constValue;

   // we need to create a reverse map for the enum in order to allow reverse lookups
   private static HashMap<Integer, ConstEnum> revMap = new HashMap<>();
   static {
      for (ConstEnum e : values()) {
         revMap.put(e.value(), e);
      }
   }

   // private constructor for the integer value
   private ConstEnum(int someValue) {
      constValue = someValue;
   }

   public int value() {
      return constValue;
   }

   public static ConstEnum enumFor(int value) {
      ConstEnum result = revMap.get(value);
      if (result == null) {
         throw new NoSuchElementException(ConstEnum.class.getName() + " for " + value); 
      }
      return result;
   }
}

The core of this code is the revMap hashmap which is initialized in the static initializer and puts all available enum objects and their corresponding integer values into a hashmap, so that we can look up the enum object by its integer value, which is done in the enumFor() method. The static values() method is provided automatically by the java compiler for all enum types. The following samples show how the enum type can now be used: List all available values:

for (ConstEnum val : ConstEnum.values()) {
   System.err.println(val + "=" + val.value());
}

DML_DELETE=2
DML_INSERT=5
DML_UPDATE=16

Convert legacy int value into enum:

int someValue = 5;
ConstEnum e = ConstEnum.enumFor(someValue);
System.err.println(e + "=" + e.value());

DML_INSERT=5

Switch on a legacy int value:

someValue = 2;
ConstEnum e = ConstEnum.enumFor(someValue);
switch(e) {
   case DML_DELETE : System.err.println("DELETE");  break;
   case DML_INSERT : System.err.println("INSERT");  break;
   case DML_UPDATE : System.err.println("UPDATE");  break;
}

DELETE

Using Lambdas to implement a function table

When I implemented an expression parser for arithmetic expressions (such as t*x+sin(x-5) + π), one part was to create a symbol table to look up constant values such as π, variables such as x and t, but also functions like sin(x). My initial approach had this structure:

 

This allowed me to create a symbol table as a HashMap, and then to add variables, constants or functions into the table:

private Map<String, Symbol> table = new HashMap<>();
...
table.put("sin",  new SinFunction());
table.put("log",  new LogFunction());
...

This works well, but requires a whole new class for each new function, where each of the classes simply provides a getValue() method which delegates to the corresponding static method from Math:

public double getValue(double arg) {
   return Math.sin(arg);
}

Using lambda expressions, the class structure can be much simplified:

Instead of an abstract class Function with specific sub classes which implement the getValue() method, we provide a concrete Function class which delegates to the functional interface DoubleFunction. The instantiation of the Function objects can then be moved into the SymbolTable class, essentially as a convenient method:

public void putSymbol(String name, DoubleFunction<Double> fun) {
   table.put(name, new Function(name, fun));
}

Now, adding new function to the symbol table is straight forward, using a lambda expression:

symbolTable.putSymbol("sin", x -> Math.sin(x));
symbolTable.putSymbol("log", x -> Math.log(x));

Especially we do not need to add another class when adding a new function. The class structure of the symbol table remains stable, all we need is to register the new function through a call to SymbolTable.putSymbol(). Besides simply mapping a function name to a method from the Math class, this works equally well for any user defined function, for example:

symbolTable.putSymbol("f1", x -> x*x + 42*x + 19);
symbolTable.putSymbol("f2", x -> Math.cos(x*x) + 42*x);

Since the Function class holds a reference to the lambda expression through the DoubleFunction interface, we simply call the DoubleFunction.apply() method to evaluate the function for a given x value:

public class Function extends Symbol {

   private DoubleFunction<Double> theFunc;

   ...

   @Override
   public double getValue(double x) {
      return theFunc.apply(x);
   }
}

Using capture groups in regular expressions

Using regular expressions, it is easy to extract parts which match a particular pattern from a string. Suppose the input string contains some text, followed by a number, possibly followed by some garbage which is of no further interest:

"Hello World12345Garbage"

To extract the leading text part (“Hello World”) and the number (“12345”), the following regular expression can be used:

(\D*)(\d*)

\D is a special sequence inside a regular expression which matches any non-numeric characters. \d is the opposite and matches any numeric character. The * specifies that we want to match any number of the preceeding character, so \D* matches any number (including none) of non-digits, while \d* matches any number of digits. Finally, the parentheses define so-called capture groups. They group the various parts of the pattern so that these groups can later be accessed. Since we want to match text (non-digits) followed by a number (digits), the capture groups are (\D*) for the text part and (\d*) for the numeric part. See https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html for a complete list of the supported regular expression syntax. The following code shows a complete example, using the Pattern and the Matcher classes. Note that we need to escape the backslash with another backslash in the regular expression string, so that the java compiler actually inserts a backslash character, and does not treat it as an escape sequence. We can then access the two groups using Matcher.group(int group):

String input = "Hello World12345Garbage";
String regexp = "(\\D*)(\\d*)";

Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(input);
matcher.find();
System.out.println("Text  : " + matcher.group(1));
System.out.println("Number: " + matcher.group(2));

Output:

Text  : Hello World
Number: 12345 

Accessing the capture groups by index can be misleading and difficult to maintain, especially for more complex regular expressions. Starting with Java 7, the API also supports named capture groups. A capture group can be given a name by adding ?<name> directly after the opening paranthesis:

(?<text>\D*)(?<number>\d*)

Then, the capture groups can be accessed by their name instead of their index, using Matcher.group(String name):

String input = "Hello World12345Garbage";

String regexp = "(?<text>\\D*)(?<number>\\d*)";

Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(input);
matcher.find();
System.out.println("Text  : " + matcher.group("text"));
System.out.println("Number: " + matcher.group("number"));

Output:

Text  : Hello World
Number: 12345 

Resolving build dependencies through manifest file

The MANIFEST.MF file in a jar file can be used to define runtime dependencies through the Class-Path attribute. In the manifest specification, it says:

Class-Path: The value of this attribute specifies the relative URLs
of the extensions or libraries that this application or extension needs. 
URLs are separated by one or more spaces. 
The application or extension class loader uses the value of this attribute
to construct its internal search path.

Since it explicitly states “application or extension class loader”, it is not completely clear from the specification that the Class-Path attribute is also considered by the javac compiler to resolve build dependencies. However, it is – this is the bug which introduced that feature in Java 5: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4212732 Consider the following sample code which imports classes from some third party jar files:

package com.example;

import org.apache.log4j.PropertyConfigurator;
import com.google.gson.Gson;

public class Sample {

   public static void main(String[] args) {
      PropertyConfigurator.configure("log4j.properties");
      Gson gson = new Gson();

      // ...
   }
}

We can create a jar file like libs.jar with a Class-Path reference to the corresponding libraries:

$ cat manifest.txt
Class-Path: lib/gson-2.2.2.jar lib/log4j-1.2.17.jar

$ jar cvfm libs.jar manifest.txt
added manifest

By simply adding the libs.jar to the classpath when invoking javac, the additional jar files get pulled in:

$ javac -d bin -classpath libs.jar -sourcepath src src/com/example/Sample.java

$ ls -la bin/com/example/Sample.class
-rw-r--r-- 1 andreas users 432 Apr  7 12:20 bin/com/example/Sample.class

A real-world sample where this is used is the Oracle Platform Security Services. There is only one jar file which needs to be added to the build path, jps-manifest.jar, which references all other required jar files through its Class-Path attribute.