au.com.scds.chats.dom.general.Person.java Source code

Java tutorial

Introduction

Here is the source code for au.com.scds.chats.dom.general.Person.java

Source

/*
 *
 *  Copyright 2015 Stephen Cameron Data Services
 *
 *
 *  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.
 */
package au.com.scds.chats.dom.general;

import java.util.Date;
import java.util.List;

import javax.inject.Inject;

import javax.jdo.annotations.Column;
import javax.jdo.annotations.DatastoreIdentity;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Queries;
import javax.jdo.annotations.Query;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.Unique;

import org.apache.isis.applib.DomainObjectContainer;
import org.apache.isis.applib.annotation.*;

import org.isisaddons.wicket.gmap3.cpt.applib.Locatable;
import org.isisaddons.wicket.gmap3.cpt.applib.Location;
import org.isisaddons.wicket.gmap3.cpt.service.LocationLookupService;
import org.joda.time.Interval;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.joda.time.Years;

import au.com.scds.chats.dom.AbstractChatsDomainEntity;
import au.com.scds.chats.dom.RegexValidation;
import au.com.scds.chats.dom.general.Person;
import au.com.scds.chats.dom.general.names.ContactType;
import au.com.scds.chats.dom.general.names.ContactTypes;
import au.com.scds.chats.dom.general.names.EnglishSkill;
import au.com.scds.chats.dom.general.names.Region;
import au.com.scds.chats.dom.general.names.Regions;
import au.com.scds.chats.dom.general.names.Salutation;
import au.com.scds.chats.dom.general.names.Salutations;

@PersistenceCapable(identityType = IdentityType.DATASTORE)
@Unique(name = "Person_UNQ", members = { "firstname", "surname", "birthdate" })
@Queries({
        @Query(name = "findPersonsBySurname", language = "JDOQL", value = "SELECT "
                + "FROM au.com.scds.chats.dom.general.Person WHERE surname == :surname"),
        @Query(name = "findPersonBySLK", language = "JDOQL", value = "SELECT "
                + "FROM au.com.scds.chats.dom.general.Person WHERE slk == :slk"),
        @Query(name = "findPersonByOldId", language = "JDOQL", value = "SELECT "
                + "FROM au.com.scds.chats.dom.general.Person WHERE oldId == :oldid"),
        @Query(name = "findPerson", language = "JDOQL", value = "SELECT "
                + "FROM au.com.scds.chats.dom.general.Person "
                + "WHERE firstname == :firstname && surname == :surname && birthdate == :birthdate"), })
@DomainObject(objectType = "PERSON")
@DomainObjectLayout(bookmarking = BookmarkPolicy.AS_ROOT)
@MemberGroupLayout(columnSpans = { 6, 6, 0, 12 }, left = "General", middle = { "Contact Details", "Admin" })
public class Person extends AbstractChatsDomainEntity implements Locatable, Comparable<Person> {

    private Long oldId;
    private Salutation salutation;
    private ContactType contactType;
    private EnglishSkill englishSkill;
    private String firstname;
    private String middlename;
    private String surname;
    private String preferredname;
    private String slk;
    private LocalDate birthdate;
    private Address streetAddress;
    private Address mailAddress;
    private String homePhoneNumber;
    private String mobilePhoneNumber;
    private String fixedPhoneNumber;
    private String faxNumber;
    private String emailAddress;
    private Sex sex;

    public Person() {
        super();
    }

    public Person(String firstName, String surname, LocalDate birthdate) {
        super();
        this.firstname = firstName;
        this.surname = surname;
        this.birthdate = birthdate;
    }

    public String title() {
        return this.getFullname();
    }

    @Property()
    // @PropertyLayout(hidden = Where.EVERYWHERE)
    @Column(allowsNull = "true")
    public Long getOldId() {
        return this.oldId;
    }

    public void setOldId(Long id) {
        this.oldId = id;
    }

