net.devbase.jfreesteel.EidInfo.java Source code

Java tutorial

Introduction

Here is the source code for net.devbase.jfreesteel.EidInfo.java

Source

/*
 * jfreesteel: Serbian eID Viewer Library (GNU LGPLv3)
 * Copyright (C) 2011 Goran Rakic
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see
 * http://www.gnu.org/licenses/.
 */

package net.devbase.jfreesteel;

import java.util.HashMap;
import java.util.Map;

import org.json.simple.JSONObject;

/**
 * Simple class to hold and reformat data read from eID
 *
 * @author Filip Miletic (filmil@gmail.com)
 * @author Nikolic Aleksandar (nikolic.alek@gmail.com)
 */
public class EidInfo {

    /** eID information codes. */
    public enum Tag {
        /** Dummy tag */
        NULL(0, "ignored", "Ignored"),

        /** Registered document number. */
        DOC_REG_NO(101, "doc_reg_no", "Document reg. number"),
        /** The issuing date, e.g. 01.01.2011. */
        ISSUING_DATE(102, "issuing_date", "Issuing date"),
        /** The date that the ID expires */
        EXPIRY_DATE(103, "expiry_date", "Expiry date"),
        /** The authority, e.g. "Ministry of the Interior". */
        ISSUING_AUTHORITY(104, "issuing_authority", "Issuing authority"),

        /** The person's unique identifier number.
         *
         * While mostly unique, due to the non-bulletproof number allocation scheme, has actually
         * been known to repeat for some rare individuals. The last digit is mod 11 checksum, but
         * due the same reason, there exist numbers with incorrect checksum.
         */
        PERSONAL_NUMBER(201, "personal_number", "Personal number"),
        /** Person's last name, e.g. "Smith" for some John Smith */
        SURNAME(202, "surname", "Surname"),
        /** The given name, e.g. "John" for some John Smith. */
        GIVEN_NAME(203, "given_name", "Given name"),
        /**
         * The parent's given name, the usual 'parenthood' middle name used to disambiguate
         * similarly named persons.
         * <p>
         * E.g. "Wiley" for some John Wiley Smith.
         */
        PARENT_GIVEN_NAME(204, "parent_given_name", "Parent given name"),
        /** The gender of the person. */
        SEX(205, "sex", "Gender"),

        /** The place the person was born in, e.g. "Belgrade" */
        PLACE_OF_BIRTH(301, "place_of_birth", "Place of birth"),
        /** The community/municipality the person was born in, e.g. "Savski Venac" */
        COMMUNITY_OF_BIRTH(302, "community_of_birth", "Community of birth"), STATE_OF_BIRTH(303, "state_of_birth",
                "State of birth"), STATE_OF_BIRTH_CODE(304, "state_of_birth_code",
                        "State of birth code"), DATE_OF_BIRTH(305, "date_of_birth", "Date of birth"),

        /** The state of the person residence */
        STATE(401, "state", "State"),
        /** The community/municipality of the person residence */
        COMMUNITY(402, "community", "Community"),
        /** The place of the person residence */
        PLACE(403, "place", "Place"),
        /** The street name of the person residence */
        STREET(404, "street", "Street name"),
        /** The house number of the person residence */
        HOUSE_NUMBER(405, "house_number", "House number"),
        /** The house letter of the person residence */
        HOUSE_LETTER(406, "house_letter", "House letter"),
        /** The entrance label of the person residence */
        ENTRANCE(407, "entrance_label", "Entrance label"),
        /** The floor number of the person residence */
        FLOOR(408, "floor_number", "Floor number"),
        /** The appartment number of the person residence */
        APPARTMENT_NUMBER(409, "appartment_number", "Appartment number"),
        /** Address update date */
        ADDRESS_DATE(410, "address_date", "Address date");

        private final int code;
        private final String key;
        private final String name;

        /**
         * Initializes a tag with the corresponding raw encoding value.
         */
        Tag(int code, String key, String name) {
            this.code = code;
            this.key = key;
            this.name = name;
        }

        /** Gets the numeric tag code corresponding to this enum. */
        public int getCode() {
            return code;
        }

        /** Gets the string tag key corresponding to this enum. */
        public String getKey() {
            return key;
        }

