org.openregistry.core.domain.jpa.JpaRoleImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.openregistry.core.domain.jpa.JpaRoleImpl.java

Source

/**
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you 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 org.openregistry.core.domain.jpa;

import org.hibernate.annotations.Index;
import org.openregistry.core.domain.*;
import org.openregistry.core.domain.internal.Entity;
import org.openregistry.core.domain.jpa.sor.JpaSorRoleImpl;
import org.openregistry.core.domain.sor.SorRole;
import org.hibernate.envers.Audited;
import org.openregistry.core.domain.sor.SystemOfRecord;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.*;
import javax.validation.Valid;

import org.slf4j.*;

/**
 * Role entity mapped to a persistence store with JPA annotations.
 *
 * Unique constraints assume that each person can have only one record of each role
 *
 * @author Scott Battaglia
 * @version $Revision$ $Date$
 * @since 1.0.0
 */
// TODO should a person be able to have multiple entries for the same role?  Perhaps if the affiliation date is unique?
@javax.persistence.Entity(name = "role")
@Table(name = "prc_role_records", uniqueConstraints = @UniqueConstraint(columnNames = { "person_id",
        "affiliation_t", "organizational_unit_id" }))
@Audited
@org.hibernate.annotations.Table(appliesTo = "prc_role_records", indexes = {
        @Index(name = "PRC_ROLE_RECORDS_PRS_STAT_IDX", columnNames = "PERSON_STATUS_T"),
        @Index(name = "PRC_ROLE_RECORDS_SPONSOR_IDX", columnNames = "SPONSOR_T"),
        @Index(name = "PRC_ROLE_RECORDS_TERM_IDX", columnNames = "TERMINATION_T"),
        @Index(name = "PRC_ROLE_REC_PRS_ROLE_REC_IDX", columnNames = "PRS_ROLE_ID") })