    @Programmatic
    public String getFullname() {
        return this.getFirstname() + " "
                + (this.getPreferredname() != null ? "(" + this.getPreferredname() + ") " : "")
                + (this.getMiddlename() != null ? this.getMiddlename() + " " : "") + this.getSurname();
    }

    @Property()
    // @PropertyLayout(hidden = Where.EVERYWHERE)
    // @MemberOrder(sequence = "1")
    @Column(allowsNull = "true")
    public Salutation getSalutation() {
        return this.salutation;
    }

    public void setSalutation(Salutation salutationId) {
        this.salutation = salutationId;
    }

    public List<Salutation> choicesSalutation() {
        return salutations.listAllSalutations();
    }

    @Property()
    // @PropertyLayout(named = "Salutation")
    // @MemberOrder(sequence = "1")
    @NotPersistent
    public String getSalutationName() {
        return getSalutation() != null ? this.getSalutation().getName() : null;
    }

    public void setSalutationName(String name) {
        this.setSalutation(salutations.salutationForName(name));
    }

    public List<String> choicesSalutationName() {
        return salutations.allNames();
    }

    @Property(editing = Editing.DISABLED, editingDisabledReason = "Set at person creation")
    // @PropertyLayout(named = "First Name")
    // @MemberOrder(sequence = "2")
    @Column(allowsNull = "false", length = 100)
    public String getFirstname() {
        return this.firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    @Property()
    // @PropertyLayout(named = "Middle Name(s)")
    // @MemberOrder(sequence = "3")
    @Column(allowsNull = "true", length = 100)
    public String getMiddlename() {
        return this.middlename;
    }

    public void setMiddlename(String middlename) {
        this.middlename = middlename;
    }

    @Property(editing = Editing.DISABLED, editingDisabledReason = "Set at person creation")
    // @PropertyLayout()
    // @MemberOrder(sequence = "4")
    @Column(allowsNull = "false", length = 100)
    public String getSurname() {
        return this.surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    @Property()
    // @PropertyLayout(named = "Preferred Name")
    // @MemberOrder(sequence = "5")
    @Column(allowsNull = "true", length = 100)
    public String getPreferredname() {
        return this.preferredname;
    }

    public void setPreferredname(String preferredname) {
        this.preferredname = preferredname;
    }

    @Property(editing = Editing.DISABLED, editingDisabledReason = "Set person at creation")
    // @PropertyLayout()
    // @MemberOrder(sequence = "6")
    @Column(allowsNull = "false")
    public LocalDate getBirthdate() {
        return this.birthdate;
    }

    public void setBirthdate(LocalDate localDate) {
        this.birthdate = localDate;
    }

    @Property(editing = Editing.DISABLED, editingDisabledReason = "Set at person creation")
    // @PropertyLayout()
    // @MemberOrder(sequence = "7")
    @Column(allowsNull = "false")
    public Sex getSex() {
        return sex;
    }

    public void setSex(Sex sex) {
        this.sex = sex;
    }

    @Property(editing = Editing.DISABLED, editingDisabledReason = "Set at person creation")
    @PropertyLayout(named = "Stat. Linkage Key")
    // @MemberOrder(sequence = "7")
    @Column(allowsNull = "false")
    public String getSlk() {
        return slk;
    }

    private void setSlk(String slk) {
        this.slk = slk;
    }

    @Programmatic
    // Creates a Statistical Linkage Key (SLK) for DEX reporting
    public void buildSlk() throws Exception {

        // validate inputs
        if (getFirstname() == null || getFirstname().trim().equals(""))
            throw new Exception("Person's first name is not set!");
        if (getSurname() == null || getSurname().trim().equals(""))
            throw new Exception("Person's surname is not set!");
        if (getBirthdate() == null)
            throw new Exception("Person's birthdate is not set!");
        if (getSex() == null)
            throw new Exception("Person's sex is not set!");

        // remove all spaces
        String firstname = getFirstname().replace(" ", "");
        String surname = getSurname().replace(" ", "");

        // build the key
        StringBuffer buffer = new StringBuffer();
        // surname
        buffer.append(surname.substring(1, 2).toUpperCase());
        if (surname.length() > 2)
            buffer.append(surname.substring(2, 3).toUpperCase());
        else
            buffer.append("2");
        if (surname.length() > 4)
            buffer.append(surname.substring(4, 5).toUpperCase());
        else
            buffer.append("2");
        // firstname
        buffer.append(firstname.substring(1, 2).toUpperCase());
        if (firstname.length() > 2)
            buffer.append(firstname.substring(2, 3).toUpperCase());
        else
            buffer.append("2");
        buffer.append(getBirthdate().toString("ddMMYYYY"));
        buffer.append(getSex() == Sex.MALE ? "1" : "2");
        setSlk(buffer.toString());
    }

    @Property()
    @Column(allowsNull = "true")
    public ContactType getContactType() {
        return this.contactType;
    }

    public void setContactType(ContactType contacttypeId) {
        this.contactType = contacttypeId;
    }

    @Property()
    // @PropertyLayout(named = "Contact Type")
    // @MemberOrder(sequence = "8.1")
    @NotPersistent
    public String getContactTypeName() {
        return getContactType() != null ? this.getContactType().getName() : null;
    }

    public void setContactTypeName(String name) {
        this.setContactType(contactTypes.contactTypeForName(name));
    }

    public List<String> choicesContactTypeName() {
        return contactTypes.allNames();
    }

    @Property(editing = Editing.DISABLED)
    // @PropertyLayout(hidden = Where.ALL_TABLES)
    // //@MemberOrder(name = "Contact Details", sequence = "1")
    @Column(allowsNull = "true")
    public Address getStreetAddress() {
        return streetAddress;
    }

    public void setStreetAddress(final Address streetAddress) {
        this.streetAddress = streetAddress;
    }

    @Programmatic
    public String getFullStreetAddress() {
        if (getStreetAddress() == null)
            return "Unknown";
        else
            return getStreetAddress().title();
    }

    @Action(semantics = SemanticsOf.IDEMPOTENT)
    // //@MemberOrder(name = "streetaddress", sequence = "1")
    public Person updateStreetAddress(@ParameterLayout(named = "Street 1") String street1,
            @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named = "Street 2") String street2,
            @Parameter(optionality = Optionality.MANDATORY) @ParameterLayout(named = "Suburb") Suburb suburb,
            @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named = "Is Mail Address Too?") boolean isMailAddress) {
        Address newAddress = container.newTransientInstance(Address.class);
        newAddress.setStreet1(street1);
        newAddress.setStreet2(street2);
        newAddress.setPostcode(suburb.getPostcode().toString());
        newAddress.setSuburb(suburb.getName());
        // do geocoding, don't fail action if not geocoded
        newAddress.updateGeocodedLocation();
        Address oldAddress = getStreetAddress();
        container.persistIfNotAlready(newAddress);
        setStreetAddress(newAddress);
        // remove old address(es) if replacing both
        // TODO this is maybe too complex? prevent orphan addresses
        if (isMailAddress == true) {
            if (getMailAddress() != null && !getMailAddress().equals(oldAddress)) {
                container.removeIfNotAlready(getMailAddress());
            }
            setMailAddress(newAddress);
            if (oldAddress != null) {
                container.removeIfNotAlready(oldAddress);
            }
        }
        return this;
    }

