package geniusweb.issuevalue; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.jdt.annotation.NonNull; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; /** * Contains a (possibly partial) bid. Basically a map. immutable, thread safe. */ @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE) public class Bid { // not immutable and explicit HashMap for better serializability, must be // kept immutable.. private final @NonNull Map<@NonNull String, @NonNull Value> issuevalues; /** * * @param issuevalues a map of issue, Value pairs. The String is the issue * name. A partial bid may not have values for all * issues. */ @JsonCreator public Bid( @JsonProperty("issuevalues") @NonNull Map<@NonNull String, @NonNull Value> issuevalues) { if (issuevalues == null) { throw new NullPointerException("issuevalues=null"); } for (final @NonNull String issue : issuevalues.keySet()) { if (issuevalues.get(issue) == null) { throw new IllegalArgumentException( "value of issue " + issue + " can not be null"); } } this.issuevalues = new HashMap(issuevalues); } /** * Makes partial bid with just 1 issue and value. * * @param issue the issue name * @param value the {@link Value} */ public Bid(@NonNull String issue, @NonNull Value value) { if (issue == null || value == null) { throw new NullPointerException("issue and value must be not =null"); } issuevalues = new HashMap<>(); issuevalues.put(issue, value); } /** * @param issue name of the issue * @return the value for the given issue, or null if there is no value for * the given issue. */ public @NonNull Value getValue(@NonNull String issue) { return issuevalues.get(issue); } /** * @param issue name of the issue (not null) * @return true iff the bid contains a value for the given issue. */ public boolean containsIssue(@NonNull String issue) { return issuevalues.containsKey(issue); } public @NonNull Set<@NonNull String> getIssues() { return Collections.unmodifiableSet(issuevalues.keySet()); } /** * Merges this partial bid with another partial bid. * * @param otherbid another partial bid (not null). * @return a bid with the combined values of both partial bids. * @throws IllegalArgumentException if issues overlap. */ public @NonNull Bid merge(final @NonNull Bid otherbid) { @NonNull Set<@NonNull String> ourissues = new HashSet<>(issuevalues.keySet()); ourissues.retainAll(otherbid.getIssues()); if (!ourissues.isEmpty()) { throw new IllegalArgumentException( "Otherbid contains issues that are already set:" + ourissues); } @NonNull HashMap<@NonNull String, @NonNull Value> newvalues = new HashMap<>( issuevalues); newvalues.putAll(otherbid.issuevalues); return new Bid(newvalues); } /** * * @return (unmodifyable) map with all issues and values in the bid. */ public @NonNull Map<@NonNull String, @NonNull Value> getIssueValues() { return Collections.unmodifiableMap(issuevalues); } @Override public @NonNull String toString() { return "Bid" + issuevalues.toString(); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((issuevalues == null) ? 0 : issuevalues.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Bid other = (Bid) obj; if (issuevalues == null) { if (other.issuevalues != null) return false; } else if (!issuevalues.equals(other.issuevalues)) return false; return true; } }