public class JpaRoleImpl extends Entity implements Role {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "prc_role_records_seq")
    @SequenceGenerator(name = "prc_role_records_seq", sequenceName = "prc_role_records_seq", initialValue = 1, allocationSize = 50)
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY, targetEntity = JpaUrlImpl.class)
    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Url> urls = new HashSet<Url>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY, targetEntity = JpaEmailAddressImpl.class)
    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<EmailAddress> emailAddresses = new HashSet<EmailAddress>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY, targetEntity = JpaPhoneImpl.class)
    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Phone> phones = new HashSet<Phone>();

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY, targetEntity = JpaAddressImpl.class)
    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Address> addresses = new HashSet<Address>();

    @Column(name = "sponsor_id", nullable = false)
    private Long sponsorId;

    @ManyToOne(optional = false, targetEntity = JpaTypeImpl.class)
    @JoinColumn(name = "sponsor_t")
    private Type sponsorType;

    @Column(name = "percent_time", nullable = false)
    private int percentage;

    @ManyToOne(optional = false, targetEntity = JpaTypeImpl.class)
    @JoinColumn(name = "person_status_t")
    private Type personStatus;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "role", fetch = FetchType.LAZY, targetEntity = JpaLeaveImpl.class)
    @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Leave> leaves = new HashSet<Leave>();

    @Column(name = "title", nullable = false, length = 100)
    private String title;

    @ManyToOne(optional = false)
    @JoinColumn(name = "organizational_unit_id")
    private JpaOrganizationalUnitImpl organizationalUnit;

    @ManyToOne(optional = false)
    @JoinColumn(name = "affiliation_t")
    private JpaTypeImpl affiliationType;

    @ManyToOne(optional = false)
    @JoinColumn(name = "person_id", nullable = false)
    private JpaPersonImpl person;

    @Column(name = "affiliation_date", nullable = false)
    @Temporal(TemporalType.DATE)
    private Date start;

    @Column(name = "termination_date")
    @Temporal(TemporalType.DATE)
    private Date end;

    @ManyToOne(targetEntity = JpaTypeImpl.class)
    @JoinColumn(name = "termination_t")
    private Type terminationReason;

    @Column(name = "prs_role_id", nullable = true)
    private Long sorRoleId;

    public JpaRoleImpl() {
        // nothing to do
    }

    public JpaRoleImpl(final JpaOrganizationalUnitImpl organizationalUnit, final String title,
            final JpaTypeImpl affiliationType, final JpaPersonImpl person) {
        this.organizationalUnit = organizationalUnit;
        this.title = title;
        this.affiliationType = affiliationType;
        this.person = person;
    }

    public JpaRoleImpl(final JpaSorRoleImpl sorRole, final JpaPersonImpl person) {
        this((JpaOrganizationalUnitImpl) sorRole.getOrganizationalUnit(), (String) sorRole.getTitle(),
                (JpaTypeImpl) sorRole.getAffiliationType(), person);
        recalculate(sorRole);
    }

    @Override
    public Long getId() {
        return this.id;
    }

    public Long getSorRoleId() {
        return this.sorRoleId;
    }

    public Set<Address> getAddresses() {
        return this.addresses;
    }

    public Set<Phone> getPhones() {
        return this.phones;
    }

    public Set<EmailAddress> getEmailAddresses() {
        return this.emailAddresses;
    }

    public Set<Url> getUrls() {
        return this.urls;
    }

    protected Address addAddress(final Address sorAddress) {
        final JpaAddressImpl jpaAddress = new JpaAddressImpl(this);
        jpaAddress.setLine1(sorAddress.getLine1());
        jpaAddress.setLine2(sorAddress.getLine2());
        jpaAddress.setLine3(sorAddress.getLine3());
        jpaAddress.setCity(sorAddress.getCity());
        jpaAddress.setRegion(sorAddress.getRegion());
        jpaAddress.setPostalCode(sorAddress.getPostalCode());
        jpaAddress.setCountry(sorAddress.getCountry());
        jpaAddress.setBldgNo(sorAddress.getBldgNo());
        jpaAddress.setRoomNo(sorAddress.getRoomNo());

        jpaAddress.setType(sorAddress.getType());
        this.addresses.add(jpaAddress);
        return jpaAddress;
    }

    protected Url addUrl(final Url sorUrl) {
        final JpaUrlImpl url = new JpaUrlImpl(this);
        url.setUrl(sorUrl.getUrl());
        url.setType(sorUrl.getType());
        this.urls.add(url);
        return url;
    }

    protected EmailAddress addEmailAddress(final EmailAddress sorEmailAddress) {
        final JpaEmailAddressImpl jpaEmailAddress = new JpaEmailAddressImpl(this);
        jpaEmailAddress.setAddress(sorEmailAddress.getAddress());
        jpaEmailAddress.setAddressType(sorEmailAddress.getAddressType());
        this.emailAddresses.add(jpaEmailAddress);
        return jpaEmailAddress;
    }

    protected Phone addPhone(final Phone sorPhone) {
        final JpaPhoneImpl jpaPhone = new JpaPhoneImpl(this);
        jpaPhone.setCountryCode(sorPhone.getCountryCode());
        jpaPhone.setAreaCode(sorPhone.getAreaCode());
        jpaPhone.setNumber(sorPhone.getNumber());
        jpaPhone.setExtension(sorPhone.getExtension());
        jpaPhone.setPhoneType(sorPhone.getPhoneType());
        jpaPhone.setAddressType(sorPhone.getAddressType());
        jpaPhone.setPhoneLineOrder(sorPhone.getPhoneLineOrder());
        this.phones.add(jpaPhone);
        return jpaPhone;
    }

    protected Leave addLeave(final Leave sorLeave) {
        final JpaLeaveImpl jpaLeaveImpl = new JpaLeaveImpl(this, sorLeave);
        this.leaves.add(jpaLeaveImpl);
        return jpaLeaveImpl;
    }

    public Long getSponsorId() {
        return this.sponsorId;
    }

    public Type getSponsorType() {
        return this.sponsorType;
    }

    public void setSponsorId(final Long id) {
        this.sponsorId = id;
    }

    public void setSponsorType(final Type type) {
        Assert.isInstanceOf(JpaTypeImpl.class, type);
        this.sponsorType = type;
    }

    public int getPercentage() {
        return this.percentage;
    }

    public Type getPersonStatus() {
        return this.personStatus;
    }

    public Set<Leave> getLeaves() {
        return this.leaves;
    }

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

    public void setTitle(String title) {
        this.title = title;
    }

    public OrganizationalUnit getOrganizationalUnit() {
        return this.organizationalUnit;
    }

    public void setOrganizationalUnit(OrganizationalUnit organizationalUnit) {
        Assert.isInstanceOf(JpaOrganizationalUnitImpl.class, organizationalUnit);
        this.organizationalUnit = (JpaOrganizationalUnitImpl) organizationalUnit;
    }

    public Type getAffiliationType() {
        return this.affiliationType;
    }

    public void setAffiliationType(Type affiliationType) {
        Assert.isInstanceOf(JpaTypeImpl.class, affiliationType);
        this.affiliationType = (JpaTypeImpl) affiliationType;
    }

    public Type getTerminationReason() {
        return this.terminationReason;
    }

    public Date getStart() {
        return this.start;
    }

    public Date getEnd() {
        return this.end;
    }

    public boolean isTerminated() {
        return ((this.end != null) && (this.end.compareTo(new Date()) <= 0));
    }

    @Override
    public boolean isNotYetActive() {
        return this.start.compareTo(new Date()) > 0;
    }

    @Override
    public boolean isActive() {
        return !isNotYetActive() && !isTerminated();
    }

    public String getDisplayableName() {
        return getTitle() + "/" + getOrganizationalUnit().getName();
    }

    public void expireNow(final Type terminationReason, final boolean orphaned) {
        Assert.isInstanceOf(JpaTypeImpl.class, terminationReason);
        //        Assert.isTrue(this.end == null || this.end.compareTo(new Date()) < 0, "this role has already been expired."); expire it again even if it is already expire
        this.end = new Date();
        this.terminationReason = terminationReason;
        if (orphaned) {
            this.sorRoleId = null;
        }
    }

    public void recalculate(final SorRole sorRole) {
        Logger logger = LoggerFactory.getLogger(getClass());
        logger.info("Role recalculate");
        this.personStatus = sorRole.getPersonStatus();
        this.start = sorRole.getStart();
        this.end = sorRole.getEnd();
        this.sorRoleId = sorRole.getId();
        this.percentage = sorRole.getPercentage();
        this.terminationReason = sorRole.getTerminationReason();
        this.setOrganizationalUnit(sorRole.getOrganizationalUnit());
        this.title = sorRole.getTitle();

        //The Easier way to recalculate is to clear the collections and just re-insert.  Unfortunately due to a document hibernate bug
        //this implementation was not possible.  Bug causes a unique constraint violation. The inserts are done before the deletes.
        //work around code below.
        //this.addresses.clear();
        //this.phones.clear();
        //this.emailAddresses.clear();
        //this.urls.clear();

        //currently leaves not fully implemented
        this.leaves.clear();
        for (final Leave leave : sorRole.getLeaves()) {
            addLeave(leave);
        }

        //put in code to work around Hibernate bug.
        recalculateAddresses(sorRole);
        recalculateEmailAddresses(sorRole);
        recalculatePhones(sorRole);
        recalculateUrls(sorRole);

        this.setSponsorId(sorRole.getSponsorId());
        this.setSponsorType(sorRole.getSponsorType());
    }

    protected void recalculateAddresses(SorRole sorRole) {
        //remove addresses from calculated role when they are not in sorRole.
        //unique constraint guarantees that there can be only one address of a given type per role.
        Set<Address> addressesToDelete = new HashSet<Address>();
        for (final Address cAddress : this.addresses) {
            boolean foundAddress = false;
            for (final Address sorAddress : sorRole.getAddresses()) {
                if (sorAddress.getType().getDescription().equals(cAddress.getType().getDescription()))
                    foundAddress = true;
            }
            if (!foundAddress)
                addressesToDelete.add(cAddress);
        }

        for (final Address address : addressesToDelete)
            this.addresses.remove(address);

        //add or update roles that are in sorRole in the calculated role.
        for (final Address sorAddress : sorRole.getAddresses()) {
            Address address = findAddress(sorAddress.getType());
            if (address == null) {
                addAddress(sorAddress);
            } else {
                address.setLine1(sorAddress.getLine1());
                address.setLine2(sorAddress.getLine2());
                address.setLine3(sorAddress.getLine3());
                address.setCity(sorAddress.getCity());
                address.setRegion(sorAddress.getRegion());
                address.setPostalCode(sorAddress.getPostalCode());
                address.setCountry(sorAddress.getCountry());
                address.setBldgNo(sorAddress.getBldgNo());
                address.setRoomNo(sorAddress.getRoomNo());
            }
        }
    }

    protected void recalculateEmailAddresses(SorRole sorRole) {
        //remove email addresses from calculated role when they are not in sorRole.
        //unique constraint guarantees that there can be only one emailaddress of a given type per role.
        Set<EmailAddress> emailsToDelete = new HashSet<EmailAddress>();
        for (final EmailAddress cEmailAddress : this.emailAddresses) {
            boolean foundAddress = false;
            for (final EmailAddress sorEmailAddress : sorRole.getEmailAddresses()) {
                if (sorEmailAddress.getAddressType().getDescription()
                        .equals(cEmailAddress.getAddressType().getDescription()))
                    foundAddress = true;
            }
            if (!foundAddress)
                emailsToDelete.add(cEmailAddress);
        }

        for (final EmailAddress email : emailsToDelete)
            this.emailAddresses.remove(email);

        for (final EmailAddress sorEmailAddress : sorRole.getEmailAddresses()) {
            EmailAddress emailAddress = findEmailAddress(sorEmailAddress.getAddressType());
            if (emailAddress == null) {
                addEmailAddress(sorEmailAddress);
            } else {
                emailAddress.setAddress(sorEmailAddress.getAddress());
            }
        }
    }

    protected void recalculatePhones(SorRole sorRole) {
        //remove phones from calculated role when they are not in sorRole.
        //unique constraint guarantees that there can be only one phone of a given type per role.
        Set<Phone> phonesToDelete = new HashSet<Phone>();
        for (final Phone cPhone : this.phones) {
            boolean found = false;
            for (final Phone sorPhone : sorRole.getPhones()) {
                if (sorPhone.getAddressType().getDescription().equals(cPhone.getAddressType().getDescription())
                        && sorPhone.getPhoneType().getDescription().equals(cPhone.getPhoneType().getDescription())
                        && sorPhone.getPhoneLineOrder().compareTo(cPhone.getPhoneLineOrder()) == 0)
                    found = true;
            }
            if (!found)
                phonesToDelete.add(cPhone);
        }

        for (final Phone phone : phonesToDelete)
            this.phones.remove(phone);

        for (final Phone sorPhone : sorRole.getPhones()) {
            Phone phone = findPhone(sorPhone.getAddressType(), sorPhone.getPhoneType(),
                    sorPhone.getPhoneLineOrder());
            if (phone == null) {
                addPhone(sorPhone);
            } else {
                phone.setCountryCode(sorPhone.getCountryCode());
                phone.setAreaCode(sorPhone.getAreaCode());
                phone.setNumber(sorPhone.getNumber());
                phone.setExtension(sorPhone.getExtension());
            }
        }
    }

    protected void recalculateUrls(SorRole sorRole) {
        //remove urls from calculated role when they are not in sorRole.
        Set<Url> urlsToDelete = new HashSet<Url>();
        for (final Url cUrl : this.urls) {
            boolean found = false;
            for (final Url sorUrl : sorRole.getUrls()) {
                if (sorUrl.getUrl().equals(cUrl))
                    found = true;
            }
            if (!found)
                urlsToDelete.add(cUrl);
        }

        for (final Url url : urlsToDelete)
            this.urls.remove(url);

        for (final Url sorUrl : sorRole.getUrls()) {
            Url url = findUrl(sorUrl);
            if (url == null) {
                addUrl(sorUrl);
            } else {
                url.setUrl(sorUrl.getUrl());
            }
        }
    }

    protected Address findAddress(Type type) {
        for (final Address address : this.addresses) {
            if (address.getType().getDescription().equals(type.getDescription()))
                return address;
        }
        return null;
    }

    protected EmailAddress findEmailAddress(Type type) {
        for (final EmailAddress emailAddress : this.emailAddresses) {
            if (emailAddress.getAddressType().getDescription().equals(type.getDescription()))
                return emailAddress;
        }
        return null;
    }

    protected Phone findPhone(Type addressType, Type phoneType, Integer phoneLineOrder) {
        for (final Phone phone : this.phones) {
            if (phone.getAddressType().getDescription().equals(addressType.getDescription())
                    && phone.getPhoneType().getDescription().equals(phoneType.getDescription())
                    && phone.getPhoneLineOrder().compareTo(phoneLineOrder) == 0)
                return phone;
        }
        return null;
    }

    protected Url findUrl(Url sorUrl) {
        for (final Url url : this.urls) {
            if (sorUrl.equals(url))
                return url;
        }
        return null;
    }

    @Override
    public int compareTo(final Role o) {
        // TODO implement
        return 0; //To change body of implemented methods use File | Settings | File Templates.
    }
}