Index: /applications/editors/josm/plugins/czechaddress/build.xml
===================================================================
--- /applications/editors/josm/plugins/czechaddress/build.xml	(revision 15762)
+++ /applications/editors/josm/plugins/czechaddress/build.xml	(revision 15763)
@@ -1,34 +1,71 @@
 <project name="czechaddress" default="dist" basedir=".">
     <property name="josm"                   location="../../core/dist/josm-custom.jar"/>
+    <property name="josm.classpath"         value="../../core/build"/>
     <property name="plugin.dist.dir"        value="../../dist"/>
     <property name="plugin.build.dir"       value="build"/>
     <property name="plugin.jar"             value="${plugin.dist.dir}/${ant.project.name}.jar"/>
+    <property name="plugin.manifest"        value="${plugin.build.dir}/org/openstreetmap/josm/plugins/czechaddress/MANIFEST.MF"/>
     <property name="ant.build.javac.target" value="1.5"/>
+
+
+
+    <target name="clean" description="Removes all build files and the plugins's jar">
+        <delete dir="${plugin.build.dir}"/>
+        <delete file="${plugin.jar}"/>
+    </target>
+
+
+
     <target name="init">
         <mkdir dir="${plugin.build.dir}"/>
+        <mkdir dir="${plugin.dist.dir}"/>
     </target>
-    <target name="compile" depends="init">
-        <echo message="creating ${plugin.jar}"/>
-        <javac srcdir="src" classpath="${josm}" debug="true" destdir="${plugin.build.dir}">
+
+
+
+    <target name="compile" depends="init"
+            description="Compile the plugin and make it ready for running">
+
+        <fail message="You must firstly compile the JOSM itself"><condition><not>
+            <resourcecount count="1" when="ge">
+                <fileset id="josm" dir="${josm.classpath}"/>
+            </resourcecount>
+        </not></condition></fail>
+
+        <javac srcdir="src"
+               classpath="${josm}"
+               debug="true"
+               destdir="${plugin.build.dir}">
             <compilerarg value="-Xlint:deprecation"/>
             <compilerarg value="-Xlint:unchecked"/>
         </javac>
-    </target>
-    <target name="dist" depends="compile,revision">
+
         <copy todir="${plugin.build.dir}/images">
             <fileset dir="images"/>
         </copy>
-        <jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
-          <manifest>
-                <attribute name="Author" value="Radomír Černoch"/>
-                <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.czechaddress.CzechAddressPlugin"/>
-                <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
-                <attribute name="Plugin-Description" value="Creating and handling address nodes and buildings within Czech Republic."/>
-                <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/JOSM/Plugins/SlippyMap"/>
-                <attribute name="Plugin-Mainversion" value="1607"/>
-                <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
-            </manifest>
-        </jar>
+
+        <manifest file="${plugin.manifest}">
+            <attribute name="Author" value="Radomír Černoch"/>
+            <attribute name="Plugin-Class" value="org.openstreetmap.josm.plugins.czechaddress.CzechAddressPlugin"/>
+            <attribute name="Plugin-Date" value="${version.entry.commit.date}"/>
+            <attribute name="Plugin-Description" value="Creating and handling address nodes and buildings within Czech Republic."/>
+            <attribute name="Plugin-Link" value="http://wiki.openstreetmap.org/index.php/Cz:JOSM/Plugins/CzechAddress"/>
+            <attribute name="Plugin-Mainversion" value="1607"/>
+            <!--<attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>-->
+            <attribute name="Plugin-Version" value="0.2.2"/>
+        </manifest>
+
     </target>
+
+
+
+    <target name="dist" depends="compile">
+        <jar destfile="${plugin.jar}"
+             basedir ="${plugin.build.dir}"
+             manifest="${plugin.build.dir}/org/openstreetmap/josm/plugins/czechaddress/MANIFEST.MF"/>
+    </target>
+
+
+
     <target name="revision">
         <exec append="false" output="REVISION" executable="svn" failifexecutionfails="false">
@@ -41,16 +78,60 @@
         <delete file="REVISION"/>
     </target>
-    <target name="clean">
-        <delete dir="${plugin.build.dir}"/>
-        <delete file="${plugin.jar}"/>
-    </target>
+
+
+
     <target name="install" depends="dist">
         <property environment="env"/>
-        <condition property="josm.plugins.dir" value="${env.APPDATA}/JOSM/plugins" else="${user.home}/.josm/plugins">
-            <and>
-                <os family="windows"/>
-            </and>
+        <condition property="josm.plugins.dir"
+                   value="${env.APPDATA}/JOSM/plugins"
+                   else="${user.home}/.josm/plugins">
+            <and><os family="windows"/></and>
         </condition>
         <copy file="${plugin.jar}" todir="${josm.plugins.dir}"/>
     </target>
+
+
+
+    <target name="run" depends="compile">
+        <fail message="You must firstly compile the JOSM itself"><condition><not>
+            <resourcecount count="1" when="gt">
+                <fileset id="josm" dir="${josm.classpath}" includes="*"/>
+            </resourcecount>
+        </not></condition></fail>
+
+        <java classname="JOSM" fork="true">
+            <jvmarg value="-Xmx1024m"/>
+            <jvmarg value="-Xdebug"/>
+            <jvmarg value="-ea"/>
+            <classpath>
+                <pathelement location="${plugin.build.dir}"/>
+                <pathelement path="${java.class.path}"/>
+            </classpath>
+            <classpath>
+                <pathelement location="${josm}"/>
+                <pathelement path="${java.class.path}"/>
+            </classpath>
+        </java>
+    </target>
+
+
+
+    <target name="profile" depends="compile" description="Profile CzechAddress">
+        <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail>
+        <nbprofiledirect>
+            <classpath><pathelement location="${plugin.build.dir}"/></classpath>
+        </nbprofiledirect>
+        <java classname="JOSM" fork="true">
+            <jvmarg value="${profiler.info.jvmargs.agent}"/>
+            <jvmarg value="-Xmx1024m"/>
+            <classpath>
+                <pathelement location="${plugin.build.dir}"/>
+                <pathelement path="${java.class.path}"/>
+            </classpath>
+            <classpath>
+                <pathelement location="${josm}"/>
+                <pathelement path="${java.class.path}"/>
+            </classpath>
+        </java>
+    </target>
 </project>
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 15762)
+++ /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 15762)
+++ /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 15762)
+++ /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 15762)
+++ /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 15762)
+++ /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;
         }
     }
