package gov.nysenate.openleg.model.bill;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.SetMultimap;
import gov.nysenate.openleg.model.base.BaseLegislativeContent;
import gov.nysenate.openleg.model.base.SessionYear;
import gov.nysenate.openleg.model.entity.CommitteeId;
import gov.nysenate.openleg.model.entity.SessionMember;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Objects;
import java.util.Set;
/**
* The BillVote class is used to store vote information pertaining to a specific bill.
* This model can be used for representing both floor and committee votes although
* committee votes will have some extra metadata that should be tracked elsewhere.
*/
public class BillVote extends BaseLegislativeContent implements Serializable, Comparable<BillVote>
{
private static final long serialVersionUID = -5265803060674818213L;
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
/** Reference to the specific bill this vote was taken on. */
private BillId billId;
/** The type of bill vote (floor/committee) */
private BillVoteType voteType;
/** Date the vote was taken on. */
private LocalDate voteDate;
private CommitteeId committeeId;
/** Sets of members grouped based upon how they voted. */
@SuppressWarnings("serial")
private SetMultimap<BillVoteCode, SessionMember> memberVotes = HashMultimap.create();
/** An identifier to uniquely identify votes that came in on the same day.
* Currently not implemented as the source data does not contain this value. */
private int sequenceNo;
/** --- Constructors --- */
public BillVote() {
super();
}
public BillVote(BillVoteId billVoteId) {
this(billVoteId.getBillId(), billVoteId.getVoteDate(), billVoteId.getVoteType(), billVoteId.getSequenceNo());
this.committeeId = billVoteId.getCommitteeId();
}
public BillVote(BillId billId, LocalDate voteDate, BillVoteType type) {
this(billId, voteDate, type, 1);
}
public BillVote(BillId billId, LocalDate voteDate, BillVoteType type, int sequenceNo) {
this();
this.billId = billId;
this.voteDate = voteDate;
this.setYear(voteDate.getYear());
this.setSession(new SessionYear(this.getYear()));
this.voteType = type;
this.sequenceNo = sequenceNo;
}
public BillVote(BillId billId, LocalDate voteDate, BillVoteType type, int sequenceNo, CommitteeId committeeId) {
this(billId, voteDate, type, sequenceNo);
this.committeeId = committeeId;
}
/** --- Functional Getters/Setters --- */
/**
* Creates and returns a unique id for the BillVote.
*/
public BillVoteId getVoteId() {
return new BillVoteId(this.billId, this.voteDate, this.voteType, this.sequenceNo, this.committeeId);
}
/**
* Retrieve a set of members that voted as 'voteCode'.
* @param voteCode BillVoteCode
* @return Set<Member>
*/
public Set<SessionMember> getMembersByVote(BillVoteCode voteCode) {
return memberVotes.get(voteCode);
}
/**
* Add a member to the map based on how they voted.
* @param voteCode BillVoteCode
* @param member Member
*/
public void addMemberVote(BillVoteCode voteCode, SessionMember member) {
memberVotes.put(voteCode, member);
}
/**
* Returns a count of all the members that have been added to the voting roll.
*/
public int count() {
return memberVotes.size();
}
/** --- Overrides --- */
/**
* Ignore the parent class (session/modified/published date) during equality checking.
* The vote date and type should suffice in uniquely identifying the vote for a certain billId.
*/
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
final BillVote other = (BillVote) obj;
return Objects.equals(this.billId, other.billId) &&
Objects.equals(this.voteType, other.voteType) &&
Objects.equals(this.voteDate, other.voteDate) &&
Objects.equals(this.memberVotes, other.memberVotes) &&
Objects.equals(this.sequenceNo, other.sequenceNo) &&
Objects.equals(this.committeeId, other.committeeId);
}
@Override
public int compareTo(BillVote o) {
return ComparisonChain.start()
.compare(this.getVoteDate(), o.getVoteDate())
.compare(this.getVoteType().code, o.getVoteType().code)
.result();
}
@Override
public int hashCode() {
return Objects.hash(billId, voteType, voteDate, memberVotes, sequenceNo);
}
@Override
public String toString() {
return "BillVote{" +
"sequenceNo=" + sequenceNo +
", billId=" + billId +
", voteType=" + voteType +
", voteDate=" + voteDate +
", committeeId=" + committeeId +
'}';
}
/** --- Basic Getters/Setters --- */
public static long getSerialVersionUID() {
return serialVersionUID;
}
public static SimpleDateFormat getDateFormat() {
return dateFormat;
}
public static void setDateFormat(SimpleDateFormat dateFormat) {
BillVote.dateFormat = dateFormat;
}
public BillVoteType getVoteType() {
return voteType;
}
public void setVoteType(BillVoteType voteType) {
this.voteType = voteType;
}
public LocalDate getVoteDate() {
return voteDate;
}
public void setVoteDate(LocalDate voteDate) {
this.voteDate = voteDate;
}
public BillId getBillId() {
return billId;
}
public void setBillId(BillId billId) {
this.billId = billId;
}
public SetMultimap<BillVoteCode, SessionMember> getMemberVotes() {
return memberVotes;
}
public int getSequenceNo() {
return sequenceNo;
}
public void setSequenceNo(int sequenceNo) {
this.sequenceNo = sequenceNo;
}
public CommitteeId getCommitteeId() {
return committeeId;
}
public void setCommitteeId(CommitteeId committeeId) {
this.committeeId = committeeId;
}
}