de.jfachwert.post.Anschrift.java Source code

Java tutorial

Introduction

Here is the source code for de.jfachwert.post.Anschrift.java

Source

/*
 * Copyright (c) 2017 by Oliver Boehm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 21.02.2017 by oboehm (ob@oasd.de)
 */
package de.jfachwert.post;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import de.jfachwert.Fachwert;
import de.jfachwert.pruefung.exception.InvalidValueException;
import de.jfachwert.util.ToFachwertSerializer;
import org.apache.commons.lang3.StringUtils;

import javax.validation.ValidationException;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Die Anschrift besteht aus Namen und Adresse oder Postfach. Der Name kann
 * dabei eine Person oder eine Personengruppe (zum Beispiel Unternehmen,
 * Vereine und Aehnliches) sein.
 *
 * @author oboehm
 * @since 0.2 (12.05.2017)
 */
@JsonSerialize(using = ToFachwertSerializer.class)
public class Anschrift implements Fachwert {

    private static final Logger LOG = Logger.getLogger(Anschrift.class.getName());
    public static final String ADDRESS = "address";

    private final Adressat adressat;
    private final Adresse adresse;
    private final Postfach postfach;

    /**
     * Zerlegt die uebergebene Anschrift in Adressat und Adresse oder Postfach,
     * um daraus eine Anschrift zu erzeugen. Folgende Heuristiken werden fuer 
     * die Zerlegung herangezogen:
     * <ul>
     *     <li>Adressat steht an erster Stelle</li>
     *     <li>Einzelteile werden durch Komma oder Zeilenvorschub getrennt</li>
     * </ul>
     *
     * @param anschrift z.B. "Donald Duck, 12345 Entenhausen, Gansstr. 23"
     */
    public Anschrift(String anschrift) {
        this(split(anschrift));
    }

    private Anschrift(Object[] anschrift) {
        this(new Adressat(anschrift[0].toString()), (Adresse) anschrift[1], (Postfach) anschrift[2]);
    }

    /**
     * Erzeugt eine neue Anschrift aus der uebergebenen Map.
     *
     * @param map mit den einzelnen Elementen fuer "adressat" und "adresse".
     */
    @JsonCreator
    public Anschrift(Map<String, Object> map) {
        this(new Adressat(map.get("adressat").toString()), new Adresse((Map<String, String>) (map.get("adresse"))));
    }

    /**
     * Erzeugt aus dem Namen und Adresse eine Anschrift.
     *
     * @param name    Namen einer Person oder Personengruppe
     * @param adresse eine gueltige Adresse
     * @deprecated bitte {@link Anschrift#Anschrift(Adressat, Adresse)} verwenden
     */
    @Deprecated
    public Anschrift(String name, Adresse adresse) {
        this(new Adressat(name), adresse);
    }

    /**
     * Erzeugt aus dem Adressaten und Adresse eine Anschrift.
     *
     * @param name    Namen einer Person oder Personengruppe
     * @param adresse eine gueltige Adresse
     */
    public Anschrift(Adressat name, Adresse adresse) {
        this(name, adresse, null);
    }

    /**
     * Erzeugt aus dem Namen und einem Postfach eine Anschrift.
     *
     * @param name     Namen einer Person oder Personengruppe
     * @param postfach ein gueltiges Postfach
     * @deprecated bitte {@link Anschrift#Anschrift(Adressat, Postfach)} verwenden
     */
    @Deprecated
    public Anschrift(String name, Postfach postfach) {
        this(new Adressat(name), postfach);
    }

    /**
     * Erzeugt aus dem Adressaten und einem Postfach eine Anschrift.
     *
     * @param name     Namen einer Person oder Personengruppe
     * @param postfach ein gueltiges Postfach
     */
    public Anschrift(Adressat name, Postfach postfach) {
        this(name, null, postfach);
    }

    private Anschrift(Adressat name, Adresse adresse, Postfach postfach) {
        this.adressat = name;
        this.adresse = adresse;
        this.postfach = postfach;
        if (adresse == null) {
            if (postfach == null) {
                throw new InvalidValueException("post_office_box");
            }
        } else {
            if (postfach != null) {
                throw new InvalidValueException(adresse, ADDRESS);
            }
        }
    }

    /**
     * Zerlegt die uebergebene Anschrift in Adressat und Adresse oder Postfach,
     * um daraus eine Anschrift zu erzeugen. Folgende Heuristiken werden fuer 
     * die Zerlegung herangezogen:
     * <ul>
     *     <li>Adressat steht an erster Stelle</li>
     *     <li>Einzelteile werden durch Komma oder Zeilenvorschub getrennt</li>
     * </ul>
     *
     * @param anschrift z.B. "Donald Duck, 12345 Entenhausen, Gansstr. 23"
     * @return Anschrift
     */
    public static Anschrift of(String anschrift) {
        return new Anschrift(anschrift);
    }

