FECRequest.java

package com.tradecloud.domain.model.fecrequest;

import com.tradecloud.common.base.PersistenceBase;
import com.tradecloud.domain.model.ForexGroup;
import com.tradecloud.domain.model.Money;
import com.tradecloud.domain.model.audit.AuditEvent;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import org.hibernate.annotations.Type;
import org.joda.time.LocalDate;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.persistence.*;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.util.List;

import static com.tradecloud.domain.helper.XMLHelper.*;

@Entity
@Table(name = "fecrequest")
public class FECRequest extends PersistenceBase {

    private static final long serialVersionUID = 1L;

    @Embedded
    @AttributeOverrides({@AttributeOverride(name = "currency", column = @Column(name = "amount_currency")),
            @AttributeOverride(name = "value", column = @Column(name = "amount_value", precision = 19, scale = 6))})
    private Money amount;

    @Column(name = "maturity_date")
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
    private LocalDate maturityDate;

    @Enumerated(value = EnumType.STRING)
    @Column(name = "status", nullable = false)
    private FECRequestStatusType status;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "organisationalunit_id")
    private OrganisationalUnit organisationalUnit;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    // don't want to create new OrganisationalUnit objects for Deal only resuse
    // existing ones
    @JoinColumn(name = "forexgroup_id")
    private ForexGroup forexGroup;

    // For JPA only
    public FECRequest() {
    }

    public static FECRequest instanceOf(Money amount, LocalDate maturityDate, OrganisationalUnit organisationalUnit, ForexGroup forexGroup) {
        FECRequest fecRequest = new FECRequest(amount, maturityDate, organisationalUnit, forexGroup);
        return fecRequest;
    }

    private FECRequest(Money amount, LocalDate maturityDate, OrganisationalUnit organisationalUnit, ForexGroup forexGroup) {
        this.amount = amount;
        this.maturityDate = maturityDate;
        this.status = FECRequestStatusType.REQUESTED;
        this.organisationalUnit = organisationalUnit;
        this.forexGroup = forexGroup;
    }

    public LocalDate getMaturityDate() {
        return maturityDate;
    }

    public void updateMaturityDate(LocalDate maturityDate) {
        this.maturityDate = maturityDate;
    }

    public Money getAmount() {
        return amount;
    }

    // public FECRequest update(Money amount, LocalDate maturityDate) {
    // this.amount = amount;
    // this.updateMaturityDate(maturityDate);
    // return this;
    // }

    public FECRequest update(Money amount, LocalDate maturityDate, OrganisationalUnit organisationalUnit, ForexGroup forexGroup) {
        this.amount = amount;
        this.updateMaturityDate(maturityDate);
        this.organisationalUnit = organisationalUnit;
        this.forexGroup = forexGroup;
        return this;
    }

    public void authorise() {
        status = FECRequestStatusType.AUTHORISED;
    }

    public boolean isAuthorised() {
        return FECRequestStatusType.AUTHORISED.equals(status);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        FECRequest that = (FECRequest) o;

        if (getId() != that.getId())
            return false;
        if (amount != null ? !amount.equals(that.amount) : that.amount != null)
            return false;
        if (maturityDate != null ? !maturityDate.equals(that.maturityDate) : that.maturityDate != null)
            return false;
        if (status != that.status)
            return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = (int) (getId() ^ (getId() >>> 32));
        result = 31 * result + (amount != null ? amount.hashCode() : 0);
        result = 31 * result + (maturityDate != null ? maturityDate.hashCode() : 0);
        result = 31 * result + (status != null ? status.hashCode() : 0);
        return result;
    }

    public String getStateAsXML() {
        try {
            Document document = null;
            document = makeNewDocument();
            Element rootElement = document.createElement("fecRequest");
            document.appendChild(rootElement);

            makeElementAndAddToRootElement(document, "fecRequestReference", Long.toString(getId()));
            makeElementAndAddToRootElement(document, "maturityDate", maturityDate.toString());
            makeElementAndAddToRootElement(document, "status", status().getStatusName());

            Element moneyElement = makeAndAppendMoneyElement(document, "amount", amount);
            rootElement.appendChild(moneyElement);
            rootElement.appendChild(makeAndAppendOrganisationalUnitElement(document, "division", organisationalUnit));
            rootElement.appendChild(makeAndAppendForexGroupElement(document, "ForexGroup", forexGroup));
            return documentAsXML(document);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        } catch (TransformerException e) {
            throw new RuntimeException(e);
        }
    }

    public FECRequestStatusType status() {
        return status;
    }

    public FECRequestStatusType getStatus() {
        return status;
    }

    public FECRequest delete() {
        status = FECRequestStatusType.DELETED;
        return this;
    }

    public FECRequest establishFEC() {
        status = FECRequestStatusType.FECESTABLISHED;
        return this;
    }

    public String getAuditEventsAsXML(List<AuditEvent> events) {
        StringBuilder builder = new StringBuilder();
        builder.append("<stateHistory>");
        builder.append(getStateAsXML());
        builder.append("<auditEvents>");
        for (AuditEvent event : events) {
            builder.append(event.getStateAsXML());
        }
        builder.append("</auditEvents>");
        builder.append("</stateHistory>");
        return builder.toString();
    }

    public OrganisationalUnit getOrganisationalUnit() {
        return organisationalUnit;
    }

    public void setOrganisationalUnit(OrganisationalUnit organisationalUnit) {
        this.organisationalUnit = organisationalUnit;
    }

    public ForexGroup getForexGroup() {
        return forexGroup;
    }

    public void setForexGroup(ForexGroup forexGroup) {
        this.forexGroup = forexGroup;
    }
}