Snapshot.java

package com.tradecloud.domain.model.accounting;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.annotations.AccessType;
import org.hibernate.annotations.Type;

import javax.persistence.*;
import javax.xml.bind.DatatypeConverter;
import java.io.Serializable;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;

/**
 * Representation of a cost message.
 */

@Entity
@Table(name = "snapshot")
@AccessType("field")
@NamedQueries({@NamedQuery(
        name = "findSnapshots",
        query = "SELECT ss FROM Snapshot ss " +
                "WHERE ss.reference = :reference " +
                "AND ss.consumerTag = :consumerTag " +
                "AND ss.snapshotType = :snapshotType " +
                "AND ss.acknowledgeEventId IS NULL " +
                "AND EXISTS ( " +
                "       SELECT 1 FROM Event e " +
                "       WHERE e.id = ss.eventId " +
                ") " +
                "ORDER BY ss.id ASC"),
        @NamedQuery(query = "select ss from Snapshot ss " +
                "where ss.reference = :reference " +
                "and ss.consumerTag = :consumerTag " +
                "and ss.snapshotType = :snapshotType " +
                "and ss.shipmentNumber = :shipmentNumber " +
                "AND ss.acknowledgeEventId IS NULL " +
                "AND EXISTS ( " +
                "       SELECT 1 FROM Event e " +
                "       WHERE e.id = ss.eventId " +
                ") " +
                "order by ss.id ASC",
                name = "findSnapshotsByShipment"),
        @NamedQuery(query = "select ss from Snapshot ss " +
                "where ss.reference = :reference " +
                "and ss.consumerTag = :consumerTag " +
                "and ss.snapshotType = :snapshotType " +
                "AND EXISTS ( " +
                "       SELECT 1 FROM Event e " +
                "       WHERE e.id = ss.eventId " +
                ") " +
                "AND ss.acknowledgeEventId IS NULL " +
                "order by ss.id ASC", name = "findSnapshotsByReference")})
public class Snapshot implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;
    @Column(name = "reference")
    private String reference;
    @Column(name = "shipmentnumber")
    private String shipmentNumber;
    @Column(name = "timestamp")
    private Date timeStamp;
    @Enumerated(EnumType.STRING)
    @Column(name = "snapshotType")
    private SnapshotType snapshotType;
    @Column(name = "consumerTag")
    private String consumerTag;
    @Lob
    @Type(type = "org.hibernate.type.TextType")
    @Column(name = "message")
    @Basic(fetch = FetchType.LAZY)
    private String message;
    //set on acknowledge, as there is no direct link between event and snapshot.
    //on reinstate clear this field
    private Long acknowledgeEventId;
    private Long eventId;
    private String md5Sum;

    /**
     * Constructor for Message. used by hibernate.
     */
    public Snapshot() {
    }

    public Snapshot(final String reference, String shipmentNumber, final Date timeStamp, final SnapshotType snapshotType,
                    String consumerTag, String message) {
        this.reference = reference;
        this.shipmentNumber = shipmentNumber;
        this.timeStamp = timeStamp;
        this.snapshotType = snapshotType;
        this.consumerTag = consumerTag;
        this.message = message;

        md5Sum = messageToMd5Sum(message);
    }

    public static String messageToMd5Sum(String message) {
        if (message != null) {
            //CNF-34: store m5d for message to compare duplicates
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                String noTimeStampMessage = message.replaceAll("timestamp=\".*?\"", "");
                md.update(noTimeStampMessage.getBytes());
                byte[] digest = md.digest();
                return DatatypeConverter.printHexBinary(digest).toUpperCase();
            } catch (NoSuchAlgorithmException e) {
                //should never get here
            }
        }
        return null;
    }

    public Long getId() {
        return id;
    }

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

    public String getReference() {
        return reference;
    }

    public void setReference(String reference) {
        this.reference = reference;
    }

    public Date getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(final Date timeStamp) {
        this.timeStamp = timeStamp;
    }

    public SnapshotType getSnapshotType() {
        return snapshotType;
    }

    public void setSnapshotType(final SnapshotType snapshotMsgType) {
        this.snapshotType = snapshotMsgType;
    }

    public String getConsumerTag() {
        return consumerTag;
    }

    public void setConsumerTag(String consumerTag) {
        this.consumerTag = consumerTag;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getShipmentNumber() {
        return shipmentNumber;
    }

    public void setShipmentNumber(String shipmentNumber) {
        this.shipmentNumber = shipmentNumber;
    }

    @Override
    public final String toString() {
        return "Snapshot [id=" + id + ", reference=" + reference + ", timeStamp=" + timeStamp + ", snapshotType=" + snapshotType + ", consumerTag="
                + consumerTag + ", message=" + message + "]";
    }

    @Override
    public final boolean equals(final Object other) {
        if (!(other instanceof Snapshot)) {
            return false;
        }
        Snapshot castOther = (Snapshot) other;
        return new EqualsBuilder().append(reference, castOther.reference).append(snapshotType, castOther.snapshotType)
                .append(eventId, ((Snapshot) other).eventId)
                .append(timeStamp, castOther.timeStamp).append(consumerTag, castOther.consumerTag)
                .append(message, castOther.message).isEquals();
    }

    @Override
    public final int hashCode() {
        return new HashCodeBuilder().append(reference).append(snapshotType).append(timeStamp).append(consumerTag)
                .append(message).append(eventId).toHashCode();
    }

    public Long getAcknowledgeEventId() {
        return acknowledgeEventId;
    }

    public void setAcknowledgeEventId(Long acknowledgeEventId) {
        this.acknowledgeEventId = acknowledgeEventId;
    }

    public Long getEventId() {
        return eventId;
    }

    public void setEventId(Long eventId) {
        this.eventId = eventId;
    }

    public static enum SnapshotType {
        CLC_ALC, DIRECT_INVOICE, DIRECT_CREDIT_NOTE, INDIRECT_INVOICE, INDIRECT_CREDIT_NOTE,
        ORDER_PAYMENT, SPI_PAYMENT, CI_PAYMENT, ALC_PER_SERVICE_PROVIDER, SPLIT_INDIRECT_INVOICE,
        PAYMENT_TO_INVOICE_ALLOCATION, BONDED_INVOICE
    }

    public String getMd5Sum() {
        return md5Sum;
    }

    public void setMd5Sum(String md5Sum) {
        //not changeable
    }
}