    /**
     * Erzeugt aus dem Adressaten und einem Postfach eine Anschrift.
     *
     * @param name     Namen einer Person oder Personengruppe
     * @param postfach ein gueltiges Postfach
     * @return Anschrift
     */
    public static Anschrift of(Adressat name, Postfach postfach) {
        return new Anschrift(name, postfach);
    }

    /**
     * Erzeugt aus dem Adressaten und Adresse eine Anschrift.
     *
     * @param name    Namen einer Person oder Personengruppe
     * @param adresse eine gueltige Adresse
     * @return Anschrift
     */
    public static Anschrift of(Adressat name, Adresse adresse) {
        return new Anschrift(name, adresse);
    }

    /**
     * Zerlegt die uebergebene Anschrift in Adressat und Adresse oder Postfach
     * fuer die Validierung.i Folgende Heuristiken werden fuer die Zerlegung
     * herangezogen:
     * <ul>
     *     <li>Adressat steht an erster Stelle</li>
     *     <li>Einzelteile werden durch Komma oder Zeilenvorschub getrennt</li>
     * </ul>
     * 
     * @param anschrift z.B. "Donald Duck, 12345 Entenhausen, Gansstr. 23"
     */
    public static void validate(String anschrift) {
        split(anschrift);
    }

    private static Object[] split(String anschrift) {
        String[] lines = StringUtils.trimToEmpty(anschrift).split("[,\\n$]");
        if (lines.length < 2) {
            throw new InvalidValueException(anschrift, ADDRESS);
        }
        Object[] parts = new Object[3];
        parts[0] = new Adressat(lines[0]);
        String adresseOrPostfach = anschrift.substring(lines[0].length() + 1).trim();
        try {
            parts[1] = null;
            parts[2] = new Postfach(adresseOrPostfach);
        } catch (ValidationException ex) {
            LOG.log(Level.FINE, "'" + adresseOrPostfach + "' is not a post office box:", ex);
            parts[1] = new Adresse(adresseOrPostfach);
            parts[2] = null;
        }
        return parts;
    }

    /**
     * Liefert den Adressaten. Ein Adressat kann eine Person oder eine 
     * Personengruppe (zum Beispiel Unternehmen, Vereine und Aehnliches) sein.
     *
     * @return z.B. "Mustermann, Max" als Adressat
     */
    public Adressat getAdressat() {
        return adressat;
    }

    /**
     * Liefert den Namen. Ein Name kann eine Person oder eine Personengruppe
     * (zum Beispiel Unternehmen, Vereine und Aehnliches) sein.
     *
     * @return z.B. "Mustermann"
     */
    public String getName() {
        return adressat.getName();
    }

    /**
     * Liefert die Adresse der Anschrift. Voraussetzung fuer den Aufruf dieser
     * Methode ist, dass die Anschrift tatsaechlich eine Adresse enthaelt, und
     * kein Postfach.
     *
     * @return eine gueltige Adresse
     */
    public Adresse getAdresse() {
        if (adresse == null) {
            throw new IllegalStateException("no address available");
        }
        return adresse;
    }

    /**
     * Liefert das Postfach der Anschrift. Voraussetzung fuer den Aufruf dieser
     * Methode ist, dass die Anschrift tatsaechlich ein Postfach enthaelt, und
     * keine Adresse.
     *
     * @return ein gueltiges Postfach
     */
    public Postfach getPostfach() {
        if (postfach == null) {
            throw new IllegalStateException("no post office box available");
        }
        return postfach;
    }

    /**
     * Hierueber kann abgefragt werden, ob die Anschrift eine Adresse oder ein
     * Postfach beinhaltet.
     *
     * @return true bei Postfach
     */
    public boolean hasPostfach() {
        return this.postfach != null;
    }

    /**
     * Zwei Anschriften sind gleich, wenn sie den gleichen Namen und die
     * gleiche Adresse besitzen. Dabei spielt es keine Rolle, ob der Name
     * gross- oder kleingeschrieben ist.
     *
     * @param obj die andere Anschrift
     * @return true bei Gleichheit
     */
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Anschrift)) {
            return false;
        }
        Anschrift other = (Anschrift) obj;
        return this.getName().equalsIgnoreCase(other.getName()) && this.getAdresse().equals(other.getAdresse());
    }

    /**
     * Da eine hashCode-Methode performant sein soll, wird nur der Name zur
     * Bildung des Hash-Codes herangezogen.
     *
     * @return Hashcode des Namen.
     */
    @Override
    public int hashCode() {
        return this.adressat.hashCode();
    }

    /**
     * Der Namen mit Anschrift wird einzeilig zurueckgegeben.
     *
     * @return z.B. "Dagobert Duck, 12345 Entenhausen, Geldspeicher 23"
     */
    @Override
    public String toString() {
        return getName() + ", " + (hasPostfach() ? getPostfach() : getAdresse());
    }

    /**
     * Liefert die einzelnen Attribute eines Postfaches als Map.
     *
     * @return Attribute als Map
     */
    @Override
    public Map<String, Object> toMap() {
        Map<String, Object> map = new HashMap<>();
        map.put("adressat", getAdressat());
        map.put("adresse", getAdresse());
        return map;
    }

}