Index: applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/CzechAddressPlugin.java
===================================================================
--- applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/CzechAddressPlugin.java	(revision 15649)
+++ applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/CzechAddressPlugin.java	(revision 15763)
@@ -69,5 +69,4 @@
                     continue;
 
-                System.err.println(name);
                 Logger.getLogger(name).setLevel(Level.FINE);
                 Logger.getLogger(name).addHandler(fileHandler);
@@ -83,4 +82,10 @@
     public CzechAddressPlugin() {
 
+        /*boolean x;
+        x = StringUtils.matchAbbrev("Ahoj lidi", "Ahoj lidi");
+        System.out.println(x ? "Match" : "Differ");
+        x = StringUtils.matchAbbrev("Bož. Němcové", "Boženy Němca.");
+        System.out.println(x ? "Match" : "Differ");*/
+
         addStatusListener(this);
         
@@ -102,5 +107,6 @@
 
         // Fill the database in separate thread.
-        Thread t = new Thread() { @Override public void run() {
+        Thread t = new Thread("CzechAddress: DB preload") {
+          @Override public void run() {
             super.run();
             try {
Index: applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/StringUtils.java
===================================================================
--- applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/StringUtils.java	(revision 15649)
+++ applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/StringUtils.java	(revision 15763)
@@ -2,4 +2,6 @@
 
 import java.text.Normalizer;
+import java.util.ArrayList;
+import java.util.List;
 import org.openstreetmap.josm.data.coor.LatLon;
 
@@ -57,27 +59,52 @@
      */
     public static boolean matchAbbrev(String s1, String s2) {
-        String[] parts1 = anglicize(s1).split(" +");
-        String[] parts2 = anglicize(s2).split(" +");
 
-        if (parts1.length != parts2.length)
+        s1 = anglicize(s1);
+        s2 = anglicize(s2);
+        List<Integer> beg1 = new ArrayList<Integer>(4);
+        List<Integer> beg2 = new ArrayList<Integer>(4);
+
+        char lastChar = ' ';
+        for (int i=0; i<s1.length(); i++) {
+            if (s1.charAt(i) != ' ' && lastChar == ' ')
+                beg1.add(i);
+            lastChar = s1.charAt(i);
+        }
+
+        lastChar = ' ';
+        for (int i=0; i<s2.length(); i++) {
+            if (s2.charAt(i) != ' ' && lastChar == ' ')
+                beg2.add(i);
+            lastChar = s2.charAt(i);
+        }
+
+        if (beg1.size() != beg2.size())
             return false;
 
-        for (int i=0; i<parts1.length; i++) {
-            String part1 = parts1[i];
-            String part2 = parts2[i];
+        for (int i=0; i<beg1.size(); i++) {
 
-            if (part1.charAt(part1.length()-1) == '.')
-                part1 = part1.substring(0, part1.length()-1);
+            int pos1 = beg1.get(i);
+            int pos2 = beg2.get(i);
 
-            if (part2.charAt(part2.length()-1) == '.')
-                part2 = part2.substring(0, part2.length()-1);
+            boolean doContinue = false;
+            while (pos1 < s1.length() && pos2 < s2.length()) {
+                if (s1.charAt(pos1) == '.' || s2.charAt(pos2) == '.')
+                    {doContinue = true; break;}
+                if (s1.charAt(pos1) == ' ' && s2.charAt(pos2) == ' ')
+                     {doContinue = true; break;}
 
-            int minLen = Math.min(part1.length(), part2.length());
-            part1 = part1.substring(0, minLen).toUpperCase();
-            part2 = part2.substring(0, minLen).toUpperCase();
+                if (Character.toUpperCase(s1.charAt(pos1)) !=
+                    Character.toUpperCase(s2.charAt(pos2)))
+                    return false;
 
-            if (!part1.equals(part2))
+                pos1++;
+                pos2++;
+            }
+            if (doContinue) continue;
+
+            if (pos1 >= s1.length() ^ pos2 >= s2.length())
                 return false;
         }
+        
         return true;
     }
@@ -93,12 +120,11 @@
      */
     public static String capitalize(String s) {
+        if (s == null) return null;
 
-        if (s == null)
-            return s;
-
-        String result = "";
-
+        char[] charr = s.toCharArray();
         char last = ' ';
-        for (char ch : s.toCharArray()) {
+        char ch = last;
+        for (int i=0; i<charr.length; i++) {
+            ch = charr[i];
             if ((last >= 'a') && (last <= 'ž') ||
                 (last >= 'A') && (last <= 'Ž'))
@@ -107,12 +133,12 @@
                 ch = Character.toTitleCase(ch);
 
-            last = ch;
-            result = result + ch;
+            last = charr[i] = ch;
         }
 
         String[] noCapitalize = { "Nad", "Pod", "U", "Na", "Z" };
+        String result = String.valueOf(charr);
+
         for (String noc : noCapitalize)
             result = result.replaceAll(" "+noc+" ", " "+noc.toLowerCase()+" ");
-
         return result;
     }
@@ -129,5 +155,5 @@
     public static String anglicize(String str) {
         String strNFD = Normalizer.normalize(str, Normalizer.Form.NFD);
-        StringBuilder sb = new StringBuilder();
+        StringBuilder sb = new StringBuilder(str.length());
         for (char ch : strNFD.toCharArray()) {
             if (Character.getType(ch) != Character.NON_SPACING_MARK) {
Index: applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/addressdatabase/ElementWithHouses.java
===================================================================
--- applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/addressdatabase/ElementWithHouses.java	(revision 15649)
+++ applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/addressdatabase/ElementWithHouses.java	(revision 15763)
@@ -18,5 +18,5 @@
     }
 
-    protected List<House> houses = new ArrayList<House>();
+    protected List<House> houses = new ArrayList<House>(30);
 
     /**
Index: applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/intelligence/Reasoner.java
===================================================================
--- applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/intelligence/Reasoner.java	(revision 15649)
+++ applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/intelligence/Reasoner.java	(revision 15763)
@@ -312,4 +312,9 @@
      */
     private int getQ(OsmPrimitive prim, AddressElement elem) {
+
+        // TODO: This is a workaround. We should not be here at all.
+        if (elemMatchIndex.get(elem) == null) return MATCH_NOMATCH;
+        if (primMatchIndex.get(prim) == null) return MATCH_NOMATCH;
+
         assert primMatchIndex.get(prim).get(elem)
             == elemMatchIndex.get(elem).get(prim);
@@ -466,4 +471,7 @@
     public Set<AddressElement> getCandidates(OsmPrimitive prim) {
 
+        Set<AddressElement> result = new HashSet<AddressElement>();
+        if (primMatchIndex.get(prim) == null) return result;
+
         int best = MATCH_NOMATCH;
         for (AddressElement elem : primMatchIndex.get(prim).keySet()) {
@@ -473,6 +481,4 @@
         }
 
-        Set<AddressElement> result = new HashSet<AddressElement>();
-
         for (AddressElement elem : primMatchIndex.get(prim).keySet()) {
             int cand = primMatchIndex.get(prim).get(elem);
@@ -499,4 +505,7 @@
     public Set<OsmPrimitive> getCandidates(AddressElement elem) {
 
+        Set<OsmPrimitive> result = new HashSet<OsmPrimitive>();
+        if (elemMatchIndex.get(elem) == null) return result;
+
         int best = MATCH_NOMATCH;
         for (OsmPrimitive prim : elemMatchIndex.get(elem).keySet()) {
@@ -505,6 +514,4 @@
                 best = cand;
         }
-
-        Set<OsmPrimitive> result = new HashSet<OsmPrimitive>();
         
         for (OsmPrimitive prim : elemMatchIndex.get(elem).keySet()) {
@@ -539,4 +546,5 @@
 
         Map<AddressElement, Integer> matches = primMatchIndex.get(prim);
+        if (matches == null) return null;
         AddressElement bestE = null;
         int bestQ = MATCH_NOMATCH;
@@ -578,4 +586,5 @@
 
         Map<OsmPrimitive, Integer> matches = elemMatchIndex.get(elem);
+        if (matches == null) return null;
         OsmPrimitive bestE = null;
         int bestQ = MATCH_NOMATCH;
Index: applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/parser/MvcrParser.java
===================================================================
--- applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/parser/MvcrParser.java	(revision 15649)
+++ applications/editors/josm/plugins/czechaddress/src/org/openstreetmap/josm/plugins/czechaddress/parser/MvcrParser.java	(revision 15763)
@@ -40,4 +40,89 @@
                                 Attributes attributes) throws SAXException {
 
+        // ========== PARSING HOUSE ========== //
+        if (name.equals("a")) {
+
+            String cp = attributes.getValue("p");
+            String co = attributes.getValue("o");
+            if ((cp == null) && (co == null))
+                return;
+
+            ElementWithHouses    topElem = curStreet;
+            if (topElem == null) topElem = curSuburb;
+            if (topElem == null) topElem = curViToCi;
+            if (topElem == null) topElem = curRegion;
+
+            topElem.addHouse(new House(cp, co));
+            return;
+        }
+        
+        // ========== PARSING STREET ========== //
+        if (name.equals("ulice")) {
+            String nazev = attributes.getValue("nazev");
+
+            // If the street filter is on, apply it!
+            if (filStreet != null && !nazev.equals(filStreet)) {
+                curStreet = null;
+                return;
+            }
+
+            ElementWithStreets   topElem = curSuburb;
+            if (topElem == null) topElem = curViToCi;
+            if (topElem == null) topElem = curRegion;
+
+            //curStreet = topElem.findStreet(attributes.getValue("nazev"));
+            //if (curStreet == null) {
+                curStreet = new Street(capitalize(nazev));
+            //    System.out.println("Parser: " + curStreet);
+                topElem.addStreet(curStreet);
+            //}
+            return;
+        }
+
+        // ========== PARSING SUBURB ========== //
+        if (name.equals("cast")) {
+            if (curViToCi == null)
+                return;
+
+            String nazev = attributes.getValue("nazev");
+
+            // If the suburb filter is on, apply it!
+            if (filSuburb != null && !nazev.equals(filSuburb)) {
+                curSuburb = null;
+                curStreet = null;
+                return;
+            }
+
+            //curSuburb = curViToCi.findSuburb(attributes.getValue("nazev"));
+            //if (curSuburb == null) {
+                curSuburb = new Suburb(capitalize(nazev));
+            //    System.out.println("Parser: " + curSuburb);
+                curViToCi.addSuburb(curSuburb);
+            //}
+            return;
+        }
+
+        // ========== PARSING ViToCi ========== //
+        if (name.equals("obec")) {
+
+            String nazev = attributes.getValue("nazev");
+
+            // If the viToCi filter is on, apply it!
+            if (filViToCi != null && !nazev.equals(filViToCi)) {
+                curViToCi = null;
+                curSuburb = null;
+                curStreet = null;
+                return;
+            }
+
+            //curViToCi = curRegion.findViToCi(attributes.getValue("nazev"));
+            //if (curViToCi == null) {
+                curViToCi = new ViToCi(capitalize(nazev));
+            //    System.out.println("Parser: " + curViToCi);
+                curRegion.addViToCi(curViToCi);
+            //}
+            return;
+        }
+
         // ========== PARSING REGION ========== //
         if (name.equals("oblast")) {
@@ -65,85 +150,5 @@
                 target.regions.add(curRegion);
             //}
-        }
-
-        // Everything must belong to some region
-        if (curRegion == null)
-            return;
-
-        // ========== PARSING ViToCi ========== //
-        if (name.equals("obec")) {
-
-            // If the viToCi filter is on, apply it!
-            if (filViToCi != null && !attributes.getValue("nazev").equals(filViToCi)) {
-                curViToCi = null;
-                curSuburb = null;
-                curStreet = null;
-                return;
-            }
-
-            //curViToCi = curRegion.findViToCi(attributes.getValue("nazev"));
-            //if (curViToCi == null) {
-                curViToCi = new ViToCi(capitalize(attributes.getValue("nazev")));
-            //    System.out.println("Parser: " + curViToCi);
-                curRegion.addViToCi(curViToCi);
-            //}
-        }
-
-        // ========== PARSING SUBURB ========== //
-        if (name.equals("cast")) {
-            if (curViToCi == null)
-                return;
-
-            // If the suburb filter is on, apply it!
-            if (filSuburb != null && !attributes.getValue("nazev").equals(filSuburb)) {
-                curSuburb = null;
-                curStreet = null;
-                return;
-            }
-
-            //curSuburb = curViToCi.findSuburb(attributes.getValue("nazev"));
-            //if (curSuburb == null) {
-                curSuburb = new Suburb(capitalize(attributes.getValue("nazev")));
-            //    System.out.println("Parser: " + curSuburb);
-                curViToCi.addSuburb(curSuburb);
-            //}
-        }
-
-        // ========== PARSING STREET ========== //
-        if (name.equals("ulice")) {
-
-            // If the street filter is on, apply it!
-            if (filStreet != null && !attributes.getValue("nazev").equals(filStreet)) {
-                curStreet = null;
-                return;
-            }
-
-            ElementWithStreets   topElem = curSuburb;
-            if (topElem == null) topElem = curViToCi;
-            if (topElem == null) topElem = curRegion;
-
-            //curStreet = topElem.findStreet(attributes.getValue("nazev"));
-            //if (curStreet == null) {
-                curStreet = new Street(capitalize(attributes.getValue("nazev")));
-            //    System.out.println("Parser: " + curStreet);
-                topElem.addStreet(curStreet);
-            //}
-
-        }
-
-        // ========== PARSING HOUSE ========== //
-        if (name.equals("a")) {
-
-            if (   (attributes.getValue("p") == null)
-                && (attributes.getValue("o") == null))
-                return;
-
-            ElementWithHouses    topElem = curStreet;
-            if (topElem == null) topElem = curSuburb;
-            if (topElem == null) topElem = curViToCi;
-            if (topElem == null) topElem = curRegion;
-
-            topElem.addHouse(new House(attributes.getValue("p"),
-                                       attributes.getValue("o")));
+            return;
         }
     }