    public String default0UpdateStreetAddress() {
        return getStreetAddress() != null ? getStreetAddress().getStreet1() : null;
    }

    public String default1UpdateStreetAddress() {
        return getStreetAddress() != null ? getStreetAddress().getStreet2() : null;
    }

    public Suburb default2UpdateStreetAddress() {
        return getStreetAddress() != null
                ? suburbs.findSuburb(getStreetAddress().getSuburb(), new Integer(getStreetAddress().getPostcode()))
                : null;
    }

    public List<Suburb> choices2UpdateStreetAddress() {
        return suburbs.listAllSuburbs();
    }

    // public String default3UpdateStreetAddress() {
    // return getStreetAddress() != null ? getStreetAddress().getPostcode() :
    // null;
    // }

    public boolean default3UpdateStreetAddress() {
        return false;
    }

    /*
     * public List<String> autoComplete2UpdateStreetAddress(@MinLength(3) String
     * search) { System.out.println("SEARCHING"); return
     * suburbs.listSuburbNamesLike(search); }
     * 
     * public String validate2UpdateStreetAddress(String name) { Suburb s =
     * suburbs.suburbForName(name); if (s != null) { return null; } else return
     * "Unknown suburb, please check spelling and use proper case"; }
     */

    @Property(editing = Editing.DISABLED)
    // @PropertyLayout(hidden = Where.ALL_TABLES)
    // //@MemberOrder(name = "Contact Details", sequence = "2")
    @Column(allowsNull = "true")
    public Address getMailAddress() {
        return mailAddress;
    }

