package geniusweb.protocol.partyconnection; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; import geniusweb.actions.PartyId; import geniusweb.inform.Inform; /** * Contains all parties with their connections. immutable */ public class ProtocolToPartyConnections implements Iterable { private List connections; public ProtocolToPartyConnections(List connections) { this.connections = connections; } /** * @param id the {@link PartyId} needed * @return a connection with that party, or null if no such connection. */ public ProtocolToPartyConn get(PartyId id) { return connections.stream().filter(conn -> id.equals(conn.getParty())) .findAny().orElse(null); } /** * * @return true iff all parties have one connection only */ public boolean allunique() { return getParties().size() == connections.size(); } /** * * @return list of parties currently in the connections. */ private List getParties() { return connections.stream().map(conn -> conn.getParty()).distinct() .collect(Collectors.toList()); } /** * Broadcast info to all parties. Notice that the broadcast immediately * aborts if an error occurs and remaining parties will not receive the * event. Therefore it is recommended to instead send to all parties * individually to ensure all parties are handled individually. * * @param info the {@link Inform} to broadcast * @return a Map<PartyId, IOException> where possible exceptions for * each party are stored. Normally a protocol would kick these * parties. */ public Map broadcast(Inform info) { Map exceptions = new HashMap<>(); for (ProtocolToPartyConn conn : connections) { try { conn.send(info); } catch (IOException e) { exceptions.put(conn.getParty(), e); } } return exceptions; } /** * * @return number of connections available */ public int size() { return connections.size(); } /** * @param i the connection number * @return the ith connection */ public ProtocolToPartyConn get(int i) { return connections.get(i); } public Stream stream() { return connections.stream(); } @Override public Iterator iterator() { return connections.iterator(); } public ProtocolToPartyConnections with(ProtocolToPartyConn conn) { List newconnections = new LinkedList<>( connections); newconnections.add(conn); return new ProtocolToPartyConnections(newconnections); } @Override public String toString() { return "ConnectionWithParties" + connections; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((connections == null) ? 0 : connections.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; ProtocolToPartyConnections other = (ProtocolToPartyConnections) obj; if (connections == null) { if (other.connections != null) return false; } else if (!connections.equals(other.connections)) return false; return true; } }