[Schmitzm-commits] r1626 - in trunk: . schmitzm-adresses schmitzm-adresses/src schmitzm-adresses/src/main schmitzm-adresses/src/main/java schmitzm-adresses/src/main/java/de schmitzm-adresses/src/main/java/de/schmitzm schmitzm-adresses/src/main/java/de/schmitzm/adresses schmitzm-adresses/src/main/resources schmitzm-adresses/src/test schmitzm-adresses/src/test/java schmitzm-adresses/src/test/java/de schmitzm-adresses/src/test/java/de/schmitzm schmitzm-adresses/src/test/java/de/schmitzm/adresses
scm-commit@wald.intevation.org
scm-commit at wald.intevation.org
Tue Jul 12 21:53:04 CEST 2011
Author: keeb
Date: 2011-07-12 21:53:03 +0200 (Tue, 12 Jul 2011)
New Revision: 1626
Added:
trunk/schmitzm-adresses/
trunk/schmitzm-adresses/pom.xml
trunk/schmitzm-adresses/src/
trunk/schmitzm-adresses/src/main/
trunk/schmitzm-adresses/src/main/java/
trunk/schmitzm-adresses/src/main/java/de/
trunk/schmitzm-adresses/src/main/java/de/schmitzm/
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/AddrStringUtil.java
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/Ebene.java
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormResult.java
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormRule.java
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/RuleRegistry.java
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSNormRule.java
trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSRulesParser.java
trunk/schmitzm-adresses/src/main/resources/
trunk/schmitzm-adresses/src/main/resources/rules.xls
trunk/schmitzm-adresses/src/main/resources/rulesHn.xls
trunk/schmitzm-adresses/src/main/resources/rulesZusatz.xls
trunk/schmitzm-adresses/src/test/
trunk/schmitzm-adresses/src/test/java/
trunk/schmitzm-adresses/src/test/java/de/
trunk/schmitzm-adresses/src/test/java/de/schmitzm/
trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/
trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/AddrStringUtilTest.java
trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/RuleRegistryTest.java
Modified:
trunk/pom.xml
Log:
New Project schmitzm-adresses deals with german street adresses
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/pom.xml 2011-07-12 19:53:03 UTC (rev 1626)
@@ -16,6 +16,7 @@
<module>schmitzm-gt</module>
<module>schmitzm-jfree</module>
<module>schmitzm-jfree-gt</module>
+ <module>schmitzm-adresses</module>
</modules>
<distributionManagement>
Added: trunk/schmitzm-adresses/pom.xml
===================================================================
--- trunk/schmitzm-adresses/pom.xml 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/pom.xml 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,43 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>de.schmitzm</groupId>
+ <artifactId>schmitzm-adresses</artifactId>
+ <version>2.6-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <parent>
+ <groupId>de.schmitzm</groupId>
+ <artifactId>schmitzm-parent</artifactId>
+ <version>2.6-SNAPSHOT</version>
+ <relativePath>../schmitzm-parent/pom.xml</relativePath>
+ </parent>
+
+ <name>schmitzm-adresses</name>
+ <url>http://maven.apache.org</url>
+ <dependencies>
+ <dependency>
+ <groupId>net.sourceforge.jexcelapi</groupId>
+ <artifactId>jxl</artifactId>
+ <version>2.6.12</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>de.schmitzm</groupId>
+ <artifactId>schmitzm-core</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>de.schmitzm</groupId>
+ <artifactId>schmitzm-core</artifactId>
+ <version>${project.version}</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+</project>
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/AddrStringUtil.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/AddrStringUtil.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/AddrStringUtil.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,446 @@
+package de.schmitzm.adresses;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+/**
+ * Diese Klasse bietete nützliche Methoden zur Bearbeitung von
+ * Addressschreibweisen. Zur Zeit werden nur Strings mit Strasse [Hn] [Zusatz]
+ * behandelt.<br/>
+ * Es werden Methoden zum Aufteilen (Splitten) von String angeboten, um Strasse
+ * +Hn + Zusatz in drei Strings zu zerlegen. Weiterhin existieren Methoden um
+ * die Schreibweisen von Straßen, Hausnummern un Zusätzen zu normalisieren.
+ * Diese normalisierten Strings können dann zum abgeleichen von
+ * Addressinformationen verwendet werden.<br/>
+ * Ersetzungsregeln für die Normalisierung werden in drei Excel-Dateien
+ * verwaltet.<br/>
+ */
+public class AddrStringUtil {
+ static final private Logger log = Logger.getLogger(AddrStringUtil.class);
+
+ final static Pattern REGEX_splitHnZusatz = Pattern
+ .compile("(\\d+)\\s*(.*?)\\s*$");
+ final static Pattern REGEX_splitFullString = Pattern
+ .compile("^(.*\\d+\\.+[^\\d]*|[^\\d,]+)"
+ + "\\s*"
+ + "(\\d+|\\d+\\s*-\\s*\\d+|\\d+\\s*[,\\s*\\d+]+|\\d+\\s*[&]\\s*\\d+|\\d+\\s*bis\\s*\\d+|\\d+\\s*\\\\\\s*\\d+|\\d+\\s*[/\\s*\\d+]+)"
+ + "\\s*" + "([^\\d].*[0][\\d]+|[^\\d]*?)" + "\\s*$");
+
+ final static Pattern REGEX_hnZusatzBereich2aBis2f = Pattern
+ .compile("(\\d+)([^\\d]?)\\s*(-|bis)\\s*(\\d*)([^\\d]?).*");
+ // final static Pattern REGEX_hnBereich = Pattern
+ // .compile("(\\d+)([^\\d]?)(\\s*)(-|bis)(\\s*)(\\w+).*");
+
+ final static Pattern REGEX_hnListe = Pattern
+ .compile("(\\d+)([^\\d]+)(\\d+).*");
+
+ final static Pattern REGEX_hnEinzeln = Pattern.compile("(\\d+)(.*)");
+
+ /**
+ * Normalisiert die Schreibweise eines Straßennamens, z.B.
+ * "Dr.-Vogeler-Str." -> "drvogelerstrasse"
+ */
+ public static final NormResult normalizeStrasse(final String strasse) {
+ return normalize(RuleRegistry.getRulesStr(), strasse);
+ }
+
+ /**
+ * Normalisiert die Schreibweise einer Hausnummer, z.B. " 5 " -> "5"
+ */
+ public static final NormResult normalizeHn(final String hn) {
+ return normalize(RuleRegistry.getRulesHn(), hn);
+ }
+
+ /**
+ * Normalisiert die Schreibweise eines Hn-Zusatzes, z.B. " A " -> "a"
+ */
+ public static final NormResult normalizeZusatz(final String zusatz) {
+ return normalize(RuleRegistry.getRulesZusatz(), zusatz);
+ }
+
+ /**
+ * Applies the given "Rules"/ Transformations to the given String.
+ */
+ private static NormResult normalize(final List<NormRule> rules,
+ final String string) {
+
+ if (string == null)
+ return new NormResult(null);
+
+ final NormResult nRes = new NormResult(string);
+
+ String lastResult = "";
+ while (!lastResult.equals(nRes.getResultStr())) {
+ lastResult = nRes.getResultStr();
+ for (final NormRule nRule : rules) {
+ nRule.applyTo(nRes);
+ }
+ }
+
+ return nRes;
+ }
+
+ /**
+ * Diese Methode teilt einen String, der Hausnummer und einen optionalen
+ * Zusatz enhält, in zwei Strings.
+ *
+ * @param origHn
+ * darf <code>null</code> sein. Kann nur die HN oder HN+ZUSATZ
+ * enthalten.
+ * @param origZusatz
+ * darf <code>null</code> sein.
+ * @return Zwei Strings, zuerst ein String mit der Hausnummer (oder null),
+ * und als zweites ein String mit dem Zusatz (oder null).
+ */
+ public static String[] splitHn(final String origHn, final String origZusatz) {
+ if (origHn == null)
+ return new String[] { null, origZusatz };
+
+ String hn = null;
+ String zusatz = null;
+
+ final Matcher m = REGEX_splitHnZusatz.matcher(origHn);
+ final boolean found = m.find();
+
+ if (!found) {
+ return new String[] { null, origZusatz };
+ }
+ try {
+ hn = m.group(1);
+ zusatz = m.group(2);
+ } catch (final Exception e) {
+ log.debug(e);
+ }
+
+ if (zusatz == null || zusatz.isEmpty()) {
+ zusatz = origZusatz;
+ } else if (origZusatz != null) {
+ zusatz += " " + origZusatz;
+ }
+
+ if (StringUtils.isEmpty(hn))
+ hn = null;
+ if (StringUtils.isEmpty(zusatz))
+ zusatz = null;
+
+ return new String[] { hn, zusatz };
+ }
+
+ /**
+ * Diese Methode teilt einen String, der Hausnummer und einen optionalen
+ * Zusatz enhält, in zwei Strings.
+ *
+ * @param origHn
+ * darf null sein.
+ * @param origZusatz2
+ * @return Drei Objekte, String strasse, dann ein Integer mit der
+ * Hausnummer, und als drittes ein String mit dem Zusatz. bei können
+ * null sein.
+ */
+ public static String[] split(final String... stringStrHnZusatz) {
+
+ boolean warn = false;
+
+ if (stringStrHnZusatz.length < 1 || stringStrHnZusatz.length > 3)
+ throw new IllegalArgumentException(
+ "Only 1, 2 or 3 String parameters are allowed (Straße [Hn] [Zusatz], Hausnummer, Zusatz)");
+
+ String origStrasse = null;
+ String origHn = null;
+ String origZusatz = null;
+ if (stringStrHnZusatz.length >= 1)
+ origStrasse = stringStrHnZusatz[0];
+ if (stringStrHnZusatz.length >= 2)
+ origHn = stringStrHnZusatz[1];
+ if (stringStrHnZusatz.length == 3)
+ origZusatz = stringStrHnZusatz[2];
+
+ if (origStrasse == null || origStrasse.isEmpty()
+ || !origStrasse.matches(".*[A-Za-z][A-Za-z]+.*")) {
+ final String[] splitHn = splitHn(origHn, origZusatz);
+ return new String[] { null, splitHn[0], splitHn[1] };
+ }
+
+ String strasse = null;
+ String hn = null;
+ String zusatz = null;
+
+ // Evt. umschliessende " im String entfernen:
+ {
+ origStrasse = trimQuotes(origStrasse);
+ origHn = trimQuotes(origHn);
+ origZusatz = trimQuotes(origZusatz);
+ }
+
+ String zusammen = origStrasse + " "
+ + (origHn != null ? " " + origHn : "")
+ + (origZusatz != null ? " " + origZusatz : "");
+ zusammen = trimQuotes(zusammen);
+ zusammen = removeKommataAfterStreetname(zusammen);
+ zusammen = removeTrailingHyphens(zusammen);
+ zusammen = removeLeadingSpacesInfrontOfNumbers(zusammen);
+
+ zusammen = removeSpacesBetweenHiphenAndDotAndLetters(zusammen);
+
+ Matcher m = REGEX_splitFullString.matcher(zusammen);
+
+ final boolean found = m.find();
+
+ if (!found) {
+ // String[] splitHn = splitHn(origHn, origZusatz);
+ // log.warn(splitRegExp.toString() + " retuned no matches for "
+ // + origStrasse + " " + origHn + " " + origZusatz);
+ // return new String[] { null, splitHn[0], splitHn[1] };
+
+ Pattern p = Pattern
+ .compile("([^\\d]*)\\s([\\d]+[^\\s]*|[\\d]+\\s+\\d+)$");
+ m = p.matcher(zusammen);
+ if (m.find()) {
+ strasse = m.group(1);
+ hn = m.group(2);
+ } else {
+ p = Pattern.compile("(.+?)\\s([\\d]+.*)$");
+ m = p.matcher(zusammen);
+ if (m.find()) {
+ strasse = m.group(1);
+ hn = m.group(2);
+ } else {
+
+ // Wenn keine Zahl enthalten ist, dann ist alles strasse
+ p = Pattern.compile(".*\\d+.*$");
+ if (p.matcher(zusammen).find())
+ return new String[] { null, null, null, null };
+ else
+ return new String[] { zusammen, null, null, null };
+ }
+ }
+ warn = true;
+ }
+ try {
+ strasse = m.group(1).trim();
+ final String group2 = m.group(2);
+ if (group2 != null && !group2.isEmpty())
+ hn = group2;
+
+ // TODO
+ if (m.groupCount() >= 3) {
+ final String group3 = m.group(3);
+ if (group3 != null && !group3.trim().isEmpty())
+ zusatz = group3.trim();
+ }
+ } catch (final Exception e) {
+ log.error("", e);
+ }
+ strasse = StringUtils.trimToNull(strasse);
+ if (strasse == null || strasse.length() < 3) {
+
+ final Pattern p = Pattern
+ .compile("(.+?)\\s([\\d]+[-]?[\\d]*)(.*)$");
+ m = p.matcher(zusammen);
+ if (m.find()) {
+ strasse = m.group(1);
+ hn = m.group(2);
+ zusatz = m.group(3);
+ } else
+ return new String[] { null, null, null, null };
+
+ // log.error("Strasse = " + strasse);
+ warn = true;
+ }
+
+ if (strasse.contains("Flurstück") || strasse.contains("Flst")) {
+ return new String[] { null, null, null, null };
+ }
+
+ if (strasse.length() <= 2) {
+ // z.b. Strasse "-"
+ return new String[] { null, null, null, null };
+ }
+
+ if (warn)
+ log.warn("Aus '" + origStrasse + "' wurde Strasse='" + strasse
+ + "', HN='" + StringUtils.trimToNull(hn) + "', Zusatz='"
+ + StringUtils.trimToNull(zusatz) + "', richtig?");
+
+ return new String[] { strasse, StringUtils.trimToNull(hn),
+ StringUtils.trimToNull(zusatz) };
+ }
+
+ /**
+ * @param zusammen
+ * @return
+ */
+ public static String removeTrailingHyphens(String zusammen) {
+ return zusammen.replaceAll("(.*)\\s?[-]$", "$1");
+ }
+
+ /**
+ * @param zusammen
+ * @return
+ */
+ public static String removeKommataAfterStreetname(String zusammen) {
+ return zusammen.replaceAll("([A-Za-z][A-Za-z]+)\\s?[,]\\s?(\\d+)",
+ "$1 $2");
+ }
+
+ private static String removeSpacesBetweenHiphenAndDotAndLetters(
+ String zusammen) {
+ zusammen = zusammen.replaceAll("([A-Za-z]+)\\s+([.-]*)\\s?([.-])+",
+ "$1$2$3");
+ return zusammen;
+ }
+
+ /**
+ * Bearbeitung eines Spezialfalls, der nicht funktioniert...
+ */
+ public static String removeLeadingSpacesInfrontOfNumbers(String zusammen) {
+ return zusammen.replaceAll("([,/\\\\])\\s+(\\d+)", "$1$2");
+ }
+
+ /**
+ * Entfernt evt. umschliessende " oder ' um den string
+ */
+ public static String trimQuotes(String s) {
+ if (s == null)
+ return "";
+ s = s.trim();
+ s = s.replace('"', ' ');
+ s = s.replace('\'', ' ');
+ s = s.replace(" ", " ");
+ return s.trim();
+ }
+
+ // TODO sauberes rewrite unter besserer Ausnutzung von Rekursion
+ public static List<String> getHausnummernInterpreted(
+ final String hausnummern) {
+ final List<String> result = new ArrayList<String>();
+ if (hausnummern != null) {
+ final Matcher m = Pattern.compile("(\\d)+\\s*([a-z]+)[,]([a-z]+)")
+ .matcher(hausnummern);
+ if (m.find()) {
+ result.addAll(getHausnummern(m.group(1) + m.group(2)));
+ result.addAll(getHausnummern(m.group(1) + m.group(3)));
+ return result;
+ }
+ final String[] splitted = hausnummern.split("[,/;]+");
+ for (final String hn : splitted) {
+ result.addAll(getHausnummern(hn));
+ }
+ }
+ return result;
+ }
+
+ public static List<String> getHausnummern(String hausnummerUntested) {
+
+ if (hausnummerUntested == null)
+ return Collections.emptyList();
+
+ hausnummerUntested = hausnummerUntested.trim().toLowerCase();
+
+ final List<String> result = new ArrayList<String>();
+
+ hausnummerUntested = hausnummerUntested.replaceAll("\\s+", "");
+
+ Matcher m = REGEX_hnZusatzBereich2aBis2f.matcher(hausnummerUntested);
+ if (m.find()) {
+
+ // 15a - f
+ if (!m.group(2).isEmpty() && m.group(4).isEmpty()
+ && !m.group(5).isEmpty()) {
+
+ for (char a = m.group(2).charAt(0); a <= m.group(5).charAt(0); a++) {
+ result.add(m.group(1) + a);
+ }
+ return result;
+ }
+
+ // TODO Hier stehen manchmal nicht nur zahlen drin!
+ /**
+ * Stefan Tzeggai : Was soll das programm aus "9a - 11d" machen?
+ * "9a, 10, 11d" ?
+ */
+
+ // Überprüfen, ob hinter der Zahl noch was steht...
+
+ final String minNumStr = m.group(1);
+ final String maxNumStr = m.group(4);
+
+ // 12-15
+ if (m.group(2).isEmpty() && !maxNumStr.isEmpty()
+ && m.group(5).isEmpty()) {
+ // Keine Zusätze in dem Bereich...
+ log.debug("Versuche Hausnummernbereich " + minNumStr + " bis "
+ + maxNumStr + " aufzulösen...");
+ final int min = Integer.parseInt(minNumStr);
+ final int max = Integer.parseInt(maxNumStr);
+
+ if (max - min > 100) {
+ log.warn("Hausnummernbereich von " + min + " bis " + max
+ + " ausgelassen, weil der Bereich zu groß ist.");
+ return Collections.EMPTY_LIST;
+ }
+
+ for (int i = min; i <= max; i++) {
+ // TODO Hier könnte man nur die geraden oder ungeraden
+ // zählen
+ result.add(Integer.toString(i));
+ }
+ } else {
+ log.debug("Hausnummernbereich " + minNumStr + m.group(2)
+ + " bis " + maxNumStr + m.group(5)
+ + " kann noch nicht hochgezählt werden.");
+ if (!minNumStr.isEmpty())
+ result.add(minNumStr + m.group(2));
+ if (!maxNumStr.isEmpty())
+ result.add(maxNumStr + m.group(5));
+ }
+ return result;
+ }
+
+ m = REGEX_hnListe.matcher(hausnummerUntested);
+ if (m.find()) {
+ result.add(m.group(1));
+ result.add(m.group(3));
+ m.group(2);
+ return result;
+ }
+
+ m = REGEX_hnEinzeln.matcher(hausnummerUntested);
+ if (m.find()) {
+ String match = m.group(1);
+ match += m.group(2);
+ result.add(match);
+ return result;
+ }
+
+ log.error("Hausnummer raw '" + hausnummerUntested
+ + "' nicht verstanden.");
+ return result;
+ }
+
+ /**
+ * Interpretiert eine GKZ, KKZ etc anhang Ihrer Länge und liefert ob es sich
+ * um einen KREIS oder ein BUNDESLAND handelt
+ *
+ * @return <code>null</code> wenn <code>null</code> übergeben worde oder der
+ * code nicht verstanden wurde.
+ */
+ static Ebene getEbeneForEbeneCode(String code) {
+ if (code == null)
+ return null;
+ code = code.trim();
+ if (code.length() == 8)
+ return Ebene.KOMMUNE;
+ if (code.length() == 5)
+ return Ebene.KREISE;
+ if (code.length() == 2)
+ return Ebene.BUNDESLAND;
+ return null;
+ }
+}
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/Ebene.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/Ebene.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/Ebene.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,26 @@
+package de.schmitzm.adresses;
+
+/**
+ * Administrative Ebene in Deutschland
+ */
+public enum Ebene {
+
+ LAND("D"), LANDESHAELFTE("LH"), BUNDESLAND("BL"), KREISE("KR"), KOMMUNE(
+ "KO"), SR("SR");
+
+ private final String id;
+
+ Ebene(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+
+}
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormResult.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormResult.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormResult.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,53 @@
+package de.schmitzm.adresses;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+public class NormResult {
+ static final private Logger log = Logger.getLogger(NormResult.class);
+
+ @Override
+ /**
+ * For some hacky convenience, this toString returns the resulting (changed) String directly.
+ */
+ public String toString() {
+ // return "NormResult [deltaMag=" + deltaMag + ", hitRules=" + hitRules
+ // + ", origStr=" + origStr + ", resultStr=" + resultStr + "]";
+ return getResultStr();
+ }
+
+ private int deltaMag = 0;
+ private List<NormRule> hitRules = new ArrayList<NormRule>();
+
+ final String origStr;
+
+ String resultString;
+
+ public NormResult(String origStr) {
+ this.origStr = origStr == null ? null : origStr.trim();
+ this.resultString = this.origStr;
+ }
+
+ public void addHitRule(NormRule nr) {
+ hitRules.add(nr);
+ }
+
+ public int getDeltaMag() {
+ return deltaMag;
+ }
+
+ public String getOrigStr() {
+ return origStr;
+ }
+
+ public String getResultStr() {
+ return resultString;
+ }
+
+ public void setResultString(String resultStr) {
+ this.resultString = resultStr;
+ }
+
+}
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormRule.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormRule.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/NormRule.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,10 @@
+package de.schmitzm.adresses;
+
+import org.apache.log4j.Logger;
+
+public interface NormRule {
+ static final Logger log = Logger.getLogger(NormRule.class);
+
+ public void applyTo(NormResult nRes);
+
+}
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/RuleRegistry.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/RuleRegistry.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/RuleRegistry.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,79 @@
+package de.schmitzm.adresses;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+public class RuleRegistry {
+ private static final String XLSRULESZUSATZ = "rulesZusatz.xls";
+
+ private static final String XLSRULESHN = "rulesHn.xls";
+
+ private static final String XLSRULES = "rules.xls";
+
+ static final private Logger log = Logger.getLogger(RuleRegistry.class);
+
+ private static final List<NormRule> allRules = new ArrayList<NormRule>();
+ private static final List<NormRule> rulesHn = new ArrayList<NormRule>();
+ private static final List<NormRule> rulesZusatz = new ArrayList<NormRule>();
+
+ private final static RuleRegistry _instance = new RuleRegistry();
+
+ NormRule lowerCaseRule = new NormRule() {
+
+ @Override
+ public void applyTo(NormResult nRes) {
+ String str = nRes.getResultStr();
+ String orig = str;
+ str = str.toLowerCase();
+ if (!orig.equals(str))
+ nRes.addHitRule(this);
+ nRes.setResultString(str);
+
+ }
+ };
+
+ private RuleRegistry() {
+ try {
+ allRules.add(lowerCaseRule);
+ rulesHn.add(lowerCaseRule);
+ rulesZusatz.add(lowerCaseRule);
+
+ // read rules from excel table and fill all rules
+ XLSRulesParser xlsRulesParser = new XLSRulesParser(this);
+ xlsRulesParser.parserExcelRules(XLSRULES);
+ xlsRulesParser.parserExcelRules(XLSRULESHN);
+ xlsRulesParser.parserExcelRules(XLSRULESZUSATZ);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static List<NormRule> getRulesStr() {
+ return allRules;
+ }
+
+ public static RuleRegistry getInstance() {
+ return _instance;
+ }
+
+ public void addRule(XLSNormRule normRule, String xlsFilename) {
+ if (xlsFilename.equals("rules.xls")) {
+ allRules.add(normRule);
+ } else if (xlsFilename.equals("rulesHn.xls")){
+ rulesHn.add(normRule);
+ } else if (xlsFilename.equals("rulesZusatz.xls")){
+ rulesZusatz.add(normRule);
+ }
+ }
+
+ public static List<NormRule> getRulesZusatz() {
+ return rulesZusatz;
+ }
+
+ public static List<NormRule> getRulesHn() {
+ return rulesHn;
+ }
+
+}
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSNormRule.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSNormRule.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSNormRule.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,46 @@
+package de.schmitzm.adresses;
+
+public class XLSNormRule implements NormRule {
+
+ @Override
+ public String toString() {
+ return "XLSNormRule [was=" + was + ", zu=" + zu + ", regEx=" + regEx
+ + ", comment=" + comment + "]";
+ }
+
+ private final String was;
+ private final String zu;
+ private final boolean regEx;
+ private final String comment;
+
+ public XLSNormRule(String was, String zu, boolean regEx, String comment) {
+ this.regEx = regEx;
+ this.was = regEx ? was : was.toLowerCase();
+ this.zu = regEx ? zu : zu.toLowerCase();
+ this.comment = comment;
+ }
+
+ @Override
+ public void applyTo(NormResult nRes) {
+ String str = nRes.getResultStr();
+
+ String orig = str;
+
+ if (regEx) {
+ str = str.replaceAll(was, zu);
+ } else {
+ str = str.replace(was, zu);
+ }
+
+ if (!orig.equals(str)) {
+ nRes.addHitRule(this);
+ nRes.setResultString(str);
+ }
+
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+}
Added: trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSRulesParser.java
===================================================================
--- trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSRulesParser.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/main/java/de/schmitzm/adresses/XLSRulesParser.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,106 @@
+package de.schmitzm.adresses;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import jxl.Cell;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.WorkbookSettings;
+import jxl.read.biff.BiffException;
+import jxl.read.biff.WorkbookParser;
+
+import org.apache.log4j.Logger;
+
+
+public class XLSRulesParser {
+
+ static final private Logger log = Logger.getLogger(XLSRulesParser.class);
+ private final RuleRegistry ruleRegistry;
+
+ public XLSRulesParser(RuleRegistry ruleRegistry) {
+ this.ruleRegistry = ruleRegistry;
+ }
+
+ /**
+ * Chartset expected in the xls file
+ */
+ private static final String EXCELCHARSET = "cp1252";
+
+ /**
+ * Reads in Replacement Rules from a XLS file
+ *
+ * @throws IOException
+ * @throws BiffException
+ */
+ void parserExcelRules(String xlsFilename) throws IOException, BiffException {
+
+ WorkbookSettings workbookSettings = new WorkbookSettings();
+ workbookSettings.setEncoding(EXCELCHARSET);
+
+ URL amdExcel = XLSRulesParser.class.getResource("/" + xlsFilename);
+
+ if (amdExcel == null)
+ throw new RuntimeException(xlsFilename + " nicht gefunden!");
+
+ InputStream openStream = amdExcel.openStream();
+
+ try {
+
+ WorkbookParser workbook = (WorkbookParser) Workbook.getWorkbook(
+ openStream, workbookSettings);
+
+ // We except only one sheet!
+ Sheet sheet = workbook.getSheet(0);
+
+ int rows = sheet.getRows();
+ log.debug("Importiere " + (rows - 10)
+ + " Zeilen mit Regeln. Erwartetes Charset der "
+ + xlsFilename + " ist " + EXCELCHARSET);
+
+ // Start in der 10. Zeile
+ for (int y = 10; y < rows; y++) {
+ importXlsRule(sheet.getRow(y), xlsFilename);
+ }
+
+ } finally {
+ openStream.close();
+ }
+
+ }
+
+ final static int ROW_IDX_WAS = 0;
+ final static int ROW_IDX_ZU = 1;
+ final static int ROW_IDX_REGEXBOOL = 2;
+ final static int ROW_IDX_COMMENT = 3;
+
+ /**
+ * Imports a replacement rule defined in the xls file
+ */
+ private void importXlsRule(Cell[] row, String xlsFilename) {
+
+ String was = row[ROW_IDX_WAS].getContents();
+ if (was == null)
+ return;
+ String zu = "";
+ if (row.length > ROW_IDX_ZU) {
+ zu = row[ROW_IDX_ZU].getContents();
+ }
+
+ boolean regEx = false;
+ if (row.length > ROW_IDX_REGEXBOOL) {
+ String regBoolStr = row[ROW_IDX_REGEXBOOL].getContents();
+ regEx = regBoolStr != null ? (!regBoolStr.isEmpty()) : false;
+ }
+
+ String comment = null;
+ if (row.length > ROW_IDX_COMMENT) {
+ comment = row[ROW_IDX_COMMENT].getContents();
+ }
+
+ XLSNormRule xlsNormRule = new XLSNormRule(was, zu, regEx, comment);
+
+ ruleRegistry.addRule(xlsNormRule, xlsFilename);
+ }
+}
Added: trunk/schmitzm-adresses/src/main/resources/rules.xls
===================================================================
(Binary files differ)
Property changes on: trunk/schmitzm-adresses/src/main/resources/rules.xls
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/schmitzm-adresses/src/main/resources/rulesHn.xls
===================================================================
(Binary files differ)
Property changes on: trunk/schmitzm-adresses/src/main/resources/rulesHn.xls
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/schmitzm-adresses/src/main/resources/rulesZusatz.xls
===================================================================
(Binary files differ)
Property changes on: trunk/schmitzm-adresses/src/main/resources/rulesZusatz.xls
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/AddrStringUtilTest.java
===================================================================
--- trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/AddrStringUtilTest.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/AddrStringUtilTest.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,258 @@
+package de.schmitzm.adresses;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+import de.schmitzm.adresses.AddrStringUtil;
+import de.schmitzm.lang.LangUtil;
+
+/**
+ *
+ */
+public class AddrStringUtilTest {
+
+ @Test
+ public void testGetHausnummernInterpreted() {
+ checkHausnummern("6 - 14", "6", "7", "8", "9", "10", "11", "12", "13",
+ "14");
+
+ checkHausnummern("0175-123456789");
+
+ checkHausnummern("1-", "1");
+
+ checkHausnummern("3/4", "3", "4");
+ checkHausnummern("3/4", "3", "4");
+ checkHausnummern(" 2, 2 a, 4,", "2", "2a", "4");
+
+ checkHausnummern("22 - 23", "22", "23");
+ checkHausnummern("22,23", "22", "23");
+ checkHausnummern(" 22 - 24 ", "22", "23", "24");
+ checkHausnummern(" 25 bis 28 ", "25", "26", "27", "28");
+ checkHausnummern(" 23/24;77 ", "23", "24", "77");
+ checkHausnummern("1,2,3,8", "1", "2", "3", "8");
+ checkHausnummern("1,3a,3ab", "1", "3a", "3ab");
+ checkHausnummern("1a-c,3b,3a", "1a", "1b", "1c", "3b", "3a");
+ checkHausnummern(" 3/4/8 ", "3", "4", "8");
+
+ checkHausnummern("1 a-c", "1a", "1b", "1c");
+ checkHausnummern("1 a - c", "1a", "1b", "1c");
+ checkHausnummern("1 a,c", "1a", "1c");
+ checkHausnummern("1/1A", "1", "1a");
+ checkHausnummern("1/3//22", "1", "3", "22");
+ checkHausnummern("1/3//22", "1", "3", "22");
+
+ // checkHausnummern("1/73E", null);
+ checkHausnummern("999", "999");
+ // checkHausnummern("1000", null);
+ // checkHausnummern("21300", null);
+
+ // checkHausnummern("40237", "1", "3");
+
+ checkHausnummern("2 - 3", "2", "3");
+ checkHausnummern("2a", "2a");
+ // checkHausnummern("2c - 6b", "2c", "4", "6b");
+ checkHausnummern("2, 2 a, 4,", "2", "2a", "4");
+ checkHausnummern("2 a", "2a");
+ checkHausnummern("2 a", "2a");
+ checkHausnummern("2,3", "2", "3");
+ checkHausnummern("9a - 10d", "9a", "10d");
+ checkHausnummern(" 2 - 4 ", "2", "3", "4");
+ checkHausnummern(" 5 bis 8 ", "5", "6", "7", "8");
+ }
+
+ private void checkHausnummern(String ist, String... soll) {
+ List<String> check = AddrStringUtil.getHausnummernInterpreted(ist);
+ if (soll.length == 0)
+ assertEquals(Collections.EMPTY_LIST, check);
+ String[] array = check.toArray(new String[] {});
+ assertEquals(LangUtil.stringConcatWithSep(";", soll),
+ LangUtil.stringConcatWithSep(";", array));
+ }
+
+ @Test
+ public void testSplit() {
+ checkSplit("Leypoldt Strasse", "Leypoldt Strasse 6,/10 8/1", "6", null,
+ ",/10 8/1", null);
+
+ checkSplit("ander B2", "ander B2 5-6", "5-6", null, null, null);
+
+ checkSplit("Bettina Strasse", "Bettina Strasse 52-54 2.OG", "52-54",
+ null, "2.OG", null);
+
+ checkSplit("Dieselstr.", "Dieselstr .11 - 13", "11 - 13", null, null,
+ null);
+
+ checkSplit("Clarenbachstrasse", "Clarenbachstrasse 6 & 8", "6 & 8",
+ null, null, null);
+
+ checkSplit(null, "Flurstück 3 a 2", null, null, null, null);
+
+ checkSplit("Ober-Ramstädter Str.", "Ober-Ramstädter Str . 96 G 1",
+ "96", null, "G 1", null);
+
+ checkSplit("Kocherstrasse", "Kocherstrasse , 5 - 9 -", "5 - 9", null,
+ null, null);
+
+ checkSplit("H.-Weigel-Str.", "H . -Weigel-Str . 5 b/ 0402 -", "5",
+ null, "b/0402", null);
+
+ checkSplit("Richard Strauss Straße", "Richard Strauss Straße 80 &",
+ "80", null, "&", null);
+
+ checkSplit(null, "'W 10 / 0170'", null, null, null, null);
+
+ checkSplit("Marder Weg", "Marder Weg", null, null, null, null);
+
+ checkSplit("Gänsepforte", "Gänsepforte 10a-12b", "10a-12b", null, null,
+ null);
+
+ checkSplit("Marder Weg", "Marder Weg 2-4", "2-4", null, null, null);
+
+ checkSplit("Hochgericht", "Hochgericht 33,35", "33,35", null, null,
+ null);
+ checkSplit("Annenstr.", "Annenstr. 23, 25, 27, 29,", "23,25,27,29,",
+ null, null, null);
+
+ checkSplit("Maternistraße", "Maternistraße 6 - 14", "6 - 14", null,
+ null, null);
+
+ checkSplit("Berliner Str.", "Berliner Str. 2,2a,4", "2,2a,4", null,
+ null, null);
+ checkSplit("Berliner Str.", "Berliner Str. 2,2a,4,", "2,2a,4,", null,
+ null, null);
+ checkSplit("Berliner Str.", "Berliner Str. 2,2 a,4", "2,2 a,4", null,
+ null, null);
+ checkSplit("Berliner Str.", "Berliner Str. 2, 4", "2,4", null, null,
+ null);
+ checkSplit("Berliner Str.", "Berliner Str. 2, 4", "2,4", null, null,
+ null);
+ checkSplit("Berliner Str.", "Berliner Str. 2a,4", "2a,4", null, null,
+ null);
+ checkSplit("Berliner Str.", "Berliner Str. 2a, 4", "2a,4", null, null,
+ null);
+ checkSplit("Berliner Str.", "Berliner Str. 2,2a, 4", "2,2a,4", null,
+ null, null);
+ checkSplit("Berliner Str.", "Berliner Str. 2, 2 a, 4,", "2,2 a,4,",
+ null, null, null);
+
+ checkSplit("Dammweg", "Dammweg 3/4", "3/4", null, null, null);
+
+ checkSplit("Hochgericht", "Hochgericht 33,35,66,78", "33,35,66,78",
+ null, null, null);
+
+ checkSplit("Marder Weg", "Marder Weg 2/4/10", "2/4/10", null, null,
+ null);
+
+ // checkSplit("Burgstr.", "Burgstr. 16,16A-B", "16,16A-B", null, null,
+ // null);
+
+ checkSplit("Marder Weg", "Marder Weg 2 - 4 ", "2 - 4", null, null, null);
+ checkSplit("Marder Weg", "Marder Weg 2 bis 4", "2 bis 4", null, null,
+ null);
+ checkSplit("Marder Weg", "Marder Weg 2\\4", "2\\4", null, null, null);
+ checkSplit("Marder Weg", "Marder Weg 2/4", "2/4", null, null, null);
+
+ checkSplit("Marder Weg", "Marder Weg 4", "4", null, null, null);
+ checkSplit("Marder Weg", "Marder Weg 4a", "4", null, "a", null);
+ checkSplit("Marder Weg", "Marder Weg", "2", "2", null, null);
+ checkSplit("Marder Weg", "Marder Weg", "2", "2a", "a", null);
+ checkSplit("Marder Weg", "Marder Weg", "2", "2", "a", "a");
+
+ checkSplit("Marderweg", "Marderweg", null, null, null, null);
+ checkSplit("Marderweg", "Marderweg 4", "4", null, null, null);
+ checkSplit("Marderweg", "Marderweg 4a", "4", null, "a", null);
+ checkSplit("Marderweg", "Marderweg", "2", "2", null, null);
+ checkSplit("Marderweg", "Marderweg", "2", "2a", "a", null);
+ checkSplit("Marderweg", "Marderweg", "2", "2", "a", "a");
+
+ checkSplit("Marderweg", "Marderweg", "2", "2", "a", "a");
+
+ // checkSplit("Strasse des 3. Juni", "Strasse des 3. Juni", null, null,
+ // null, null);
+ // checkSplit("Strasse des 3. Juni", "Strasse des 3. Juni 4b", "4",
+ // null,
+ // "b", null, null, null);
+
+ checkSplit(null, null, null, null, null, null);
+ checkSplit(null, null, "3", "3 aa", "aa", null);
+ checkSplit(null, null, "3", "3 aa ", "aa", null);
+ checkSplit(null, null, "3", "3 aa a", "aa a", null);
+ checkSplit(null, null, "3", " 3 a", "a", null);
+ checkSplit(null, null, "2", "2a", "a blub", "blub");
+ checkSplit(null, null, "2", "2", "blub", "blub");
+ }
+
+ private void checkSplit(String sollStrasse, String istStrasse,
+ String sollHn, String istHn, String sollZusatz, String istZusatz) {
+
+ String[] objects = AddrStringUtil.split(istStrasse, istHn, istZusatz);
+
+ String strasse = objects[0];
+ String hn = objects[1];
+ String zusatz = objects[2];
+ assertEquals(sollStrasse, strasse);
+ assertEquals(sollHn, hn);
+ assertEquals(sollZusatz, zusatz);
+
+ }
+
+ @Test
+ public void testNormalizeStrasse() {
+ checkNormalizeStrasse("jaegerndorferzeile", "Jägerndorfer Zeile");
+ checkNormalizeStrasse("weststrasse", "West Straße");
+ checkNormalizeStrasse("weststrasse", "West Str.");
+ checkNormalizeStrasse("hatschiergasse", " hatschiergasse ");
+ checkNormalizeStrasse("eichendorfstrasse", "Eichendorfstr.");
+ checkNormalizeStrasse("burgstrasse", "Burgstr.");
+ checkNormalizeStrasse("burgstrasse", "Burg Straße");
+ checkNormalizeStrasse("drosselweg", "Drossel Weg");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr.-Vogeler-Str.");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr. Vogeler Str.");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr. Vogeler Str .");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr. Vogeler Strasse");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr. Vogeler Straße");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr. Vogeler-Straße");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr.Vogeler-Straße");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr.Vogelerstraße");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr.Vogelerstrasse");
+ checkNormalizeStrasse("drvogelerstrasse", "Dr.Vogeler S");
+
+ }
+
+ @Test
+ public void testNormalizeZusatz() {
+ checkNormalizeZusatz("palim palim", "Palim Palim");
+ checkNormalizeZusatz("dumdidum", " dumdidum ");
+ checkNormalizeZusatz("strasse", "Straße");
+ checkNormalizeZusatz("oe", "ö");
+ checkNormalizeZusatz("ae", "ä");
+ checkNormalizeZusatz("ue", "ü");
+ checkNormalizeZusatz("e", "é");
+ checkNormalizeZusatz("a", "á");
+ }
+
+ private void checkNormalizeStrasse(String s1, String s2) {
+ assertEquals(s1, AddrStringUtil.normalizeStrasse(s2).getResultStr());
+ }
+
+ private void checkNormalizeZusatz(String s1, String s2) {
+ assertEquals(s1, AddrStringUtil.normalizeZusatz(s2).getResultStr());
+ }
+
+ @Test
+ public void testTrimQuotes() {
+ assertEquals("m m m 3", AddrStringUtil.trimQuotes("\"m m \"m 3\""));
+ }
+
+ @Test
+ public void testRemoveLeadingSpacesInfrontOfNumbers() {
+ assertEquals("2a,4",
+ AddrStringUtil.removeLeadingSpacesInfrontOfNumbers("2a, 4"));
+
+ }
+
+}
Added: trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/RuleRegistryTest.java
===================================================================
--- trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/RuleRegistryTest.java 2011-07-11 18:27:42 UTC (rev 1625)
+++ trunk/schmitzm-adresses/src/test/java/de/schmitzm/adresses/RuleRegistryTest.java 2011-07-12 19:53:03 UTC (rev 1626)
@@ -0,0 +1,23 @@
+package de.schmitzm.adresses;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import de.schmitzm.adresses.RuleRegistry;
+import de.schmitzm.testing.TestingClass;
+
+public class RuleRegistryTest extends TestingClass {
+
+ @Test
+ public void testGetRulesStr() {
+ List<NormRule> ar = RuleRegistry.getInstance().getRulesStr();
+
+ assertNotNull(ar);
+ assertTrue(ar.size() > 4);
+ }
+
+}
More information about the Schmitzm-commits
mailing list