    public void setMailAddress(final Address mailAddress) {
        this.mailAddress = mailAddress;
    }

    @Programmatic
    public String getFullMailAddress() {
        if (getMailAddress() == null)
            return "Unknown";
        else
            return getMailAddress().title();
    }

    @Action(semantics = SemanticsOf.IDEMPOTENT)
    // //@MemberOrder(name = "mailaddress", sequence = "1")
    public Person updateMailAddress(@ParameterLayout(named = "Street 1") String street1,
            @Parameter(optionality = Optionality.OPTIONAL) @ParameterLayout(named = "Street 2") String street2,
            @ParameterLayout(named = "Suburb") String suburb,
            @ParameterLayout(named = "Postcode") String postcode) {
        Address newAddress = container.newTransientInstance(Address.class);
        newAddress.setStreet1(street1);
        newAddress.setStreet2(street2);
        newAddress.setPostcode(postcode);
        newAddress.setSuburb(suburb);
        Address oldMailAddress = getMailAddress();
        container.persist(newAddress);
        setMailAddress(newAddress);
        if (oldMailAddress != null && oldMailAddress != getStreetAddress())
            container.removeIfNotAlready(oldMailAddress);
        return this;
    }

    public String default0UpdateMailAddress() {
        return getMailAddress() != null ? getMailAddress().getStreet1() : null;
    }

    public String default1UpdateMailAddress() {
        return getMailAddress() != null ? getMailAddress().getStreet2() : null;
    }

    public String default2UpdateMailAddress() {
        return getMailAddress() != null ? getMailAddress().getSuburb() : null;
    }

    public String default3UpdateMailAddress() {
        return getMailAddress() != null ? getMailAddress().getPostcode() : null;
    }

    @Property(regexPattern = RegexValidation.CommunicationChannel.PHONENUMBER)
    // @PropertyLayout(named = "Home Phone Number")
    // @MemberOrder(name = "Contact Details", sequence = "3")
    @Column(allowsNull = "true")
    public String getHomePhoneNumber() {
        return homePhoneNumber;
    }

    public void setHomePhoneNumber(final String homePhoneNumber) {
        this.homePhoneNumber = homePhoneNumber;
    }

    @Property(regexPattern = RegexValidation.CommunicationChannel.PHONENUMBER)
    // @PropertyLayout(named = "Mobile Phone Number")
    // @MemberOrder(name = "Contact Details", sequence = "4")
    @Column(allowsNull = "true")
    public String getMobilePhoneNumber() {
        return mobilePhoneNumber;
    }

    public void setMobilePhoneNumber(final String mobilePhoneNumber) {
        this.mobilePhoneNumber = mobilePhoneNumber;
    }

    @Property(regexPattern = RegexValidation.CommunicationChannel.PHONENUMBER)
    // @PropertyLayout(named = "Fixed Phone Number")
    // @MemberOrder(name = "Contact Details", sequence = "5")
    @Column(allowsNull = "true")
    public String getFixedPhoneNumber() {
        return fixedPhoneNumber;
    }

    public void setFixedPhoneNumber(String fixedPhoneNumber) {
        this.fixedPhoneNumber = fixedPhoneNumber;
    }