        /** Gets the string tag name corresponding to this enum. */
        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return name;
        }
    }

    /** Builds an instance of EID info. */
    public static class Builder {

        Map<Tag, String> builder;

        public Builder() {
            builder = new HashMap<Tag, String>();
        }

        /**
        * Adds the value to the information builder.
        *
        * @throws IllegalArgumentException if the same tag is added twice.
        */
        public Builder addValue(Tag tag, String value) {
            builder.put(tag, value);
            return this;
        }

        public EidInfo build() {
            return new EidInfo(builder);
        }
    }

    private Map<Tag, String> fields;

    private EidInfo(Map<Tag, String> fields) {
        this.fields = fields;
    }

    /** Returns the value associated with the supplied tag. */
    public String get(Tag tag) {
        return fields.get(tag);
    }

    /** Returns if there is a value associated with the supplied tag. */
    public boolean has(Tag tag) {
        String value = get(tag);
        return (value != null && value.length() > 0);
    }

    /** Append tag value using given separator as a prefix. */
    private void appendTo(StringBuilder builder, String separator, Tag tag) {
        if (has(tag)) {
            builder.append(separator);
            builder.append(get(tag));
        }
    }

    /** Append tag value without any prefix. */
    private void appendTo(StringBuilder builder, Tag tag) {
        appendTo(builder, "", tag);
    }

    /** Append formatted tag value using given separator as a prefix */
    private void appendTo(StringBuilder builder, String separator, String format, Tag tag) {
        if (has(tag)) {
            builder.append(separator);
            builder.append(String.format(format, get(tag)));
        }
    }

    /**
     * Require at least one %s in the format string
     *
     * If given format is null or does not contain %s, replace with "%s"
     */
    private String sanitizeFormat(String format) {
        return (format != null && format.contains("%s")) ? format : "%s";
    }

    private String formatDate(String date) {
        return date.length() == 8
                ? String.format("%s.%s.%s", date.substring(0, 2), date.substring(2, 4), date.substring(4, 8))
                : date;
    }

    /**
     * Get given name, parent given name and a surname as a single string.
     *
     * @return Nicely formatted full name
     */
    public String getNameFull() {
        return String.format("%s %s %s", get(Tag.GIVEN_NAME), get(Tag.PARENT_GIVEN_NAME), get(Tag.SURNAME));
    }

    /**
     * Get place of residence as multiline string. Format parameters can be used to provide better
     * output or null/empty strings can be passed for no special formating.
     *
     * For example if floorLabelFormat is "%s. sprat" returned string will contain "5. sprat" for
     * floor number 5.
     *
     * Recommended values for Serbian are "ulaz %s", "%s. sprat" and "br. %s"
     *
     * @param entranceLabelFormat String to format entrance label or null
     * @param floorLabelFormat String to format floor label or null
     * @param appartmentLabelFormat String to format apartment label or null
     * @return Nicely formatted place of residence as multiline string
     *
     * FIXME: Use one parameterized format string to allow both "Main street 11" and 
     * "11 Main street"
     * 
     * FIXME: Think about how to handle short form format with missing ENTRANCE/FLOOR 
     * label (line 298).
     */
    public String getPlaceFull(String entranceLabelFormat, String floorLabelFormat, String appartmentLabelFormat) {

        StringBuilder out = new StringBuilder();

        entranceLabelFormat = sanitizeFormat(entranceLabelFormat);
        floorLabelFormat = sanitizeFormat(floorLabelFormat);
        appartmentLabelFormat = sanitizeFormat(appartmentLabelFormat);

        // Main street, Main street 11, Main street 11A
        appendTo(out, Tag.STREET);
        appendTo(out, " ", Tag.HOUSE_NUMBER);
        appendTo(out, Tag.HOUSE_LETTER);

        // For entranceLabel = "ulaz %s" gives "Main street 11A ulaz 2"
        appendTo(out, " ", entranceLabelFormat, Tag.ENTRANCE);

        // For floorLabel = "%s. sprat" gives "Main street 11 ulaz 2, 5. sprat"
        appendTo(out, ", ", floorLabelFormat, Tag.FLOOR);

        if (has(Tag.APPARTMENT_NUMBER)) {
            // For appartmentLabel "br. %s" gives "Main street 11 ulaz 2, 5. sprat, br. 4"
            if (has(Tag.ENTRANCE) || has(Tag.FLOOR)) {
                appendTo(out, ", ", appartmentLabelFormat, Tag.APPARTMENT_NUMBER);
            } else {
                // short form: Main street 11A/4
                appendTo(out, "/", Tag.APPARTMENT_NUMBER);
            }
        }

        appendTo(out, "\n", Tag.PLACE);
        appendTo(out, ", ", Tag.COMMUNITY);

        String rawState = get(Tag.STATE);

        out.append("\n");

        if (rawState.contentEquals("SRB")) {
            // small cheat for a better output
            out.append("REPUBLIKA SRBIJA");
        } else {
            out.append(rawState);
        }

        return out.toString();
    }

    /**
     * Get full place of birth as a multiline string, including community and state if present.
     *
     * @return Nicely formatted place of birth as a multiline string.
     */
    public String getPlaceOfBirthFull() {
        StringBuilder out = new StringBuilder();

        appendTo(out, Tag.PLACE_OF_BIRTH);
        appendTo(out, ", ", Tag.COMMUNITY_OF_BIRTH);
        appendTo(out, "\n", Tag.STATE_OF_BIRTH);

        return out.toString();
    }

    public String getDocRegNo() {
        return get(Tag.DOC_REG_NO);
    }

    public String getIssuingDate() {
        return formatDate(get(Tag.ISSUING_DATE));
    }

    public String getExpiryDate() {
        return formatDate(get(Tag.EXPIRY_DATE));
    }

    public String getIssuingAuthority() {
        return get(Tag.ISSUING_AUTHORITY);
    }

    public String getPersonalNumber() {
        return get(Tag.PERSONAL_NUMBER);
    }

    public String getSurname() {
        return get(Tag.SURNAME);
    }

    public String getGivenName() {
        return get(Tag.GIVEN_NAME);
    }

    public String getParentGivenName() {
        return get(Tag.PARENT_GIVEN_NAME);
    }

    public String getSex() {
        return get(Tag.SEX);
    }

    public String getPlaceOfBirth() {
        return get(Tag.PLACE_OF_BIRTH);
    }

    public String getCommunityOfBirth() {
        return get(Tag.COMMUNITY_OF_BIRTH);
    }

    public String getStateOfBirth() {
        return get(Tag.STATE_OF_BIRTH);
    }

    public String getDateOfBirth() {
        return formatDate(get(Tag.DATE_OF_BIRTH));
    }

    public String getState() {
        return get(Tag.STATE);
    }

    public String getCommunity() {
        return get(Tag.COMMUNITY);
    }

    public String getPlace() {
        return get(Tag.PLACE);
    }

    public String getStreet() {
        return get(Tag.STREET);
    }

    public String getHouseNumber() {
        return get(Tag.HOUSE_NUMBER);
    }

    public String getHouseLetter() {
        return get(Tag.HOUSE_LETTER);
    }

    public String getEntrance() {
        return get(Tag.ENTRANCE);
    }

    public String getFloor() {
        return get(Tag.FLOOR);
    }

    public String getAppartmentNumber() {
        return get(Tag.APPARTMENT_NUMBER);
    }

    public String getAddressDate() {
        String value = get(Tag.ADDRESS_DATE);
        if (value == null || value.equals("01010001"))
            return null;
        return formatDate(get(Tag.APPARTMENT_NUMBER));
    }

    @Override
    public String toString() {
        StringBuilder out = new StringBuilder();
        for (Map.Entry<Tag, String> field : fields.entrySet()) {
            out.append(String.format("%s: %s", field.getKey(), field.getValue()));
        }
        return out.toString();
    }

    @SuppressWarnings("unchecked")
    public JSONObject toJSON() {
        JSONObject obj = new JSONObject();
        obj.put("name_full", getNameFull());
        obj.put("place_full", getPlaceFull("ulaz %s", "%s. sprat", "br. %s"));
        obj.put("place_of_birth_full", getPlaceOfBirthFull());
        for (Map.Entry<Tag, String> field : fields.entrySet()) {
            Tag tag = field.getKey();
            obj.put(tag.getKey(), field.getValue());
        }
        return obj;
    }
}