Mittwoch, 23. Juli 2014

Requiring a constructor without arguments in Java

In Java every class gets a default constructor. This constructor has no arguments and it is possible to override this constructor. But it is also possible to define a constructor with arguments. In this case it is not possible any more to make an instance of this class without specifying the arguments for the constructor. Java does not create any default constructors as long as any constructor has been defined.

This leads to the problem: how to require a class to have a constructor without arguments?

In Java it is not possible to specify any rules for anything static. Anything static are either classes or static methods. It is neither possible to implement an interface with a static method, nor is it possible to define an interface for a class. Interfaces in Java specify requirements only for objects. Java does not implement a Meta Object Protocol. How to work around this problem?

It is necessary to move the constructor from the class to the object, because for the object it is possible to define requirements in the interface the class implements. But the solution is not obvious, because it is necessary to make the interface generic. Otherwise it would not be possible for the constructor method to return the correct type. Here is a complete example:

import java.util.List;
import java.util.LinkedList;

class Make
{
  static interface HasMake<T extends HasMake<?>>
  {
    T make();
  }

  static class Car implements HasMake<Car>
  {
    public Car make() { return new Car(); }
  }

  static class Bike implements HasMake<Bike>
  {
    public Bike make() { return new Bike(); }
  }

  public static void main (String[] args)
  {
    List<HasMake<?>> makeables = new LinkedList<HasMake<?>>();
    makeables.add (new Car());
    makeables.add (new Bike());
    for (HasMake<?> makeable : makeables)
      System.out.println (makeable.make());
  }
}

The interface which defines the constructor is HasMake and the constructor is called make. The interface has to be configured with itself. This makes it possible to use the correct return type in the prototype of make. The classes Car and Bike implement HasMake and as long as you have an instance of the classes it is possible to rely at compile time on the existence of the make method which creates a new instance of the class without arguments.

A solution using reflection will not guarantee this at compile time. It is possible to instantiate a class at run time using a constructor requiring no arguments. But it is not possible to require a class to have such a constructor. If it does not exist, the solution using reflection will fail at run time with an run time exception and it will be impossible to work around this exception at run time.

Dienstag, 8. Juli 2014

Subversion reintegrate without --reintegrate

Older Subversion servers do not support the --reintegrate option of newer clients. This makes it necessary to do it without. In order to merge the changes from a branch into the trunk it is necessary to find the revision number when the branch has been created by a copy. This is done by the --stop-on-copy option of svn log.

$ svn log --verbose --stop-on-copy ../branches/szi
------------------------------------------------------------------------
r3501 | szi | 2014-07-08 16:14:07 +0200 (Tue, 08 Jul 2014) | 1 line
Changed paths:
   A /java-dao/branches/szi (from /java-dao/trunk:3494)
   M /java-dao/branches/szi/src/dao/Condition.java
   M /java-dao/branches/szi/src/dao/Entity.java
   M /java-dao/branches/szi/src/dao/Factory.java
   M /java-dao/branches/szi/src/dao/Facturable.java
   M /java-dao/branches/szi/src/dao/Order.java
   M /java-dao/branches/szi/src/dao/Value.java

After that you can do the merge.

$ svn merge -r 3494:HEAD ../branches/szi
--- Merging r3495 through r3581 into '.':
U    src/dao/Factory.java
U    src/dao/Facturable.java
U    src/dao/Order.java
U    src/dao/Value.java
U    src/dao/Entity.java
U    src/dao/Condition.java

Mittwoch, 25. Juni 2014

Quoted Identifiers in Oracle

The default setting of Oracle's Data Modeler is to generate a DDL file without quoted identifier. This involves the danger of name collisions. It is not possible to call a table "TABLE", because "TABLE" is an identifier of the data definition language. The list of standard identifiers is quite long and the list of vendor specific extensions is much longer. It is impossible to know all identifiers to prevent name collisions. But it is quite simple to avoid any name collisions by quoting the identifiers. If you use quoted identifiers you do not need to care any longer about identifiers.

The following screen shot shows where to enable quoted identifiers in Oracle's Data Modeler.

But you have to consider MySQL's incompatibility. MySQL conforms not to the SQL standard. The SQL standard specifies that quoted identifiers must be quoted with a double quote. But MySQL uses back quotes instead to quote an identifier.

Renaming primary keys in the logical model of Oracles Data Modeler

In the past I explained already how to rename inheritance relations. Now I will show a small script to fix wrong names of primary key constraints. This is necessary, if an entity gets renamed. In this case the primary key constraint has still the old name of the entity according to the naming convention, which was active when the primary key has been created.

entities = model.getEntitySet().toArray();
for (var e = 0; e < entities.length; e++) {
  entity = entities[e];
  entity_name = entity.getName();
  primarykey = entity.getPK();
  primarykey_name = primarykey.getName();
  new_primarykey_name = entity_name.toUpperCase() + "_PK";
  if (primarykey_name != new_primarykey_name) {
    primarykey.setName(new_primarykey_name);
    primarykey.setDirty(true);
  }
}

This script works on the logical model and sets all primary key names to the upper case of the entity name followed by "_PK".

Mittwoch, 11. Juni 2014

Extract the Class-Path from a JAR using SED

The Class-Path in a manifest file of a JAR exceeds in most cases the line width limit of manifest files. In this case the line is continued in the next line which starts with a space. In order to read the class path from a manifest file it is necessary to join the lines. The following sed command does it on Unix.

unzip -c example.jar META-INF/MANIFEST.MF |
sed -n '/^Class-Path: /,/^[^ ]/{s/^\(Class-Path:\)\? //;H};${g;s/\r\?\n//g;s/ /:/g;p}'

The command replaces the spaces in the class path of a manifest file with colons. The result can be used directly as an argument to a -classpath option.

Freitag, 6. Juni 2014

Using Saxon-HE as a XPath command line tool

Subversion can print the repository information in XML format.

svn info --xml

This makes it easy to extract the interesting parts in a Shell script, if an XPath tool is available. Newer versions of xmllint provide such a functionality. On those Systems which do not provide any suitable xmllint but provide a Java RE it is possible to use Saxon-HE. But the command line options are not very intuitive. The following example shows how to get the URL for the repository root.

saxon () { java -cp Saxon-HE-9.5.1-5.jar net.sf.saxon.Query "$@" ; }
xpath () { saxon '!method=text' -s:- -qs:"$1" ; }
svn info --xml | xpath '/info/entry/repository/root/text()'

The Saxon-HE JAR can be found in the Maven repository.

Donnerstag, 5. Juni 2014

Configure Emacs 24.3 on Red Hat Enterprise Linux 5.10

The following packages are required on Red Hat 5 to configure Emacs 24.3.

yum install gnome-desktop-devel libXpm-devel libjpeg-devel giflib-devel libtiff-devel ncurses-devel librsvg2-devel libselinux-devel

Emacs 24.3 requires GNU TLS 2.6.6, which is not available on Red Hat 5. Installing gnutls-devel does not help, because only version 1.4 of GNU TLS will be installed.