    @Property(regexPattern = RegexValidation.CommunicationChannel.PHONENUMBER)
    // @PropertyLayout(named = "Fax Number")
    // @MemberOrder(name = "Contact Details", sequence = "6")
    @Column(allowsNull = "true")
    public String getFaxNumber() {
        return faxNumber;
    }

    public void setFaxNumber(String faxNumber) {
        this.faxNumber = faxNumber;
    }

    @Property(regexPattern = RegexValidation.CommunicationChannel.EMAIL)
    // @PropertyLayout(hidden = Where.ALL_TABLES, named = "Email Address")
    // @MemberOrder(name = "Contact Details", sequence = "5")
    @Column(allowsNull = "true")
    public String getEmailAddress() {
        return emailAddress;
    }

    public void setEmailAddress(final String emailAddress) {
        this.emailAddress = emailAddress;
    }

    @Property(editing = Editing.DISABLED)
    // @PropertyLayout(named = "English Skill")
    // @MemberOrder(sequence = "16")
    @Column(allowsNull = "true")
    public EnglishSkill getEnglishSkill() {
        return this.englishSkill;
    }

    public void setEnglishSkill(EnglishSkill englishSkill) {
        this.englishSkill = englishSkill;
    }

    @Action(semantics = SemanticsOf.NON_IDEMPOTENT_ARE_YOU_SURE)
    // Provide a means to change the identifying unique key properties
    public Person updateIdentity(
            @Parameter(optionality = Optionality.MANDATORY) @ParameterLayout(named = "First name") String firstname,
            @Parameter(optionality = Optionality.MANDATORY) @ParameterLayout(named = "Surname") String surname,
            @Parameter(optionality = Optionality.MANDATORY) @ParameterLayout(named = "Birthdate") LocalDate birthdate,
            @Parameter(optionality = Optionality.MANDATORY) @ParameterLayout(named = "Sex") Sex sex)
            throws Exception {
        Person existing = persons.findPerson(firstname, surname, birthdate);
        if (existing == null) {
            // transactional
            setFirstname(firstname);
            setSurname(surname);
            setBirthdate(birthdate);
            setSex(sex);
            buildSlk();
        } else {
            container.warnUser("Such a person already exists!");
        }
        return this;
    }

    public String default0UpdateIdentity() {
        return getFirstname();
    }

    public String default1UpdateIdentity() {
        return getSurname();
    }

    public LocalDate default2UpdateIdentity() {
        return getBirthdate();
    }

    public Sex default3UpdateIdentity() {
        return getSex();
    }

    @Programmatic()
    public Integer getDaysUntilBirthday(LocalDate futureDate) {
        if (futureDate == null)
            futureDate = LocalDate.now();
        Integer diff = getBirthdate().getDayOfYear() - futureDate.getDayOfYear();
        if (diff < 0) {
            return 365 + diff;
        } else {
            return diff;
        }
    }

    @Programmatic()
    public Integer getAge(LocalDate futureDate) {
        if (futureDate == null)
            futureDate = LocalDate.now();
        Period p = new Period(getBirthdate(), futureDate);
        return p.getYears();
    }

    @NotPersistent
    public org.isisaddons.wicket.gmap3.cpt.applib.Location getLocation() {
        if (getStreetAddress() != null)
            return getStreetAddress().getLocation();
        else
            return null;
    }

    @Override
    public int compareTo(Person o) {
        String thisNameAndBirthdate = getSurname().toUpperCase() + getFirstname().toUpperCase() + getBirthdate();
        String otherNameAndBirthdate = o.getSurname().toUpperCase() + o.getFirstname().toUpperCase()
                + o.getBirthdate();
        ;
        return thisNameAndBirthdate.compareTo(otherNameAndBirthdate);
    }

    @Inject
    private Persons persons;

    @Inject
    private Salutations salutations;

    @Inject
    private Suburbs suburbs;

    @Inject
    ContactTypes contactTypes;

    @Inject
    private DomainObjectContainer container;

}