LiquiBase Extension Contest 2009

To reduce myself to the important I will simply repeat the important phrases from the liquibase homepage:

“LiquiBase is an open source (LGPL), database-independent library for tracking, managing and applying database changes.

Learn more about liquibase with a video or with the quickstart guide. There exist ant- and maven-plugins to apply liquid changes to your database.

“Now is your chance to extend the capabilities of LiquiBase and possibly win a great prize!

The LiquiBase Extension Contest 2009 ends on September 30, 2009.”

Read more about the contest here!

Convert Zaurus Addressbook xml to csv (e.g. for Thunderbird)

Some years ago my father gave me a Zaurus – a PDA-like-device. But in the mean time the battery losts its energy and the only usecase for me was the addressbook. Although the Zaurus was a nice PDA, where you can programm Java GUI’s (via awt, e.g. here or here) and other nice things.

I used the csv file to import my address-data into Thunderbird: in the menu bar under Extras->Import you can choose the csv format for the addressbook and verify every entry in the csv. It will not overwrite anything, because it will create an entirely fresh addressbook named like the csv file, so feel free to try it out and develop it to your needs. If you have another usecase for this source please let me know in the comments.

But today here is the Java source code, so that you can convert the addressbook.xml to an csv and be independent from Zaurus (and its battery life):

package zaurus2thunderbird;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author Peter Karich, peat_hal 'at' users 'dot' sourceforge 'dot' net
 */
public class Main {

    public static void main(String[] args) throws Exception {
        new Main().start();
    }

    public void start() throws Exception {
        // Create a factory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // Use the factory to create a builder
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.parse("addressbook.xml");

        // Get a list of all contacts in the document
        NodeList list = doc.getElementsByTagName("Contact");

        // maps oldKeys to newKeys, but store order of how elements are added
        Map<String, String> map = new LinkedHashMap<String, String>() {

            {
                put("FirstName", "Vorname");
                put("LastName", "Nachname");
                put("MiddleName", "Spitzname");

                put("BusinessStreet", "Dienstlich: Adresse");
                put("BusinessState", "Dienstlich: Adresse 2");
                put("BusinessCity", "Dienstlich: Stadt");
                put("BusinessPhone", "Tel. dienstlich");
                put("BusinessFax", "Fax-Nummer");
                put("BusinessMobile", "Mobil-Tel.-Nr.");

                put("HomeStreet", "Privat: Adresse");
                put("HomeState", "Privat: Adresse 2");
                put("HomeCity", "Privat: Stadt");
                put("HomePhone", "Tel. privat");
                put("HomeFax", "Fax-Nummer");
                put("HomeMobile", "Mobil-Tel.-Nr.");

                put("JobTitle", "Arbeitstitel");
                put("Company", "Organisation");
                put("Department", "Abteilung");

                put("Anniversary", "Geburtstag");
                put("Birthday", "Geburtstag");

                put("DefaultEmail", "Primäre E-Mail");
                put("Emails", "Sekundäre E-Mail");

                put("Categories", "Notizen");

                put("FileAs", "");
                put("rid", "");
                put("Gender", "");
                put("Uid", "");
                put("rinfo", "");
            }
        };

        // maps newKeys to values
        LinkedHashMap<String, String> oneLine = new LinkedHashMap<String, String>();
        for (String newKey : map.values()) {
            oneLine.put(newKey, "");
        }

        // print csv header
        printLine(map.values());

        Set<String> missing = new HashSet<String>();
        for (int i = 0; i < list.getLength(); i++) {
            Map<String, String> cloneForNewLine = (Map<String, String>) oneLine.clone();
            NamedNodeMap attr = list.item(i).getAttributes();
            for (Entry<String, String> entry : map.entrySet()) {
                Node newAttr = attr.getNamedItem(entry.getKey());
                if (newAttr != null)
                    cloneForNewLine.put(entry.getValue(), newAttr.getTextContent());
            }

            // print csv values
            printLine(cloneForNewLine.values());

            // add items if an old attribute does not exist in map
            for (int j = 0; j < attr.getLength(); j++) {
                String newAttr = map.get(attr.item(j).getNodeName());
                if (newAttr == null)
                    missing.add(attr.item(j).getNodeName());
            }
        }

        System.out.println("\nMissing new mappings for old attributes:");
        printLine(missing);
    }

    public void printLine(Collection<String> items) {

        for (String m : items) {
            System.out.print(m + ",");
        }
        System.out.println();
    }
}

A Pagination-enabled List in Swing with Hessian

In an ealier post I documented how to set up a maven project to use port 80 for client-server-communication in a Java Swing project.

Today I want to show how you could implement a list which shows ‘all’ objects of one entity. It is common that there exists thousand or more objects for one entity in a database, so pagination is required. I know that JList and JTable could handle very large result sets easily, but the bandwith would be the limitating factor and loading all the objects into memory is often not required (and not good …).

I will use the simplest Swing solution with some pagination buttons, although it would be a lot nicer to have the pagination with a custom vertical JScrollBar-implementation which loads the objects while scrolling (‘on demand’). But this will be either a task for my readers or for myself at a later time. First we can take a look at the resulting (primitive) GUI:

paginationlist

The interface for the data access object was quickly created:

public interface RemoteDao<T> {
   List<T> getAll(int index, int items, String query);
   int count(String query);
}

… the implementation, too (but for this see the source in the provided project). You can simply replace the existing fake-implementation with a RemoteHibernateDao or sth. like this, if you like.

The communication follows this picture:

dao-hessian

To try this maven project: start PaginationServlet under the paginationlist package and then the PaginationClient. The Swing gui should pop up and you could hit enter after a search string like ‘person’ or ’18’ in the textfield at the top. Now try to paginate through the results with the provided buttons at the bottom.

The final goal for me (at a later time) will be to replace the left ‘Available’-JList in a ShuttleList (from Spring rich client project) with my PaginationList. For you information: with a normal ShuttleList one could drop one or more items from ‘available’ list to ‘choosen’ with the buttons in the middle (they have nothing to do with pagination!). Here a normal shuttle list is shown:

shuttlelist-orig

So, now have fun with my small Swing example and feel free to provide feedback or ask questions if you need help while maven or sth. else!

News on an old Java Wisdom

I am fully aware of the brace initialisation of anonymous classes, but I didn’t know that this can help to improve readability of Java programs until I read this nice post:

Map<Integer, String> map = new HashMap<Integer, String>() {{
 put(1, "one");
 put(2, "two");
 put(3, "three");
 put(4, "four");
 put(5, "five");
}};

The author said that this could help in GUI programming:

JFrame frame = new JFrame() {{
   setDefaultCloseOperation(EXIT_ON_CLOSE);  
   add(new JLabel("Hello, World!"));
   pack();
}};

Nice !

Lasst uns unseren Kindern Linux beibringen, anstatt sie von Microsoft-Produkten abhängig zu machen

Die Grünen werden von vielen als die Ökopartei belächelt oder sogar beschimpft. Doch mich überzeugen viele Ihrer Handlungen und Meinungen. (Nicht so 100% allerdings die Kandidaten, aber man wählt ja keine Personen sondern eine Partei, oder? 😉 )

Ein Artikel bei Heise.de fand ich wieder einmal recht erhellend. Auch die Idee der Kulturflatrate finde ich gut, obwohl damit wohl Änderungen des Urheberrechts verbunden sind. Bei dem Artikel stach besonders die Aussage von Herrn Spitz hervor:

“Lasst uns unseren Kindern Linux beibringen, anstatt sie von Microsoft-Produkten abhängig zu machen”

Ein wenig zweifelhaft ist dagegen folgende pauschale Aussage im Programm der Grünen:

“Wir unterstützen die Anwendung von Open Source, Freier
Software, Freien Funknetzwerken, Offenen Formaten und
innovativen Lizenzen. Sie müssen stärker als bisher Einzug in
Bildungseinrichtungen und die öffentliche Verwaltung finden,
weil sie kostengünstiger, energiesparender und grundsätzlich
sicherer sind”

Ich glaube nicht das zur Zeit z.B. Linuxlaptops energiesparender sein können, als solche mit extrem angepassten MS-Windows-Sytemen.

Okay, es gibt mind. eine Ausnahme, aber generell vertrauen Hardwarehersteller lieber auf einen Softwaregiganten und bekommen auch eine gewisse Garantie von diesem anstatt auf ein ebenbürtiges, preiswertes Betriebssystem zu setzen wo nur kleinere bis keinere Firmen dahinter stehen.

Allerdings untestütze ich persönlich auch Open Source Software – vorallem im Bildungssektor. Ganz nach dem Motto:

Freiheit für unsere Kinder!

Test All Browsers Under Almost One Operating System

For professional website development it is necessary to test the application under the major browsers. I will not decide which browsers the major ones are. Instead you can “install” all browser at one time under the latest Ubuntu:

  1. If you have Ubuntu you already have access to Firefox, Konqueror and Opera
  2. Now install VirtualBox and  a Windows of you choice (installation of Novell Silverlight fails under my ubuntu version :-()
    1. Now you can install Microsoft Silverlight under Windows
    2. Go to xenocode then you can install InternetExplorer 6,7 and 8. Plus the Mac Os browser Safari
      The cool thing about xenocode is that you can have several different versions of IE installed (and even all the others)

View the results in the picture below:

browsers

From left to right: Firefox 3, Opera 9.6, Konqueror 4.2, IE 7, IE 8 and Safari 3

So, even if the side is only a static one like my timefinder side not all browser display it correctly (konqueror fails …)

Have fun to try your application under all the funky browsers out there …