Changeset 24 for protocol/src


Ignore:
Timestamp:
10/06/20 13:12:20 (4 years ago)
Author:
bart
Message:

Fixes an issue with processing maxPower of a vote. Javadoc maven plugin now uses latest version.

Location:
protocol/src
Files:
5 added
30 edited

Legend:

Unmodified
Added
Removed
  • protocol/src/main/java/geniusweb/protocol/NegoProtocol.java

    r21 r24  
    1313import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
    1414import geniusweb.protocol.session.SessionProtocol;
    15 import geniusweb.protocol.session.SessionSettings;
    1615import geniusweb.protocol.session.SessionState;
    1716import geniusweb.protocol.tournament.TournamentProtocol;
     
    3029 *
    3130 * A protocol is mutable because the incoming connections cause state changes.
    32  * But it is recommended to push all changing properties into the state.
     31 * But it is recommended to push changing properties into the state so that the
     32 * complete state can be recovered and analysed.
    3333 * <p>
    3434 * Because a protocol contains an internal state, it can be used only once.
    35  * <p>
    3635 * <p>
    3736 * The protocol can emit a {@link CurrentState} event at any time. It should do
     
    4241 * which it can resolve received {@link Reference}s. <br>
    4342 * First call to instances <b>must be</b>
    44  * {@link #start(SessionSettings, ConnectionFactory)}.
     43 * {@link #start(ProtocolToPartyConnFactory)}.
    4544 *
    4645 * <h2>Ensure time deadline</h2>
     
    4847 * The protocol also needs to keep an eye on the deadline and take appropriate
    4948 * actions when the deadline is reached. <br>
    50  * A protocol should emit a {@link SessionEnded} or {@link TournamentEnded}
    51  * event when it is finished.
    5249 * <p>
    5350 * All protocol implementations must ensure that the deadline is kept and that
     
    7370         * <p>
    7471         *
    75          * All errors are to be handled through {@link SessionState#getError()}
    76          * except for plain {@link IllegalArgumentException}s. <br>
     72         * All errors are to be handled through {@link SessionState#getResult()}
     73         * except for bugs that use {@link RuntimeException} like
     74         * {@link IllegalArgumentException}s. <br>
    7775         * The protocol usually uses the incoming connections to keep running. It
    7876         * does not need to run in a separate thread or so.
  • protocol/src/main/java/geniusweb/protocol/NegoState.java

    r21 r24  
    1111
    1212/**
    13  * The current state of the session/tournament. Must be serializabl;e so that it
    14  * can be restarted if a crash occurs.
     13 * The current state of the session/tournament. Must be (de)serializabl;e so
     14 * that it can be restarted if a crash occurs. Notice that this restart
     15 * functionality is not yet available.
     16 * <p>
     17 * In general the state contains all the information to control the flow of the
     18 * negotiation: who did what, are we finished, etc. This object may be stored to
     19 * record the final result as well
    1520 */
    1621@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
  • protocol/src/main/java/geniusweb/protocol/ProtocolException.java

    r21 r24  
    55
    66/**
    7  * thrown if a {@link Party} violates the protocols (that includes
    8  * disconnecting).
     7 * thrown if a Party violates the protocols (that includes disconnecting).
    98 */
    109public class ProtocolException extends Exception {
  • protocol/src/main/java/geniusweb/protocol/partyconnection/ProtocolToPartyConnections.java

    r21 r24  
    4949
    5050        /**
    51          * Broadcast info to all parties
     51         * Broadcast info to all parties. Notice that the broadcast immediately
     52         * aborts if an error occurs and remaining parties will not receive the
     53         * event. Therefore it is recommended to instead send to all parties
     54         * individually to ensure all parties are handled individually.
    5255         *
    5356         * @param info the {@link Inform} to broadcast
     57         * @throws IOException if the send fails.
    5458         */
    5559        public void broadcast(Inform info) throws IOException {
     
    6872
    6973        /**
    70          * @param i
     74         * @param i the connection number
    7175         * @return the ith connection
    7276         */
  • protocol/src/main/java/geniusweb/protocol/session/SessionResult.java

    r23 r24  
    6767
    6868        /**
    69          * 8return the final {@link Agreements} of the session. May be empty, not
    70          * null
     69         * @return the final {@link Agreements} of the session. May be empty, not
     70         *         null
    7171         */
    7272        public Agreements getAgreements() {
  • protocol/src/main/java/geniusweb/protocol/session/SessionState.java

    r21 r24  
    1818 * and the parties currently connected. <br>
    1919 * The state checks if transitions (Actions from the party) are following the
    20  * protocol, and thus implement most of the protocol . See
    21  * {@link #with(geniusweb.actions.PartyId, Action)}. <br>
    22  *
    23  * Use {@link #with(geniusweb.actions.PartyId, Action)} and
    24  * {@link #with(geniusweb.actions.PartyId, tudelft.utilities.connection.Connection)}
    25  * to create a new state <br>
    26  *
     20 * protocol, and thus implement most of the protocol . <br>
    2721 *
    2822 * If protocol errors occur, these should be stored in the state and the state
    29  * should become {@link #isFinal()}. Throwing should happen only in case of a
    30  * bug.<br>
     23 * should become {@link #isFinal(long)}. Throwing should happen only in case of
     24 * a bug.<br>
    3125 *
    3226 * Implementations should be immutable (to ensure thread safety, testability
     
    6660         * @return the current standing agreement, or null if there is no agreement
    6761         *         at this point. An agreement does not necessarily mean
    68          *         {@link #isFinal()}.
     62         *         {@link #isFinal(long)}.
    6963         */
    7064        Agreements getAgreements();
     
    7266        /**
    7367         *
    74          * @return the {@link SessionResult}. Assumes {@link #isFinal(long)}. result
    75          *         may be undefined if not.
     68         * @return the {@link SessionResult} which is a short report of the final
     69         *         outcome. Assumes {@link #isFinal(long)}. result may be undefined
     70         *         if not.
    7671         */
    7772        SessionResult getResult();
  • protocol/src/main/java/geniusweb/protocol/session/amop/AMOP.java

    r21 r24  
    2828import geniusweb.protocol.CurrentNegoState;
    2929import geniusweb.protocol.ProtocolException;
    30 import geniusweb.protocol.WillBeCalled;
    3130import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
    3231import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
     
    5150 * <h1>parameter</h1> AMOP parties can receive a parameter: minVotes containing
    5251 * a Double. If set, the AMOP protocol checks that all {@link Votes} from that
    53  * party have {@link Vote#getMinPower()} > minVotes.
    54  * <h1>Protocol steps</h1> The protocol tries to start all parties. If not all
    55  * parties start, the parties are freed up and another attempt is done to start
    56  * all parties some time later.
     52 * party have {@link Vote#getMinPower()} &gt; minVotes.
     53 * <h1>Protocol steps</h1>
     54 * <ol>
     55 * <li>The protocol tries to start all parties. If not all parties start, the
     56 * parties are freed up and another attempt is done to start all parties some
     57 * time later.
    5758 * <li>the variable remainingparties = {all parties}
    5859 * <li>The session deadline clock now starts ticking.
    5960 * <li>All parties are sent their settings.
    60  * <li>Loop until {@link Deadline} is reached or |remainingparties|<2:
     61 * <li>Loop until {@link Deadline} is reached or |remainingparties|&lt;2:
    6162 * <ol>
    6263 * <li>protocol sends {@link YourTurn} to all remainingparties. Each party now
    6364 * must submit an {@link Offer} within {@link #PHASE_TIME} seconds. If a party
    6465 * fails to submit it is send Finished and removed from from remainingparties.
    65  * <li>protocol sends a {@link Voting} containing a List<Bid> containing all
    66  * received {@link Bid}s. Each party must place his {@link Votes} within
    67  * {@link #PHASE_TIME} seconds. If a party does not submit, it is send a
     66 * <li>protocol sends a {@link Voting} containing a List of {@link Bid}
     67 * containing all received {@link Bid}s. Each party must place his {@link Votes}
     68 * within {@link #PHASE_TIME} seconds. If a party does not submit, it is send a
    6869 * {@link Finished} and removed from remainingparties. Previous votes for the
    6970 * same bid do not count. But see {@link Agreements}.
    70  * <li>The protocol determines a maximum sized subset of size N>=2 of the votes
    71  * for bid B for which the vote conditions hold. If there is such a subset, the
    72  * parties that placed these votes reached an agreement. They are added to the
    73  * agreement set, sent the {@link Finished} info and terminated. They are
    74  * removed from the remainingparties.
     71 * <li>The protocol determines a maximum sized subset of size N&ge;2 of the
     72 * votes for bid B for which the vote conditions hold. If there is such a
     73 * subset, the parties that placed these votes reached an agreement. They are
     74 * added to the agreement set, sent the {@link Finished} info and terminated.
     75 * They are removed from the remainingparties.
    7576 * </ol>
    7677 * <li>Any remaining parties are sent a {@link Finished} object without
     
    109110        /**
    110111         *
    111          * @param state normally the initial state coming from SAOPSettings
     112         * @param state  normally the initial state coming from SAOPSettings
     113         * @param logger the {@link Reporter} to use
    112114         */
    113115        public AMOP(AMOPState state, Reporter logger) {
     
    218220         * overridable factory method, used for testing.
    219221         *
    220          * @param r
    221          * @param delayMs
     222         * @param r       the {@link Runnable} that will be called
     223         * @param delayMs the time after which r will be called
    222224         * @return new WillBeCalled(r,delayms)
    223225         */
  • protocol/src/main/java/geniusweb/protocol/session/amop/AMOPSettings.java

    r21 r24  
    3030         *                     protocol. But SAOP can be initialized with less, for
    3131         *                     use in TournamentSettings.
    32          * @param deadline
    33          * @param minimumVotes the minimum number of votes allowed for a bid.
     32         * @param deadline     the {@link Deadline} of the negotiation
    3433         */
    3534        @JsonCreator
  • protocol/src/main/java/geniusweb/protocol/session/amop/AMOPState.java

    r23 r24  
    197197
    198198        /**
    199          * @param actor         the actor that did this action. Can be used to check
    200          *                      if action is valid. NOTICE caller has to make sure
    201          *                      the current state is not final. MUST NOT be null.
    202          * @param action        the action that was proposed by actor. MUST NOT be
    203          *                      null.
    204          * @param currentTimeMs the current time in ms since 1970, see
    205          *                      {@link System#currentTimeMillis()}
     199         * @param actor  the actor that did this action. Can be used to check if
     200         *               action is valid. NOTICE caller has to make sure the current
     201         *               state is not final. MUST NOT be null.
     202         * @param action the action that was proposed by actor. MUST NOT be null.
    206203         * @return new SessionState with the action added as last action.
    207204         * @throws ProtocolException if actor is violating the protocol
  • protocol/src/main/java/geniusweb/protocol/session/mopac/MOPAC.java

    r23 r24  
    22
    33import java.io.IOException;
     4import java.util.Collections;
    45import java.util.List;
    56import java.util.Timer;
     
    5556 * parties are freed up and another attempt is done to start all parties some
    5657 * time later.
    57  * <li>the variable remainingparties = {all parties}
    5858 * <li>The session deadline clock now starts ticking.
    5959 * <li>remainingparties are sent their settings.
    60  * <li>Loop until {@link Deadline} is reached or |remainingparties|<2:
     60 * <li>Loop until {@link Deadline} is reached or |remainingparties| &le; 2:
    6161 * <ol>
    6262 * <li>protocol sends {@link YourTurn} to all remainingparties. Each party now
    6363 * must submit an {@link Offer} within {@link Phase#PHASE_MAXTIME} seconds. If a
    6464 * party fails to submit it is removed from from remainingparties.
    65  * <li>protocol sends a {@link Voting} containing a List<Bid> containing all
    66  * received {@link Bid}s. Each party must place his {@link Votes} within
    67  * {@link #PHASE_TIME} seconds. If a party does not submit, it is terminated and
    68  * removed from remainingparties. Previous votes for the same bid do not count.
    69  * But see {@link Agreements}. A party that misbehaves after submitting its vote
    70  * is removed but it Votes remain standing.
     65 * <li>protocol sends a {@link Voting} containing a List of Bid containing all
     66 * received {@link Bid}s. Each party must place his {@link Votes} within the
     67 * provided deadline. If a party does not submit, it is terminated and removed
     68 * from remainingparties. Previous votes for the same bid do not count. But see
     69 * {@link Agreements}. A party that misbehaves after submitting its vote is
     70 * removed but it Votes remain standing.
    7171 * <li>protocol sends to all remainingparties a OptIn containing all received
    72  * votes. Each party now must submit again a {@link Votes} object within
    73  * {@link #PHASE_TIME} seconds. This new Votes must equal or extend the previous
    74  * Votes of the party.
    75  * <li>The protocol use the {@link MOPACState#getEvaluator()} to determine the
    76  * ... . If there is such a subset, the parties that placed these votes reached
    77  * an agreement. They are added to the agreement set, sent the {@link Finished}
    78  * info and terminated. They are removed from the remainingparties.
     72 * votes. Each party now must submit again a {@link Votes} object within the
     73 * deadline. This new Votes must equal or extend the previous Votes of the
     74 * party.
     75 * <li>The protocol uses the {@link Phase#getEvaluator()} to determine the
     76 * agreements from the votes. If there are agreements, the parties that placed
     77 * these votes reached an agreement. They are moved to the agreement set and
     78 * removed from the remainingparties.
    7979 * </ol>
    8080 * <li>Any remaining parties are sent a {@link Finished} object without
     
    114114        private final Reporter log;
    115115        private MOPACState state = null; // mutable!
     116        /**
     117         * the existing party connections. we assume ownership of this so it should
     118         * not be modified although connections may of course break. mutable!
     119         */
     120        private ProtocolToPartyConnections connections = new ProtocolToPartyConnections(
     121                        Collections.emptyList());
    116122
    117123        /**
     
    124130        /**
    125131         *
    126          * @param state normally the initial state coming from SAOPSettings
     132         * @param state  normally the initial state coming from SAOPSettings
     133         * @param logger the {@link Reporter} to use
    127134         */
    128135        public MOPAC(MOPACState state, Reporter logger) {
     
    145152                        ProtocolToPartyConnFactory connectionfactory) {
    146153                try {
    147                         // System.out.println("starting MOPAC");
    148                         // we're in Phase.INIT still
    149154                        connect(connectionfactory);
    150                         setupParties();
    151                         long now = System.currentTimeMillis();
    152                         state = state.initPhase(now);
    153                         startPhase(now);
    154155                } catch (Throwable e) {
    155                         e.printStackTrace();
    156                         handleError("Failed to start MOPAC session", new PartyId("BUG"), e);
    157                 }
     156                        /** We can't {@link #handleError} yet. FIXME */
     157                        throw new RuntimeException("Failed to connect", e);
     158                }
     159                long now = System.currentTimeMillis();
     160                state = state.initPhase(
     161                                ProgressFactory.create(state.getSettings().getDeadline(), now),
     162                                now);
     163                setupParties(now);
     164                startPhase(now);
     165
    158166        }
    159167
     
    212220                                .map(parti -> (parti.getParty().getPartyRef()))
    213221                                .collect(Collectors.toList());
    214                 List<ProtocolToPartyConn> connections = null;
    215222                log.log(Level.INFO, "MOPAC connect " + parties);
    216                 while (connections == null) {
     223                List<ProtocolToPartyConn> newconnections = null;
     224                while (newconnections == null) {
    217225                        try {
    218                                 connections = connectionfactory.connect(parties);
     226                                newconnections = connectionfactory.connect(parties);
    219227                        } catch (NoResourcesNowException e) {
    220228                                long waitms = e.getLater().getTime()
     
    228236                }
    229237                for (int i = 0; i < participants.size(); i++) {
    230                         state = state.with(connections.get(i), participants.get(i));
     238                        ProtocolToPartyConn conn = newconnections.get(i);
     239                        connections = connections.with(conn);
     240                        state = state.with(conn.getParty(), participants.get(i));
    231241                }
    232242        }
     
    239249         * part of the interface.
    240250         *
    241          * @throws ProtocolException if a party does not follow the protocol
    242          */
    243         protected synchronized void setupParties() throws ProtocolException {
    244                 for (ProtocolToPartyConn conn : state.getConnections()) {
    245                         conn.addListener(action -> actionRequest(conn, action,
    246                                         System.currentTimeMillis()));
    247                 }
    248                 Long now = System.currentTimeMillis();
    249                 state = state.with(
    250                                 ProgressFactory.create(state.getSettings().getDeadline(), now));
    251                 for (ProtocolToPartyConn connection : state.getConnections()) {
     251         * @param now the current time.
     252         */
     253        protected synchronized void setupParties(long now) {
     254                for (ProtocolToPartyConn conn : connections) {
     255                        conn.addListener(action -> actionRequest(conn, action, now));
     256                }
     257                for (ProtocolToPartyConn connection : connections) {
    252258                        try {
    253259                                sendSettings(connection);
     
    257263                        }
    258264                }
    259 
    260265        }
    261266
     
    357362                                .getNegotiatingParties()) {
    358363                        try {
    359                                 state.getConnections().get(party).send(info);
     364                                connections.get(party).send(info);
    360365                        } catch (IOException e) {
    361                                 handleError("Party seems to have disconnected", party, e);
    362                         }
    363                 }
    364         }
    365 
    366         /**
    367          * Update state to include the given error and closes the party.
    368          *
    369          * @param message The message to attach to the error
    370          * @param party   the party where the error occured
    371          * @param e       the exception that occured.
    372          */
    373         private void handleError(final String message, final PartyId partyid,
    374                         final Throwable e) {
    375                 if (e instanceof ProtocolException) {
    376                         state = state.with((ProtocolException) e);
    377                 } else {
    378                         state = state.with(new ProtocolException(message, partyid, e));
    379                 }
    380                 log.log(Level.WARNING,
    381                                 "MOPAC intercepted error from party " + partyid + ":" + message,
    382                                 e);
    383         }
    384 
    385 //      /**
    386 //       * Sets the new state. If the new state is final, the finish-up procedure is
    387 //       * executed. All state changes go through here to ensure we check isFinal
    388 //       * before any state change.
    389 //       *
    390 //       * @param newstate the new state.
    391 //       */
    392 //      private synchronized void setState(MOPACState newstate) {
    393 //              long now = System.currentTimeMillis();
    394 //              if (state.isFinal(now)) {
    395 //                      endNegotiation();
    396 //                      return;
    397 //              }
    398 //
    399 //              this.state = newstate;
    400 //              if (newstate.isFinal(now)) {
    401 //                      endNegotiation();
    402 //              }
    403 //      }
     366                                state = state.with(new ProtocolException(
     367                                                "Party seems to have disconnected", party, e));
     368                        }
     369                }
     370        }
    404371
    405372        /**
     
    413380                finished = true;
    414381                Finished info = new Finished(state.getAgreements());
    415                 for (ProtocolToPartyConn conn : state.getConnections()) {
     382                for (ProtocolToPartyConn conn : connections) {
    416383                        try {
    417384                                conn.send(info);
  • protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACSettings.java

    r21 r24  
    1919/**
    2020 * Settings for MOPAC negotiation. in MOPAC, each party may get a "power"
    21  * parameter containing an natural number >=1.
     21 * parameter containing an natural number &le;1.
    2222 */
    2323public class MOPACSettings implements SessionSettings {
     
    3030         * @param participants the list of {@link PartyWithProfile} in clockwise
    3131         *                     order. There must be at least 2 to run the MOPAC
    32          *                     protocol. But SAOP can be initialized with less, for
    33          *                     use in TournamentSettings.
    34          *
    35          *                     All provided participants must
    36          *
    37          * @param deadline
    38          * @param minimumVotes the minimum number of votes allowed for a bid.
     32         *                     protocol. This is not tested in the constructor
     33         *                     because this can be initialized with less, for use in
     34         *                     TournamentSettings.
     35         * @param deadline     the {@link Deadline} for the negotiation
     36         * @param votingeval   the {@link VotingEvaluator} to use.
    3937         */
    4038        @JsonCreator
     
    9088
    9189        @Override
    92         public SessionSettings with(TeamOfPartiesAndProfiles party) {
     90        public MOPACSettings with(TeamOfPartiesAndProfiles party) {
    9391                if (!(party instanceof OnePartyTeam))
    9492                        throw new IllegalArgumentException(
  • protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACState.java

    r23 r24  
    1717import geniusweb.progress.Progress;
    1818import geniusweb.progress.ProgressRounds;
     19import geniusweb.protocol.NegoProtocol;
    1920import geniusweb.protocol.ProtocolException;
    20 import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
    21 import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;
    2221import geniusweb.protocol.session.SessionResult;
    2322import geniusweb.protocol.session.SessionState;
     
    2726import geniusweb.protocol.session.saop.SAOPSettings;
    2827import geniusweb.references.PartyWithProfile;
    29 import geniusweb.voting.VotingEvaluator;
    30 
     28
     29/**
     30 * Keeps track of the current {@link Phase}. Adds initializing stuff and
     31 * time/deadline checking. This state does not contain connections, this assumes
     32 * that someone else handles (i.e. {@link NegoProtocol} that and the connections
     33 * with the parties and that negotiation events are just pumped in from there.
     34 * <p>
     35 * This object is a bit tricky. It has two states
     36 * <ol>
     37 * <li>The initial state, where phase=null and connections are being made to all
     38 * parties. At this point, problems can not be handled nicely yet because there
     39 * are no PartyId's for problematic parties
     40 * <li>The working state, where all parties are connected and all problems can
     41 * be connected to an offending party.
     42 * </ol>
     43 */
    3144public class MOPACState implements SessionState {
    3245
    33         private final Phase phase;
     46        private final Phase phase; // maybe null while initializing
    3447        private final MOPACSettings settings;
    3548        private final Map<PartyId, PartyWithProfile> partyprofiles;
    36         private final ProtocolToPartyConnections connections;
    3749        private final List<Action> actions;
    3850        private final Progress progress;
     
    4456         */
    4557        public MOPACState(MOPACSettings settings) {
    46                 this(null, Arrays.asList(),
    47                                 new ProtocolToPartyConnections(Collections.emptyList()), null,
    48                                 settings, Collections.emptyMap());
     58                this(null, Arrays.asList(), null, settings, Collections.emptyMap());
    4959
    5060        }
     
    5464         *                      set something only after we have connections.
    5565         * @param actions       the legal actions that have been done in the
    56          *                      negotiation. A new-sub-list is added for each phase
    57          *                      change. It is assumed that the last element of the
    58          *                      list is the list with actions taken in the current
    59          *                      phase. first action in first list is the oldest.
    60          *                      This MUST NOT contain illegal actions. Parties doing
    61          *                      illegal actions are killed and the offending action
    62          *                      ends up in the stacktrace. Previous actions of
    63          *                      crashed parties remain standing and valid.
    64          * @param conns         the existing party connections. we assume ownership
    65          *                      of this so it should not be modified although
    66          *                      connections may of course break.
     66         *                      negotiation. {@link PartyStates#getActions()} is
     67         *                      called to collect the actions after the phase is
     68         *                      finished.first action in list is the oldest. This
     69         *                      will not contain actions that immediately led to an
     70         *                      agreement, because {@link PartyStates} removes the
     71         *                      actions that led to an agreement. This MUST NOT
     72         *                      contain illegal actions. Parties doing illegal
     73         *                      actions are killed and the offending action ends up
     74         *                      in the stacktrace. Previous actions of crashed
     75         *                      parties remain standing and valid.
    6776         * @param progress      the {@link Progress} line. can be null if not yet
    68          *                      known. This happens because during setup we first
    69          *                      add all connections, and only when we have that we
    70          *                      set the correct deadline.
     77         *                      known. null happens because during initialization
     78         *                      phase the protocol first add all connections. During
     79         *                      this time, parties may already enter the
     80         *                      failed/exception state.
    7181         * @param settings      the {@link SAOPSettings}
    7282         * @param partyprofiles map with the {@link PartyWithProfile} for connected
    7383         *                      parties. null is equivalent to an empty map.
    74          * @param evaluator     the {@link VotingEvaluator}
    7584         */
    7685        @JsonCreator
    7786        protected MOPACState(@JsonProperty("phase") Phase phase,
    7887                        @JsonProperty("actions") List<Action> actions,
    79                         @JsonProperty("connections") ProtocolToPartyConnections conns,
    8088                        @JsonProperty("progress") Progress progress,
    8189                        @JsonProperty("settings") MOPACSettings settings,
     
    8391                this.phase = phase;
    8492                this.actions = actions;
    85                 this.connections = conns;
    8693                this.progress = progress;
    8794                this.settings = settings;
     
    9097
    9198        /**
    92          * Can be called after all connections are initialized.
    93          *
    94          * @param now current time ms since 1970
    95          *
    96          * @return state with the initial partystates set.
    97          */
    98         public MOPACState initPhase(long now) {
    99                 PartyStates partyStates = new PartyStates(getPowers());
    100                 Phase firstPhase = new OfferPhase(null, partyStates,
    101                                 now + getAvailablePhaseTime(now),
    102                                 settings.getVotingEvaluation());
    103                 return new MOPACState(firstPhase, actions, connections, progress,
    104                                 settings, partyprofiles);
    105         }
    106 
    107         @Override
    108         public List<Action> getActions() {
    109                 return Collections.unmodifiableList(actions);
    110         }
    111 
    112         @Override
    113         public Progress getProgress() {
    114                 return progress;
    115         }
    116 
    117         public Map<PartyId, PartyWithProfile> getPartyProfiles() {
    118                 return Collections.unmodifiableMap(partyprofiles);
    119         }
    120 
    121         /**
    122          * @return all current/remaining active party connections. Finished/crashed
    123          *         parties should be removed immediately.
    124          */
    125         public ProtocolToPartyConnections getConnections() {
    126                 return connections;
    127         }
    128 
    129         /**
    130          * @param now current time ms since 1970
    131          * @return the max possible duration in ms of the NEXT phase. Maybe 0 or
    132          *         negative if past deadline.
    133          */
    134         private Long getAvailablePhaseTime(long now) {
    135                 // explicit check, to check also the round counts.
    136                 if (incrementProgress().isPastDeadline(now + Phase.PHASE_MINTIME))
    137                         return 0l;
    138                 return Math.min(progress.getTerminationTime().getTime() - now,
    139                                 Phase.PHASE_MAXTIME);
    140         }
    141 
    142         /**
    143          *
    144          * @param connection   the new {@link ProtocolToPartyConn}
    145          * @param partyprofile the {@link PartyWithProfile} that is associated with
    146          *                     this state
    147          * @return new {@link MOPACState} with the new connection added. This call
    148          *         ignores the progress (does not check isFinal) because we uses
    149          *         this during the setup where the deadline is not yet relevant.
    150          */
    151         protected MOPACState with(ProtocolToPartyConn connection,
    152                         PartyWithProfile partyprofile) {
    153                 if (phase != null)
    154                         throw new IllegalStateException(
    155                                         "Adding connections only allowed while initializing");
    156 
    157                 ProtocolToPartyConnections newconns = getConnections().with(connection);
    158                 Map<PartyId, PartyWithProfile> newprofiles = new HashMap<>(
    159                                 partyprofiles);
    160                 newprofiles.put(connection.getParty(), partyprofile);
    161                 return new MOPACState(null, actions, newconns, progress, settings,
    162                                 newprofiles);
    163         }
    164 
    165         /**
    166          * @param id the {@link PartyId} of the party that failed.
    167          * @param e  the {@link ProtocolException} that occurred in the party
    168          * @return a new state with the error set.
    169          */
    170         public MOPACState with(ProtocolException e) {
    171                 return new MOPACState(phase.with(e), actions, connections, progress,
    172                                 settings, partyprofiles);
    173         }
    174 
    175         /**
    176          * Sets the progress for this session. Can be set only if progress=null.
    177          * Should be set in INIT phase.
    178          *
    179          * @param newprogress the new progress
    180          * @return new {@link MOPACState} with the progress set
    181          */
    182         public MOPACState with(Progress newprogress) {
     99         * Sets the progress for this session and initial phase. Must be called
     100         * after all parties have been connected with
     101         * {@link #with(PartyId, PartyWithProfile)}.
     102         *
     103         * @param newprogress the initial {@link Progress} typically matching the
     104         *                    settings deadline object
     105         * @param now         current time ms since 1970
     106         *
     107         * @return state with the initial partystates , progress set.
     108         */
     109        public MOPACState initPhase(Progress newprogress, long now) {
    183110                if (progress != null || newprogress == null || phase != null) {
    184111                        throw new IllegalArgumentException(
    185112                                        "progress must be null, newprogress must be not null and phase must be INIT");
    186113                }
    187                 return new MOPACState(phase, actions, connections, newprogress,
    188                                 getSettings(), partyprofiles);
     114
     115                PartyStates partyStates = new PartyStates(getPowers());
     116                Phase firstPhase = new OfferPhase(partyStates,
     117                                now + getAvailablePhaseTime(newprogress, now),
     118                                settings.getVotingEvaluation());
     119                return new MOPACState(firstPhase, actions, newprogress, settings,
     120                                partyprofiles);
     121        }
     122
     123        @Override
     124        public List<Action> getActions() {
     125                return Collections.unmodifiableList(actions);
     126        }
     127
     128        @Override
     129        public Progress getProgress() {
     130                return progress;
     131        }
     132
     133        @Override
     134        public Agreements getAgreements() {
     135                return phase.getPartyStates().getAgreements();
     136        }
     137
     138        @Override
     139        public MOPACSettings getSettings() {
     140                return settings;
     141        }
     142
     143        public Map<PartyId, PartyWithProfile> getPartyProfiles() {
     144                return Collections.unmodifiableMap(partyprofiles);
     145        }
     146
     147        @Override
     148        public boolean isFinal(long now) {
     149                return phase != null && phase.isFinal(now) && !isNewPhasePossible(now);
     150        }
     151
     152        @Override
     153        public SessionResult getResult() {
     154                return new SessionResult(partyprofiles, getAgreements(),
     155                                Collections.emptyMap(), null);
     156        }
     157
     158        /**
     159         * @param progress the Progress that needs to be checked
     160         * @param now      current time ms since 1970
     161         * @return the max possible duration in ms of a phase considering the
     162         *         progress.
     163         */
     164        private static Long getAvailablePhaseTime(Progress aprogress, long now) {
     165                return Math.min(aprogress.getTerminationTime().getTime() - now,
     166                                Phase.PHASE_MAXTIME);
     167        }
     168
     169        /**
     170         * @param id           the new {@link PartyId}
     171         * @param partyprofile the {@link PartyWithProfile} that is associated with
     172         *                     this state
     173         * @return new {@link MOPACState} with the new party added. This call
     174         *         ignores the progress (does not check isFinal) because we uses
     175         *         this during the setup where the deadline is not yet relevant.
     176         */
     177        protected MOPACState with(PartyId id, PartyWithProfile partyprofile) {
     178                if (phase != null)
     179                        throw new IllegalStateException(
     180                                        "Adding connections only allowed while initializing");
     181
     182                Map<PartyId, PartyWithProfile> newprofiles = new HashMap<>(
     183                                partyprofiles);
     184                newprofiles.put(id, partyprofile);
     185                return new MOPACState(null, actions, progress, settings, newprofiles);
     186        }
     187
     188        /**
     189         * @param e the {@link ProtocolException} that occured
     190         * @return a new state with the error set. You MUST have called
     191         *         {@link #initPhase(Progress, long)} before using this
     192         */
     193        public MOPACState with(ProtocolException e) {
     194                return new MOPACState(phase.with(e), actions, progress, settings,
     195                                partyprofiles);
    189196        }
    190197
     
    202209                                Math.min(remainingNegoTime, Phase.PHASE_MAXTIME));
    203210
    204                 return new MOPACState(newphase, actions, connections,
    205                                 incrementProgress(), getSettings(), partyprofiles);
    206         }
    207 
    208         /**
    209          *
    210          * @return the next progress. Progress round advances if phase is
    211          *         {@link OptIn}.
    212          */
    213         private Progress incrementProgress() {
    214                 if (progress instanceof ProgressRounds && phase instanceof OptInPhase)
    215                         return ((ProgressRounds) progress).advance();
    216                 return progress;
    217         }
    218 
    219         @Override
    220         public boolean isFinal(long now) {
    221                 return phase != null && phase.isFinal(now) && !isNewPhasePossible(now);
     211                return new MOPACState(newphase, actions, increment(progress, phase),
     212                                getSettings(), partyprofiles);
    222213        }
    223214
     
    225216         * When this is called, all parties should have acted.
    226217         *
    227          * @param now
    228          * @return
     218         * @param now current time
     219         * @return true if there are still &gt;2 parties active and we have enough
     220         *         time for a new phase.
    229221         */
    230222        public boolean isNewPhasePossible(long now) {
    231223                // System.out.println("phase=" + phase);
    232                 boolean a = phase.getPartyStates().getNegotiatingParties().size() >= 2
    233                                 && getAvailablePhaseTime(now) > Phase.PHASE_MINTIME;
    234                 // System.out.println("newstate possible:" + a);
    235                 return a;
    236         }
    237 
    238         @Override
    239         public Agreements getAgreements() {
    240                 return phase.getPartyStates().getAgreements();
    241         }
    242 
    243         @Override
    244         public MOPACSettings getSettings() {
    245                 return settings;
     224                Progress newprogress = increment(progress, phase);
     225                if (newprogress.isPastDeadline(now + Phase.PHASE_MINTIME))
     226                        return false;
     227
     228                return phase.getPartyStates().getNegotiatingParties().size() >= 2
     229                                && getAvailablePhaseTime(newprogress,
     230                                                now) > Phase.PHASE_MINTIME;
    246231        }
    247232
     
    261246         * @param now    the current time in ms since 1970, see
    262247         *               {@link System#currentTimeMillis()}
     248         * @return new {@link MOPACState} with the action checked and registered. If
     249         *         the action is not allowed, the new state may be that the actor is
     250         *         in the exception list.
    263251         */
    264252
    265253        public MOPACState with(PartyId actor, Action action, long now) {
    266                 return new MOPACState(phase.with(actor, action, now), actions,
    267                                 connections, progress, settings, partyprofiles);
    268         }
    269 
    270         @Override
    271         public SessionResult getResult() {
    272                 return new SessionResult(partyprofiles, getAgreements(),
    273                                 Collections.emptyMap(), null);
     254                return new MOPACState(phase.with(actor, action, now), actions, progress,
     255                                settings, partyprofiles);
     256        }
     257
     258        /**
     259         * @param aprogress the progress that might need to be advanced
     260         * @param aphase    the phase
     261         * @return the next progress. Progress round advances if phase is
     262         *         {@link OptIn}.
     263         */
     264        private static Progress increment(Progress aprogress, Phase aphase) {
     265                if (aprogress instanceof ProgressRounds && aphase instanceof OptInPhase)
     266                        return ((ProgressRounds) aprogress).advance();
     267                return aprogress;
    274268        }
    275269
     
    294288        public String toString() {
    295289                return "MOPACState[" + phase + "," + settings + "," + partyprofiles
    296                                 + "," + connections + "," + progress + "," + "]";
     290                                + "," + progress + "]";
    297291        }
    298292
     
    306300                LinkedList<Action> newactions = new LinkedList<Action>(actions);
    307301                newactions.addAll(newphase.getPartyStates().getActions());
    308                 return new MOPACState(newphase, newactions, connections, progress,
    309                                 settings, partyprofiles);
     302                return new MOPACState(newphase, newactions, progress, settings,
     303                                partyprofiles);
     304        }
     305
     306        @Override
     307        public int hashCode() {
     308                final int prime = 31;
     309                int result = 1;
     310                result = prime * result + ((actions == null) ? 0 : actions.hashCode());
     311                result = prime * result
     312                                + ((partyprofiles == null) ? 0 : partyprofiles.hashCode());
     313                result = prime * result + ((phase == null) ? 0 : phase.hashCode());
     314                result = prime * result
     315                                + ((progress == null) ? 0 : progress.hashCode());
     316                result = prime * result
     317                                + ((settings == null) ? 0 : settings.hashCode());
     318                return result;
     319        }
     320
     321        @Override
     322        public boolean equals(Object obj) {
     323                if (this == obj)
     324                        return true;
     325                if (obj == null)
     326                        return false;
     327                if (getClass() != obj.getClass())
     328                        return false;
     329                MOPACState other = (MOPACState) obj;
     330                if (actions == null) {
     331                        if (other.actions != null)
     332                                return false;
     333                } else if (!actions.equals(other.actions))
     334                        return false;
     335                if (partyprofiles == null) {
     336                        if (other.partyprofiles != null)
     337                                return false;
     338                } else if (!partyprofiles.equals(other.partyprofiles))
     339                        return false;
     340                if (phase == null) {
     341                        if (other.phase != null)
     342                                return false;
     343                } else if (!phase.equals(other.phase))
     344                        return false;
     345                if (progress == null) {
     346                        if (other.progress != null)
     347                                return false;
     348                } else if (!progress.equals(other.progress))
     349                        return false;
     350                if (settings == null) {
     351                        if (other.settings != null)
     352                                return false;
     353                } else if (!settings.equals(other.settings))
     354                        return false;
     355                return true;
    310356        }
    311357
  • protocol/src/main/java/geniusweb/protocol/session/mopac/PartyStates.java

    r21 r24  
    11package geniusweb.protocol.session.mopac;
    22
    3 import java.util.Arrays;
    4 import java.util.Collection;
    53import java.util.Collections;
    64import java.util.HashMap;
     
    1210import java.util.stream.Collectors;
    1311
     12import com.fasterxml.jackson.annotation.JsonAutoDetect;
     13import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
     14import com.fasterxml.jackson.annotation.JsonCreator;
     15import com.fasterxml.jackson.annotation.JsonProperty;
     16
    1417import geniusweb.actions.Action;
    1518import geniusweb.actions.EndNegotiation;
     
    1922
    2023/**
    21  * The current state of all participating parties. A party either notYetActed,
    22  * did action, reached an agreement, walked away or made a
     24 * Invariant: contains the current state of all participating parties. A party
     25 * either notYetActed, did action, reached an agreement, walked away or made a
    2326 * {@link ProtocolException}.
    2427 * <p>
     
    2629 * agreements and move remaining parties back to notYetActed.
    2730 *
    28  * This is not considering current time or checking actions.
    2931 */
     32@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
    3033public class PartyStates {
    3134        // all parties must be in exactly one state at all times.
     
    3538        private final List<PartyId> walkedAway;
    3639        private final Map<PartyId, ProtocolException> exceptions;
    37         private Map<PartyId, Integer> powers;
     40        private final Map<PartyId, Integer> powers;
     41
     42        @JsonCreator
     43        protected PartyStates(@JsonProperty("notYetActed") Set<PartyId> notYetActed,
     44                        @JsonProperty("actions") List<Action> actions,
     45                        @JsonProperty("agreements") Agreements agreements,
     46                        @JsonProperty("walkedAway") List<PartyId> walkedAway,
     47                        @JsonProperty("exceptions") Map<PartyId, ProtocolException> exceptions,
     48                        @JsonProperty("powers") Map<PartyId, Integer> powers) {
     49                this.notYetActed = notYetActed;
     50                this.actions = actions;
     51                this.agreements = agreements;
     52                this.walkedAway = walkedAway;
     53                this.exceptions = exceptions;
     54                this.powers = powers;
     55        }
    3856
    3957        /**
     
    5169        }
    5270
    53         public PartyStates(Set<PartyId> notYetActed, List<Action> actions,
    54                         Agreements agreements, List<PartyId> walkedAway,
    55                         Map<PartyId, ProtocolException> exceptions,
    56                         Map<PartyId, Integer> powers) {
    57                 this.notYetActed = notYetActed;
    58                 this.actions = actions;
    59                 this.agreements = agreements;
    60                 this.walkedAway = walkedAway;
    61                 this.exceptions = exceptions;
    62                 this.powers = powers;
    63         }
    64 
    65         /**
    66          *
    67          * @param action
    68          * @return new state with party done given action.
     71        /**
     72         *
     73         * @param action the action done by some party. The correctness of action,
     74         *               particularly of {@link Action#getActor()}, must be correct.
     75         * @return new state with party done given action. This just accepts any
     76         *         given action and is not considering number of rounds, time or
     77         *         whether an action is allowed.
     78         *
    6979         * @throws IllegalArgumentException if party doing action already acted.
    7080         *                                  This is just a safety check as legality
     
    151161
    152162        /**
    153          *
    154163         * @param actor
    155164         * @return {@link #notYetActed} with actor removed
    156          */
    157         private Set<PartyId> removeParty(PartyId actor) {
    158                 return removeParties(new HashSet<>(Arrays.asList(actor)));
     165         * @throws IllegalArgumentException if party already acted (not in
     166         *                                  {@link #notYetActed}).
     167         */
     168        private Set<PartyId> removeParty(PartyId party) {
     169                Set<PartyId> newActiveParties = new HashSet<>(notYetActed);
     170                if (!newActiveParties.remove(party))
     171                        throw new IllegalArgumentException(
     172                                        "Party " + party + " is not active, can't be removed");
     173                return newActiveParties;
     174
    159175        }
    160176
     
    169185        public Map<PartyId, ProtocolException> getExceptions() {
    170186                return Collections.unmodifiableMap(exceptions);
    171         }
    172 
    173         /**
    174          *
    175          * @param parties the parties to remove
    176          * @return {@link #notYetActed} without the given parties.
    177          */
    178         private Set<PartyId> removeParties(Collection<PartyId> parties) {
    179                 Set<PartyId> newActiveParties = new HashSet<>(notYetActed);
    180                 for (PartyId party : parties) {
    181                         if (!newActiveParties.remove(party))
    182                                 throw new IllegalArgumentException(
    183                                                 "Party " + party + " is not active, can't be removed");
    184                 }
    185                 return newActiveParties;
    186187        }
    187188
     
    204205
    205206        /**
    206          * @param type the type of actions to extract
     207         *
     208         * @return all parties that walked away
     209         */
     210        public List<PartyId> getWalkedAway() {
     211                return walkedAway;
     212        }
     213
     214        /**
     215         * @param <T>  the type of objects requested
     216         * @param type the type of actions to extract. Must be of type T, needed
     217         *             because of java's type erasure.
     218         *
    207219         * @return all actions of type done in this phase
    208220         */
     
    233245        }
    234246
     247        @Override
     248        public int hashCode() {
     249                final int prime = 31;
     250                int result = 1;
     251                result = prime * result + ((actions == null) ? 0 : actions.hashCode());
     252                result = prime * result
     253                                + ((agreements == null) ? 0 : agreements.hashCode());
     254                result = prime * result
     255                                + ((exceptions == null) ? 0 : exceptions.hashCode());
     256                result = prime * result
     257                                + ((notYetActed == null) ? 0 : notYetActed.hashCode());
     258                result = prime * result + ((powers == null) ? 0 : powers.hashCode());
     259                result = prime * result
     260                                + ((walkedAway == null) ? 0 : walkedAway.hashCode());
     261                return result;
     262        }
     263
     264        @Override
     265        public boolean equals(Object obj) {
     266                if (this == obj)
     267                        return true;
     268                if (obj == null)
     269                        return false;
     270                if (getClass() != obj.getClass())
     271                        return false;
     272                PartyStates other = (PartyStates) obj;
     273                if (actions == null) {
     274                        if (other.actions != null)
     275                                return false;
     276                } else if (!actions.equals(other.actions))
     277                        return false;
     278                if (agreements == null) {
     279                        if (other.agreements != null)
     280                                return false;
     281                } else if (!agreements.equals(other.agreements))
     282                        return false;
     283                if (exceptions == null) {
     284                        if (other.exceptions != null)
     285                                return false;
     286                } else if (!exceptions.equals(other.exceptions))
     287                        return false;
     288                if (notYetActed == null) {
     289                        if (other.notYetActed != null)
     290                                return false;
     291                } else if (!notYetActed.equals(other.notYetActed))
     292                        return false;
     293                if (powers == null) {
     294                        if (other.powers != null)
     295                                return false;
     296                } else if (!powers.equals(other.powers))
     297                        return false;
     298                if (walkedAway == null) {
     299                        if (other.walkedAway != null)
     300                                return false;
     301                } else if (!walkedAway.equals(other.walkedAway))
     302                        return false;
     303                return true;
     304        }
     305
    235306}
  • protocol/src/main/java/geniusweb/protocol/session/mopac/phase/DefaultPhase.java

    r23 r24  
    11package geniusweb.protocol.session.mopac.phase;
    2 
    3 import java.util.List;
    4 import java.util.stream.Collectors;
    5 
    6 import com.fasterxml.jackson.annotation.JsonIgnore;
    72
    83import geniusweb.actions.Action;
    94import geniusweb.actions.PartyId;
    10 import geniusweb.actions.Votes;
    115import geniusweb.protocol.ProtocolException;
    126import geniusweb.protocol.session.mopac.PartyStates;
     
    1711        protected final Long deadline;
    1812        protected final PartyStates partyStates;
    19 
    20         // don't serialize this, users don't need it..
    21         @JsonIgnore
    2213        protected final VotingEvaluator evaluator;
    2314
    24         // don't serialize this, it will cause very large file
    25         @JsonIgnore
    26         protected final Phase prevPhase;
    27 
    2815        /**
    29          *
    30          * @param actions     the actions done in this phase .
    31          * @param prevPhase   the previous phase, can be used to collect previous
    32          *                    votes etc.
    33          * @param partyStates
     16         * @param partyStates the {@link PartyStates}
    3417         * @param deadline    deadline for this phase, ms since 1970
     18         * @param evaluator   the {@link VotingEvaluator} to be used
    3519         */
    36         public DefaultPhase(Phase prevPhase, PartyStates partyStates, Long deadline,
     20        public DefaultPhase(PartyStates partyStates, Long deadline,
    3721                        VotingEvaluator evaluator) {
    3822                this.partyStates = partyStates;
    3923                this.deadline = deadline;
    40                 this.prevPhase = prevPhase;
    4124                this.evaluator = evaluator;
    4225        }
     
    5336
    5437        /**
    55          * @return all votes done in this phase.
    56          */
    57         public List<Votes> getVotes() {
    58                 return partyStates.getActions().stream()
    59                                 .filter(act -> act instanceof Votes).map(act -> (Votes) act)
    60                                 .collect(Collectors.toList());
    61         }
    62 
    63         /**
    6438         * Check if actor can do given action. Basic checks:
    6539         * <ul>
     
    7044         * </ul>
    7145         *
    72          * @param activeParties the currently active parties
    73          * @param actor
    74          * @param action
    75          * @param timems
    76          * @throws ProtocolException
    77          * @throw ProtocolException if the action violates the protocol, or null if
    78          *        ok
     46         * @param actor  the actor that really acted
     47         * @param action the action that was done
     48         * @param now    current time
     49         * @throws ProtocolException if the action violates the protocol
    7950         */
    80         protected void checkAction(PartyId actor, Action action, long timems)
     51        protected void checkAction(PartyId actor, Action action, long now)
    8152                        throws ProtocolException {
    8253                if (action == null)
     
    8657                                        "Incorrect actor info in action:" + action.getActor(),
    8758                                        actor);
    88                 if (isFinal(timems))
     59                if (isFinal(now))
    8960                        throw new ProtocolException("passed deadline", actor);
    9061                if (!(getAllowedActions().contains(action.getClass())))
    91                         throw new ProtocolException(
    92                                         "Action not allowed in " + this.getClass() + ":" + action,
    93                                         actor);
     62                        throw new ProtocolException("Action not allowed in "
     63                                        + this.getClass().getSimpleName() + ": " + action, actor);
    9464                if (!partyStates.getNotYetActed().contains(actor))
    9565                        throw new ProtocolException("Actor can not act anymore", actor);
     
    9868
    9969        /**
    100          * @param timems current time
    10170         * @return current PartyStates
    10271         */
     
    11685                        throw new IllegalArgumentException("Bug, illegal duration");
    11786                if (!isFinal(now))
    118                         throw new IllegalStateException(
    119                                         "next must only be called when phase isFinal");
    120                 if (!partyStates.getNotYetActed().isEmpty())
    121                         throw new IllegalStateException("Bug. State has not been finished");
     87                        throw new IllegalStateException("phase is not final");
    12288                return checkedNext(now + duration);
    12389        }
    12490
    12591        /**
     92         * As {@link #next(long, long)} but DefaultPhase already checked that 1.
     93         * there is enough time for a next phase 2. current state is final 3.
    12694         *
    127          * @param deadline
     95         * @param dl the deadline for the next phase (ms since 1970).
    12896         * @return the next phase
    12997         */
    130         protected abstract Phase checkedNext(long deadline);
     98        protected abstract Phase checkedNext(long dl);
    13199
    132100        @Override
    133101        public String toString() {
    134                 // don't print prev state, it will give HUGE list because it also
    135                 // contains prevstate.....
    136102                return getClass().getSimpleName() + "[" + partyStates + "," + deadline
    137103                                + "," + evaluator + "]";
    138104        }
     105
     106        @Override
     107        public int hashCode() {
     108                final int prime = 31;
     109                int result = 1;
     110                result = prime * result
     111                                + ((deadline == null) ? 0 : deadline.hashCode());
     112                result = prime * result
     113                                + ((evaluator == null) ? 0 : evaluator.hashCode());
     114                result = prime * result
     115                                + ((partyStates == null) ? 0 : partyStates.hashCode());
     116                return result;
     117        }
     118
     119        @Override
     120        public boolean equals(Object obj) {
     121                if (this == obj)
     122                        return true;
     123                if (obj == null)
     124                        return false;
     125                if (getClass() != obj.getClass())
     126                        return false;
     127                DefaultPhase other = (DefaultPhase) obj;
     128                if (deadline == null) {
     129                        if (other.deadline != null)
     130                                return false;
     131                } else if (!deadline.equals(other.deadline))
     132                        return false;
     133                if (evaluator == null) {
     134                        if (other.evaluator != null)
     135                                return false;
     136                } else if (!evaluator.equals(other.evaluator))
     137                        return false;
     138                if (partyStates == null) {
     139                        if (other.partyStates != null)
     140                                return false;
     141                } else if (!partyStates.equals(other.partyStates))
     142                        return false;
     143                return true;
     144        }
    139145}
  • protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OfferPhase.java

    r23 r24  
    44import java.util.List;
    55import java.util.stream.Collectors;
     6
     7import com.fasterxml.jackson.annotation.JsonCreator;
     8import com.fasterxml.jackson.annotation.JsonProperty;
    69
    710import geniusweb.actions.Action;
     
    1821public class OfferPhase extends DefaultPhase {
    1922
    20         public OfferPhase(Phase prevPhase, PartyStates partyStates, Long deadlinems,
    21                         VotingEvaluator evaluator) {
    22                 super(prevPhase, partyStates, deadlinems, evaluator);
     23        @JsonCreator
     24        public OfferPhase(@JsonProperty("partyStates") PartyStates partyStates,
     25                        @JsonProperty("deadlinems") Long deadlinems,
     26                        @JsonProperty("evaluator") VotingEvaluator evaluator) {
     27                super(partyStates, deadlinems, evaluator);
    2328        }
    2429
     
    3035                        return this.with(ex);
    3136                }
    32                 return new OfferPhase(prevPhase, partyStates.with(action), deadline,
    33                                 evaluator);
     37                return new OfferPhase(partyStates.with(action), deadline, evaluator);
    3438        }
    3539
     
    4246        public OfferPhase with(ProtocolException e) {
    4347                System.out.println("Party kicked because of protocol exception:" + e);
    44                 return new OfferPhase(prevPhase, partyStates.with(e), deadline,
    45                                 evaluator);
     48                return new OfferPhase(partyStates.with(e), deadline, evaluator);
    4649        }
    4750
    4851        @Override
    4952        public Phase finish() {
    50                 return new OfferPhase(prevPhase, partyStates.finish(), deadline,
    51                                 evaluator);
     53                return new OfferPhase(partyStates.finish(), deadline, evaluator);
    5254        }
    5355
    5456        @Override
    5557        public VotingPhase checkedNext(long deadln) {
    56                 return new VotingPhase(this, partyStates.flush(), deadln, evaluator);
     58                return new VotingPhase(getOffers(), partyStates.flush(), deadln,
     59                                evaluator);
    5760        }
    5861
    59         public List<Bid> getOffers() {
     62        protected List<Bid> getOffers() {
    6063                return partyStates.getActions(Offer.class).stream()
    6164                                .map(offer -> offer.getBid()).collect(Collectors.toList());
  • protocol/src/main/java/geniusweb/protocol/session/mopac/phase/OptInPhase.java

    r23 r24  
    55import java.util.Map;
    66import java.util.stream.Collectors;
     7
     8import com.fasterxml.jackson.annotation.JsonCreator;
     9import com.fasterxml.jackson.annotation.JsonProperty;
    710
    811import geniusweb.actions.Action;
     
    2023public class OptInPhase extends DefaultPhase {
    2124
    22         protected OptInPhase(Phase prevPhase, PartyStates partyStates,
    23                         Long deadlinems, VotingEvaluator evaluator) {
    24                 super(prevPhase, partyStates, deadlinems, evaluator);
     25        /**
     26         * The votes received in the {@link VotingPhase}
     27         */
     28        private final List<Votes> votes;
     29
     30        @JsonCreator
     31        protected OptInPhase(@JsonProperty("votes") List<Votes> votes,
     32                        @JsonProperty("partyStates") PartyStates partyStates,
     33                        @JsonProperty("deadlinems") Long deadlinems,
     34                        @JsonProperty("evaluator") VotingEvaluator evaluator) {
     35                super(partyStates, deadlinems, evaluator);
     36                this.votes = votes;
    2537        }
    2638
    2739        @Override
    2840        public Inform getInform() {
    29                 return new OptIn(((VotingPhase) prevPhase).getVotes());
     41                return new OptIn(votes);
    3042        }
    3143
     
    3547                        checkAction(actor, action, now);
    3648                        if (action instanceof Votes)
    37                                 checkExtends(action);
     49                                checkExtends((Votes) action);
    3850
    39                         return new OptInPhase(prevPhase, partyStates.with(action), deadline,
     51                        return new OptInPhase(votes, partyStates.with(action), deadline,
    4052                                        evaluator);
    4153
     
    4860         * Check that this action extends previous action.
    4961         *
    50          * @param action
    51          * @param phase
     62         * @param newvotes new {@link Votes} just received
    5263         * @throws ProtocolException if this action does not correctly extend
    5364         *                           previous vote.
    5465         */
    55         private void checkExtends(Action action) throws ProtocolException {
    56 
    57                 Votes votes = (Votes) action;
    58                 PartyId actor = action.getActor();
     66        private void checkExtends(Votes newvotes) throws ProtocolException {
     67                PartyId actor = newvotes.getActor();
    5968                // this actor is active so he must have voted in previous round.
    60                 Votes prevVotes = ((VotingPhase) prevPhase).getVotes().stream()
    61                                 .filter(v -> v.getActor().equals(actor)).findFirst().get();
    62                 if (!(votes.isExtending(prevVotes)))
    63                         throw new ProtocolException("New votes " + action
     69                Votes prevVotes = votes.stream().filter(v -> v.getActor().equals(actor))
     70                                .findFirst().get();
     71                if (!(newvotes.isExtending(prevVotes)))
     72                        throw new ProtocolException("New votes " + newvotes
    6473                                        + " does not extend previous vote " + prevVotes, actor);
    6574        }
     
    6776        @Override
    6877        public OptInPhase with(ProtocolException e) {
    69                 return new OptInPhase(prevPhase, partyStates.with(e), deadline,
    70                                 evaluator);
     78                return new OptInPhase(votes, partyStates.with(e), deadline, evaluator);
    7179        }
    7280
     
    8492                PartyStates finalStates = states.with(newAgree);
    8593
    86                 return new OptInPhase(prevPhase, finalStates, deadline, evaluator);
     94                return new OptInPhase(votes, finalStates, deadline, evaluator);
    8795        }
    8896
    8997        @Override
    9098        public OfferPhase checkedNext(long newdeadline) {
    91                 return new OfferPhase(this, partyStates.flush(), newdeadline,
    92                                 evaluator);
     99                return new OfferPhase(partyStates.flush(), newdeadline, evaluator);
    93100        }
    94101
  • protocol/src/main/java/geniusweb/protocol/session/mopac/phase/Phase.java

    r23 r24  
    22
    33import java.util.List;
    4 import java.util.Set;
    54
    65import com.fasterxml.jackson.annotation.JsonAutoDetect;
    76import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
     7import com.fasterxml.jackson.annotation.JsonSubTypes;
     8import com.fasterxml.jackson.annotation.JsonTypeInfo;
    89
    910import geniusweb.actions.Action;
     
    1718 * A Phase is a part of the round structure. In each round parties have to take
    1819 * multiple actions. Each action is part of a phase.
    19  *
     20 *
     21 * Invariant: A phase object handles negotiation events, ensuring that the
     22 * events are handled according to the possible actions in this phase. A phase
     23 * object must always remain in a consistent state. It does so by modifying the
     24 * contained {@link PartyStates} as needed.
     25 * <p>
     26 * The standard exception handling is assumed: unchecked exceptions are thrown
     27 * only if there is a bug in the protocol. Because none of the functions in this
     28 * interface throws, any error must be either ignored or the party must be
     29 * kicked.
    2030 */
    21 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
     31@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
     32@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
     33@JsonSubTypes({ @JsonSubTypes.Type(value = OfferPhase.class),
     34                @JsonSubTypes.Type(value = OptInPhase.class),
     35                @JsonSubTypes.Type(value = VotingPhase.class) })
    2236public interface Phase {
    2337        public static final Long PHASE_MAXTIME = 30000l; // 30sec
     
    2842         * handled by updating the PartyStates
    2943         *
    30          * @param prevPhases the list of all previous phases
    31          * @param actor      the real actor
    32          * @param action     the action submitted by actor, which this phase can
    33          *                   really handle.
    34          * @param now        the current time
     44         * @param actor  the real actor (may differ from the actor contained in the
     45         *               action)
     46         * @param action the action submitted by actor, which this phase can really
     47         *               handle.
     48         * @param now    the current time
    3549         * @return new VotingPhase
    3650         */
     
    7387         * after {@link #finish()}
    7488         *
    75          * @param now      the curren time
    76          * @param duration the max duration of the next phase. Must be between
     89         * @param now      the current time
     90         * @param duration the max duration (ms) of the next phase. Must be between
    7791         *                 {@link #PHASE_MINTIME} and {@link #PHASE_MAXTIME}. Also
    7892         *                 make sure that now+duration is at most at the total
     
    8397
    8498        /**
    85          * Get the voting evaluator
    86          *
    87          * @return
     99         * @return the voting evaluator
    88100         */
    89101        public VotingEvaluator getEvaluator();
     
    97109
    98110        /**
    99          * @param now the current time
    100          *
    101111         * @return the party states. Notice that someone must call
    102          *         {@link PartyStates#finish(Set)} if passed the deadline.
     112         *         {@link PartyStates#finish()} if passed the deadline.
    103113         */
    104114        public PartyStates getPartyStates();
  • protocol/src/main/java/geniusweb/protocol/session/mopac/phase/VotingPhase.java

    r23 r24  
    33import java.util.Arrays;
    44import java.util.List;
     5import java.util.stream.Collectors;
     6
     7import com.fasterxml.jackson.annotation.JsonCreator;
     8import com.fasterxml.jackson.annotation.JsonProperty;
    59
    610import geniusweb.actions.Action;
     
    1014import geniusweb.inform.Inform;
    1115import geniusweb.inform.Voting;
     16import geniusweb.issuevalue.Bid;
    1217import geniusweb.protocol.ProtocolException;
    1318import geniusweb.protocol.session.mopac.PartyStates;
     
    1621public class VotingPhase extends DefaultPhase {
    1722
    18         VotingPhase(Phase prevPhase, PartyStates partyStates, Long deadlinems,
    19                         VotingEvaluator evaluator) {
    20                 super(prevPhase, partyStates, deadlinems, evaluator);
     23        /**
     24         * the offers received in the {@link OfferPhase}
     25         */
     26        private final List<Bid> offers;
     27
     28        @JsonCreator
     29        protected VotingPhase(@JsonProperty("offers") List<Bid> offers,
     30                        @JsonProperty("partyStates") PartyStates partyStates,
     31                        @JsonProperty("deadlinems") Long deadlinems,
     32                        @JsonProperty("evaluator") VotingEvaluator evaluator) {
     33                super(partyStates, deadlinems, evaluator);
     34                this.offers = offers;
    2135        }
    2236
     
    2842                        return this.with(ex);
    2943                }
    30                 return new VotingPhase(prevPhase, partyStates.with(action), deadline,
     44                return new VotingPhase(offers, partyStates.with(action), deadline,
    3145                                evaluator);
    3246        }
     
    3448        @Override
    3549        public Inform getInform() {
    36                 return new Voting(((OfferPhase) prevPhase).getOffers(),
    37                                 partyStates.getPowers());
     50                return new Voting(offers, partyStates.getPowers());
    3851        }
    3952
    4053        @Override
    4154        public VotingPhase with(ProtocolException e) {
    42                 return new VotingPhase(prevPhase, partyStates.with(e), deadline,
     55                return new VotingPhase(offers, partyStates.with(e), deadline,
    4356                                evaluator);
    4457        }
     
    4659        @Override
    4760        public VotingPhase finish() {
    48                 return new VotingPhase(prevPhase, partyStates.finish(), deadline,
     61                return new VotingPhase(offers, partyStates.finish(), deadline,
    4962                                evaluator);
    5063        }
     
    5265        @Override
    5366        protected Phase checkedNext(long deadln) {
    54                 return new OptInPhase(this, partyStates.flush(), deadln, evaluator);
     67                return new OptInPhase(getVotes(), partyStates.flush(), deadln,
     68                                evaluator);
    5569        }
    5670
     
    6074        }
    6175
     76        /**
     77         * @return all votes done in this phase.
     78         */
     79        public List<Votes> getVotes() {
     80                return partyStates.getActions().stream()
     81                                .filter(act -> act instanceof Votes).map(act -> (Votes) act)
     82                                .collect(Collectors.toList());
     83        }
     84
    6285}
  • protocol/src/main/java/geniusweb/protocol/session/saop/SAOP.java

    r21 r24  
    3838
    3939/**
    40  *
    41  * All parties are first sent the {@link SessionSettings}. Only parties
    42  * specified initially in the settings do participate.
     40 * The protocol runs as follows
    4341 * <ol>
    44  * The protocol tries to start all parties. If not all parties start, the
     42 * <li>The protocol tries to start all parties. If not all parties start, the
    4543 * parties are freed up and another attempt is done to start all parties some
    4644 * time later.
     45 * <li>All parties are sent the {@link SessionSettings}. Only parties specified
     46 * initially in the settings do participate.
    4747 * <li>The session deadline clock now starts ticking.
    4848 * <li>All parties are sent their settings.
     
    6161 * the protocol.
    6262 * <p>
    63  * Threadsafe: all entrypoints are synhronized.
     63 * Thread safe: all entry points are synchronized.
    6464 */
    6565public class SAOP extends DefaultListenable<ProtocolEvent>
     
    7979        /**
    8080         *
    81          * @param state normally the initial state coming from SAOPSettings
     81         * @param state  normally the initial state coming from SAOPSettings
     82         * @param logger the Reporter to log to
    8283         */
    8384        public SAOP(SAOPState state, Reporter logger) {
  • protocol/src/main/java/geniusweb/protocol/session/saop/SAOPSettings.java

    r21 r24  
    2727         *                     protocol. But SAOP can be initialized with less, for
    2828         *                     use in TournamentSettings.
    29          * @param deadline
     29         * @param deadline     the deadline of the negotiation
    3030         */
    3131        @JsonCreator
  • protocol/src/main/java/geniusweb/protocol/session/saop/SAOPState.java

    r23 r24  
    3333        /**
    3434         *
    35          * @param actions
     35         * @param actions       the actions done by the parties
    3636         * @param conns         the existing party connections. we assume ownership
    3737         *                      of this so it should not be modified although
     
    8888        /**
    8989         *
    90          * @param e             the error that occured
    91          * @param currentTimeMs the current time in ms since 1970, see
    92          *                      {@link System#currentTimeMillis()}
     90         * @param e the error that occured
    9391         * @return a new state with the error set.
    9492         */
     
    160158
    161159        /**
    162          * @param actor         the actor that did this action. Can be used to check
    163          *                      if action is valid. NOTICE caller has to make sure
    164          *                      the current state is not final.
    165          * @param action        the action that was proposed by actor.
    166          * @param currentTimeMs the current time in ms since 1970, see
    167          *                      {@link System#currentTimeMillis()}
    168          * @return new SessionState with the action added as last action.
     160         * @param actor  the actor that did this action. Can be used to check if
     161         *               action is valid. NOTICE caller has to make sure the current
     162         *               state is not final.
     163         * @param action the action that was proposed by actor.
     164         * @return new SAOPState with the action added as last action.
    169165         */
    170166
  • protocol/src/main/java/geniusweb/protocol/session/shaop/BareSHAOPState.java

    r23 r24  
    4444        /**
    4545         *
    46          * @param actions    value for actions done so far. null equals to empty
    47          *                   list
    48          * @param conns      the currently existing connections. Can be empty/null.
    49          *                   Each connection represents another party. Normally the
    50          *                   connections are in the order SHAOP1,COB1,SHAOP2,COB2,..
    51          *                   so 2 parties for each team. The protocol should check
    52          *                   this.
    53          * @param progr      the {@link Progress} that governs this session. Can be
    54          *                   null if session did not yet start.
    55          * @param settings   the settings used for the session
    56          * @param e          the exception that occured, usually null. All errors
    57          *                   occuring due to faulty {@link Action}s translate to
    58          *                   {@link ProtocolException}s. All errors in our own code
    59          *                   are bugs (not ProtocolExceptions) and should result in
    60          *                   a throw.
    61          * @param teamNr     the teamnr (0,1,2..) that has the turn. 2* gives index
    62          *                   {@link #connections} and settings
    63          * @param partyNrs   a map for each known PartyId to a number. The number is
    64          *                   the index in both {@link SHAOPSettings#getTeams()} and
    65          *                   in {@link #connections}. null is empyt map.
    66          * @param totalSpent total accumulated elicitation costs so far. only SHAOP
    67          *                   parties accumulate costs. null = empty map
     46         * @param actions  value for actions done so far. null equals to empty list
     47         * @param conns    the currently existing connections. Can be empty/null.
     48         *                 Each connection represents another party. Normally the
     49         *                 connections are in the order SHAOP1,COB1,SHAOP2,COB2,..
     50         *                 so 2 parties for each team. The protocol should check
     51         *                 this.
     52         * @param progr    the {@link Progress} that governs this session. Can be
     53         *                 null if session did not yet start.
     54         * @param settings the settings used for the session
     55         * @param e        the exception that occured, usually null. All errors
     56         *                 occuring due to faulty {@link Action}s translate to
     57         *                 {@link ProtocolException}s. All errors in our own code
     58         *                 are bugs (not ProtocolExceptions) and should result in a
     59         *                 throw.
     60         * @param teamNr   the teamnr (0,1,2..) that has the turn. 2* gives index
     61         *                 {@link #connections} and settings
     62         * @param partyNrs a map for each known PartyId to a number. The number is
     63         *                 the index in both {@link SHAOPSettings#getTeams()} and in
     64         *                 {@link #connections}. null is empyt map.
     65         * @param spent    total accumulated elicitation costs so far for each
     66         *                 party. only SHAOP parties accumulate costs. null = empty
     67         *                 map
    6868         */
    6969        @JsonCreator
  • protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOP.java

    r21 r24  
    8585        /**
    8686         *
    87          * @param state normally the initial state coming from SAOPSettings
     87         * @param state  normally the initial state coming from SAOPSettings
     88         * @param logger the {@link Reporter} to use
    8889         */
    8990        public SHAOP(SHAOPState state, Reporter logger) {
  • protocol/src/main/java/geniusweb/protocol/session/shaop/SHAOPState.java

    r21 r24  
    3838         * see {@link BareSHAOPState}.
    3939         */
     40        /**
     41         *
     42         * @param actions       see
     43         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     44         * @param conns         see
     45         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     46         * @param progress      see
     47         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     48         * @param settings      see
     49         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     50         * @param e             see
     51         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     52         * @param teamNr        see
     53         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     54         * @param partytNumbers see
     55         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     56         * @param spent         see
     57         *                      {@link BareSHAOPState#BareSHAOPState(List, ProtocolToPartyConnections, Progress, SHAOPSettings, ProtocolException, int, Map, Map)}.
     58         */
    4059        @JsonCreator
    4160        public SHAOPState(@JsonProperty("actions") List<Action> actions,
     
    7291        /**
    7392         *
    74          * @param party
    75          * @return true iff party is a SHAOP party.
     93         * @param party the {@link PartyId} to test
     94         * @return true iff party is a SHAOP party (not a COB party).
    7695         */
    7796        public boolean isShaopParty(PartyId party) {
     
    81100        /**
    82101         *
    83          * @return the team leader {@link PartyId}s.
     102         * @return the team leader {@link PartyId}s which are the SHAOP parties.
    84103         */
    85104        private Set<PartyId> getLeaders() {
     
    149168        /**
    150169         *
    151          * @param e             the error that occured
    152          * @param currentTimeMs the current time in ms since 1970, see
    153          *                      {@link System#currentTimeMillis()}
     170         * @param e the error that occured
    154171         * @return a new state with the error set.
    155172         */
     
    201218
    202219        /**
    203          * @param actor         the actor that did this action. Can be used to check
    204          *                      if action is valid. NOTICE caller has to make sure
    205          *                      the current state is not final.
    206          * @param action        the action that was proposed by actor.
    207          * @param currentTimeMs the current time in ms since 1970, see
    208          *                      {@link System#currentTimeMillis()}
     220         * @param actor  the actor that did this action. Can be used to check if
     221         *               action is valid. NOTICE caller has to make sure the current
     222         *               state is not final.
     223         * @param action the action that was proposed by actor.
    209224         * @return new SessionState with the action added as last action.
    210225         */
  • protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsProtocol.java

    r20 r24  
    3434        /**
    3535         *
    36          * @param state
     36         * @param state  the {@link AllPermutationsState}
    3737         * @param logger used for all logging, about the tournament, and the created
    3838         *               the session and protocols.
     
    8181                        long now = System.currentTimeMillis();
    8282                        if (sessionstate.isFinal(now)) {
    83                                 // List<TeamOfPartiesAndProfiles> participants =
    84                                 // sessionstate.getSettings().getParticipants()
    8583                                SessionResult result = sessionstate.getResult();
    8684                                state = state.with(result);
  • protocol/src/main/java/geniusweb/protocol/tournament/allpermutations/AllPermutationsSettings.java

    r21 r24  
    6969        /**
    7070         *
    71          * @param teams             a list of {@link Team}s. Must contain at least
    72          *                          {@link #teamsPerSession} elements. The
    73          *                          <teamsize> must match the protocol: (SAOP:1,
    74          *                          SHAOP:2)
    75          * @param reuseTeams        if true, we use PermutationsWithReturn, if false
    76          *                          we use PermutationsWithoutReturn to create the
    77          *                          teams.
    78          * @param plists            list of available {@link ProfileList}s to be
    79          *                          permutated over the teams. Each
    80          *                          {@link ProfileList} must contain <teamsize>
    81          *                          elements.
    82          * @param teamsPerSession   number of parties per session, must be at least
    83          *                          2.
    84          * @param sesettings        The generic {@link SessionSetting}.
    85          *                          {@link SessionSettings#with(PartyWithProfile)}
    86          *                          will be used to add the required
    87          *                          {@link PartyWithProfile}s
    88          * @param numberTournaments the number of times the tournament should be
    89          *                          run.
     71         * @param teams           a list of {@link Team}s. Must contain at least
     72         *                        {@link #teamsPerSession} elements. The
     73         *                        {@link #teamsPerSession} must match the protocol:
     74         *                        (SAOP:1, SHAOP:2)
     75         * @param reuseTeams      if true, we use PermutationsWithReturn, if false
     76         *                        we use PermutationsWithoutReturn to create the
     77         *                        teams.
     78         * @param plists          list of available {@link ProfileList}s to be
     79         *                        permutated over the teams. Each
     80         *                        {@link ProfileList} must contain
     81         *                        {@link #teamsPerSession} elements.
     82         * @param teamsPerSession number of parties per session, must be at least 2.
     83         * @param sesettings      The generic {@link SessionSettings}.
     84         *                        {@link SessionSettings#with(TeamOfPartiesAndProfiles)}
     85         *                        will be used to add the required
     86         *                        {@link TeamOfPartiesAndProfiles}s
     87         * @param nTournaments    the number of times the tournament should be run.
    9088         */
    9189        @JsonCreator
  • protocol/src/test/java/geniusweb/protocol/session/mopac/MOPACTest.java

    r21 r24  
    22
    33import static org.junit.Assert.assertEquals;
     4import static org.junit.Assert.assertFalse;
    45import static org.junit.Assert.assertNotNull;
    56import static org.junit.Assert.assertTrue;
    67import static org.mockito.Matchers.any;
     8import static org.mockito.Matchers.anyLong;
    79import static org.mockito.Mockito.mock;
    810import static org.mockito.Mockito.times;
     
    1214import java.io.IOException;
    1315import java.util.Arrays;
     16import java.util.Date;
    1417import java.util.List;
    1518
    1619import org.junit.Before;
    17 import org.junit.Ignore;
    1820import org.junit.Test;
    1921
     
    2830import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
    2931import geniusweb.protocol.partyconnection.ProtocolToPartyConnFactory;
     32import geniusweb.protocol.session.mopac.phase.OfferPhase;
     33import geniusweb.protocol.session.mopac.phase.Phase;
     34import geniusweb.protocol.session.mopac.phase.VotingPhase;
    3035import tudelft.utilities.logging.Reporter;
    3136import tudelft.utilities.repository.NoResourcesNowException;
     
    5762                        conn3 = mock(ProtocolToPartyConn.class);
    5863
     64        private List<ProtocolToPartyConn> connections;
     65
    5966        @Before
    6067        public void before() throws JsonParseException, JsonMappingException,
     
    6370                mopac = settings.getProtocol(logger);
    6471
    65                 List connections = Arrays.asList(conn1, conn2, conn3);
     72                connections = Arrays.asList(conn1, conn2, conn3);
    6673                when(factory.connect(any(List.class))).thenReturn(connections);
    6774
     
    94101        }
    95102
    96         @Ignore
    97103        @Test
    98104        public void testWorkingCheckDeadline()
     
    101107                mopac.start(factory);
    102108
    103                 System.out.println(mopac.getState());
    104 
     109                assertFalse(mopac.getState().isFinal(System.currentTimeMillis()));
    105110                // we have deadline in 100ms so check
    106111                Thread.sleep(200);
    107 
    108                 System.out.println(mopac.getState());
    109112                assertTrue(mopac.getState().isFinal(System.currentTimeMillis()));
    110113        }
    111114
    112         @Ignore
    113115        @Test
    114116        public void testSubscribedToConnections() {
     
    119121        }
    120122
    121         @Ignore
    122123        @Test
    123124        public void testActionIsBroadcast()
     
    134135        }
    135136
    136         @Test
    137         public void testAgreementTerminates() {
    138 
    139         }
     137        /**
     138         * Fatal error occurs, run should fail
     139         */
     140        @Test(expected = RuntimeException.class)
     141        public void testPartyFailsConnect()
     142                        throws IOException, NoResourcesNowException {
     143                ProtocolToPartyConnFactory factory1 = mock(
     144                                ProtocolToPartyConnFactory.class);
     145                // irrecoverable fail test
     146                when(factory1.connect(any(List.class)))
     147                                .thenThrow(new IOException("Failed to connect to parties"));
     148
     149                mopac.start(factory1);
     150
     151        }
     152
     153        /**
     154         * Nonfatal error occurs, protocol should retry till success
     155         */
     156        @Test
     157        public void testPartyFailsConnect2ndtimeOK()
     158                        throws IOException, NoResourcesNowException {
     159                long now = System.currentTimeMillis();
     160                ProtocolToPartyConnFactory factory1 = mock(
     161                                ProtocolToPartyConnFactory.class);
     162                // recoverable fail, and then success.
     163                when(factory1.connect(any(List.class)))
     164                                .thenThrow(new NoResourcesNowException("try again later",
     165                                                new Date(now + 100)))
     166                                .thenReturn(connections);
     167
     168                mopac.start(factory1);
     169
     170        }
     171
     172        /**
     173         * Test that in Offer phase, and party does action, the next phase is
     174         * entered.
     175         */
     176        @Test
     177        public void testProceedsNextPhase() {
     178                // the state before the last party makes the offer
     179                MOPACState offerstate = mock(MOPACState.class);
     180                when(offerstate.getSettings()).thenReturn(settings);
     181                OfferPhase offerphase = mock(OfferPhase.class);
     182                when(offerphase.isFinal(anyLong())).thenReturn(false);
     183                when(offerstate.getPhase()).thenReturn(offerphase);
     184
     185                // the phase where all parties placed an offer
     186                OfferPhase finalofferphase = mock(OfferPhase.class);
     187                when(finalofferphase.isFinal(anyLong())).thenReturn(true);
     188                MOPACState finalofferstate = mock(MOPACState.class);
     189                when(finalofferstate.getPhase()).thenReturn(finalofferphase);
     190                when(finalofferstate.finishPhase()).thenReturn(finalofferstate);
     191
     192                when(offerstate.with(any(PartyId.class), any(Action.class), anyLong()))
     193                                .thenReturn(finalofferstate);
     194
     195                // the phase where all parties can start voting.
     196                // this is the state to be reached.
     197                long now = System.currentTimeMillis();
     198                MOPACState votingstate = mock(MOPACState.class);
     199                Phase votingphase = mock(VotingPhase.class);
     200                PartyStates votingpartystates = mock(PartyStates.class);
     201                when(votingphase.getDeadline()).thenReturn(now + 100);
     202                when(votingphase.getPartyStates()).thenReturn(votingpartystates);
     203                when(votingstate.getPhase()).thenReturn(votingphase);
     204
     205                when(finalofferstate.nextPhase(anyLong())).thenReturn(votingstate);
     206
     207                mopac = new MOPAC(offerstate, logger);
     208                Offer action = mock(Offer.class);
     209                mopac.actionRequest(conn3, action, now);
     210
     211                // check that the action result in reaching the voting phase
     212                assertEquals(votingstate, mopac.getState());
     213        }
     214
    140215}
  • protocol/src/test/java/geniusweb/protocol/session/mopac/PartyStatesTest.java

    r21 r24  
    33import static org.junit.Assert.assertEquals;
    44
     5import java.io.IOException;
     6import java.net.URISyntaxException;
    57import java.util.Arrays;
    68import java.util.Collections;
    79import java.util.HashMap;
    810import java.util.HashSet;
     11import java.util.List;
    912import java.util.Map;
    1013
    1114import org.junit.Test;
    1215
     16import com.fasterxml.jackson.core.JsonProcessingException;
     17import com.fasterxml.jackson.databind.ObjectMapper;
     18
    1319import geniusweb.actions.PartyId;
    1420import geniusweb.inform.Agreements;
    1521import geniusweb.protocol.ProtocolException;
     22import tudelft.utilities.junit.GeneralTests;
    1623
    17 public class PartyStatesTest {
     24public class PartyStatesTest extends GeneralTests<PartyStates> {
     25        private final ObjectMapper jackson = new ObjectMapper();
    1826
    1927        private final PartyId party1 = new PartyId("party1");
     
    2230
    2331        private final Map<PartyId, Integer> powers = new HashMap<>();
    24         private final PartyStates states;
     32        private final PartyStates states1, states1a, states2;
     33        private final String serialized = "{\"notYetActed\":[\"party2\",\"party1\",\"party3\"],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{\"party2\":3,\"party1\":2,\"party3\":3}}";
    2534
    2635        public PartyStatesTest() {
     36
     37                // FIXME use the other constructor to really test this.
     38//              PartyStates(Set<PartyId> notYetActed, List<Action> actions,
     39//                              Agreements agreements, List<PartyId> walkedAway,
     40//                              Map<PartyId, ProtocolException> exceptions,
     41//                              Map<PartyId, Integer> powers)
     42//             
    2743                powers.put(party1, 2);
    2844                powers.put(party2, 3);
     45                states2 = new PartyStates(powers);
    2946                powers.put(party3, 3);
    30                 states = new PartyStates(powers);
     47                states1 = new PartyStates(powers);
     48                states1a = new PartyStates(powers);
     49        }
     50
     51        @Override
     52        public List<List<PartyStates>> getGeneralTestData() {
     53                return Arrays.asList(Arrays.asList(states1, states1a),
     54                                Arrays.asList(states2));
     55        }
     56
     57        @Override
     58        public List<String> getGeneralTestStrings() {
     59                return Arrays.asList(
     60                                "PartyStates.*\\[party2, party1, party3\\],\\[\\],Agreements\\{\\},\\[\\],\\{\\}.*",
     61                                "PartyStates.*\\[party2, party1\\],\\[\\],Agreements\\{\\},\\[\\],\\{\\}.*");
    3162        }
    3263
    3364        @Test
    3465        public void testBasics() {
    35                 assertEquals(powers.keySet(), states.getNegotiatingParties());
    36                 assertEquals(powers.keySet(), states.getNotYetActed());
    37                 assertEquals(0, states.getExceptions().size());
     66                assertEquals(powers.keySet(), states1.getNegotiatingParties());
     67                assertEquals(powers.keySet(), states1.getNotYetActed());
     68                assertEquals(0, states1.getExceptions().size());
    3869        }
    3970
    4071        @Test
    4172        public void testException() {
    42                 PartyStates newstates = states
     73                PartyStates newstates = states1
    4374                                .with(new ProtocolException("bla", party1));
    4475                assertEquals(new Agreements(), newstates.getAgreements());
    45                 assertEquals(powers.keySet(), states.getNegotiatingParties());
     76                assertEquals(powers.keySet(), states1.getNegotiatingParties());
    4677                assertEquals(new HashSet<>(Arrays.asList(party2, party3)),
    4778                                newstates.getNotYetActed());
     
    5081        @Test
    5182        public void testFinish() {
    52                 PartyStates newstates = states.finish();
     83                PartyStates newstates = states1.finish();
    5384                assertEquals(new Agreements(), newstates.getAgreements());
    54                 assertEquals(powers.keySet(), states.getNegotiatingParties());
     85                assertEquals(powers.keySet(), states1.getNegotiatingParties());
    5586                assertEquals(Collections.emptySet(), newstates.getNotYetActed());
    5687        }
     88
     89        @Test
     90        public void testDeserialize() throws IOException {
     91                PartyStates obj = jackson.readValue(serialized, PartyStates.class);
     92                System.out.println(obj);
     93                assertEquals(states1, obj);
     94        }
     95
     96        @Test
     97        public void testSerialize()
     98                        throws JsonProcessingException, URISyntaxException {
     99
     100                String string = jackson.writeValueAsString(states1);
     101                System.out.println(string);
     102                assertEquals(serialized, string);
     103        }
     104
     105        @Test
     106        public void testWalkAway() {
     107                PartyStates walkawaystate = states1.withWalkAway(party2);
     108                assertEquals(new HashSet<>(Arrays.asList(party1, party3)),
     109                                walkawaystate.getNotYetActed());
     110                assertEquals(Arrays.asList(party2), walkawaystate.getWalkedAway());
     111        }
    57112}
  • protocol/src/test/java/geniusweb/protocol/session/mopac/phase/OfferPhaseTest.java

    r21 r24  
    44import static org.junit.Assert.assertFalse;
    55import static org.junit.Assert.assertTrue;
     6import static org.junit.Assert.fail;
    67import static org.mockito.Mockito.mock;
    7 
     8import static org.mockito.Mockito.when;
     9
     10import java.io.IOException;
     11import java.net.URISyntaxException;
     12import java.util.Arrays;
    813import java.util.Collections;
    914import java.util.HashMap;
     15import java.util.List;
    1016import java.util.Map;
    1117
    1218import org.junit.Test;
    1319
     20import com.fasterxml.jackson.core.JsonProcessingException;
     21import com.fasterxml.jackson.databind.ObjectMapper;
     22
     23import geniusweb.actions.Accept;
    1424import geniusweb.actions.EndNegotiation;
     25import geniusweb.actions.Offer;
    1526import geniusweb.actions.PartyId;
    1627import geniusweb.actions.Votes;
     28import geniusweb.inform.YourTurn;
     29import geniusweb.issuevalue.Bid;
     30import geniusweb.issuevalue.DiscreteValue;
    1731import geniusweb.protocol.ProtocolException;
    1832import geniusweb.protocol.session.mopac.PartyStates;
    1933import geniusweb.voting.VotingEvaluator;
     34import geniusweb.voting.votingevaluators.LargestAgreement;
     35import geniusweb.voting.votingevaluators.LargestAgreementsLoop;
     36import tudelft.utilities.junit.GeneralTests;
    2037
    2138/**
    2239 * We also test defaultPhase here.
    2340 */
    24 public class OfferPhaseTest {
    25 
     41public class OfferPhaseTest extends GeneralTests<OfferPhase> {
     42        private final ObjectMapper jackson = new ObjectMapper();
     43
     44        private static final long DEADLINE = 10l;
    2645        private final PartyId party1 = new PartyId("party1");
    2746        private final PartyId party2 = new PartyId("party2");
     
    2948
    3049        private final Map<PartyId, Integer> powers = new HashMap<>();
    31         private final PartyStates states;
    32         private final VotingEvaluator evaluator = mock(VotingEvaluator.class);
    33         private final OfferPhase phase;
     50        private final PartyStates states, states2;
     51        private final VotingEvaluator evaluator = new LargestAgreement();
     52        private final VotingEvaluator evaluator2 = new LargestAgreementsLoop();
     53        private final OfferPhase phase, phase1, phase1a, phase2, phase3, phase4;
     54
     55        // just a test bid
     56        private final Bid bid = new Bid("issue", new DiscreteValue("yes"));
     57        private final Offer offer = new Offer(party1, bid);
     58
     59        private final String serialized = "{\"OfferPhase\":{\"partyStates\":{\"notYetActed\":[\"party2\",\"party1\",\"party3\"],\"actions\":[],\"agreements\":{},\"walkedAway\":[],\"exceptions\":{},\"powers\":{\"party2\":3,\"party1\":2,\"party3\":3}},\"evaluator\":{\"LargestAgreement\":{}},\"deadline\":10}}";
    3460
    3561        public OfferPhaseTest() {
    3662                powers.put(party1, 2);
    3763                powers.put(party2, 3);
     64                states2 = new PartyStates(powers);
    3865                powers.put(party3, 3);
    3966                states = new PartyStates(powers);
    40                 phase = new OfferPhase(null, states, 10l, evaluator);
    41         }
    42 
    43         @Test
    44         public void isInitFinalTest() {
     67                phase = new OfferPhase(states, DEADLINE, evaluator);
     68
     69                phase1 = new OfferPhase(states, 10l, evaluator);
     70                phase1a = new OfferPhase(states, 10l, evaluator);
     71                phase2 = new OfferPhase(states2, 10l, evaluator);
     72                phase3 = new OfferPhase(states, 20l, evaluator);
     73                phase4 = new OfferPhase(states, 10l, evaluator2);
     74
     75        }
     76
     77        @Override
     78        public List<List<OfferPhase>> getGeneralTestData() {
     79                return Arrays.asList(Arrays.asList(phase1, phase1a),
     80                                Arrays.asList(phase2), Arrays.asList(phase3),
     81                                Arrays.asList(phase4));
     82        }
     83
     84        @Override
     85        public List<String> getGeneralTestStrings() {
     86                return Arrays.asList(
     87                                "OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
     88                                "OfferPhase.*PartyStates.*party2, party1.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreement.*",
     89                                "OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],20,LargestAgreement.*",
     90                                "OfferPhase.*PartyStates.*party2, party1, party3.*\\[\\],Agreements.*\\[\\],\\{\\}.*],10,LargestAgreementsLoop.*");
     91        }
     92
     93        @Test
     94        public void smokeTest() {
     95        }
     96
     97        @Test
     98        public void testInitState() {
     99                assertEquals(3, phase.getPartyStates().getNotYetActed().size());
     100        }
     101
     102        @Test
     103        public void testInform() {
     104                assertEquals(new YourTurn(), phase.getInform());
     105        }
     106
     107        @Test
     108        public void isFinalTest() {
    45109                assertFalse(phase.isFinal(1l));
    46110                assertTrue(phase.isFinal(10l));
     111        }
     112
     113        @Test
     114        public void isFinalTestActorNotYetActed() {
     115                PartyStates actedstate = mock(PartyStates.class);
     116                when(actedstate.getNotYetActed())
     117                                .thenReturn(Collections.singleton(party1));
     118                OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
     119                assertFalse(testphase.isFinal(1l));
     120        }
     121
     122        @Test
     123        public void isFinalTestAllActorsActed() {
     124                PartyStates actedstate = mock(PartyStates.class);
     125                when(actedstate.getNotYetActed()).thenReturn(Collections.emptySet());
     126                OfferPhase testphase = new OfferPhase(actedstate, 10l, evaluator);
     127                assertTrue(testphase.isFinal(1l));
    47128        }
    48129
     
    65146        }
    66147
     148        @Test
     149        public void testFinish() {
     150                Phase ph = phase.finish();
     151                assertTrue(ph.getPartyStates().getNotYetActed().isEmpty());
     152                assertEquals(3, ph.getPartyStates().getExceptions().size());
     153                assertTrue(phase.getPartyStates().getAgreements().getMap().isEmpty());
     154        }
     155
     156        @Test(expected = IllegalStateException.class)
     157        public void testNextWrong() {
     158                // state is not final, should not work
     159                phase.next(1, 1000);
     160        }
     161
     162        @Test
     163        public void testNextNoParties() {
     164                Phase ph = phase.finish();
     165                // no parties are left now, all failed
     166                // but this is not part of the next() check.
     167                Phase next = ph.next(1, 1000);
     168                assertTrue(next instanceof VotingPhase);
     169                // no remaining parties, since finish kicked all
     170                assertTrue(next.getPartyStates().getNotYetActed().isEmpty());
     171        }
     172
     173        @Test
     174        public void testAllowed() {
     175                phase.with(party1, offer, 1);
     176        }
     177
     178        @Test
     179        public void testAllowedWrongClass() {
     180                try {
     181                        phase.checkAction(party1, new Accept(party1, bid), 1);
     182                } catch (ProtocolException e) {
     183                        assertTrue(e.getMessage().contains("not allowed in OfferPhase"));
     184                        return;
     185                }
     186                fail("checkAction did not throw as expected");
     187        }
     188
     189        @Test
     190        public void testAllowedWrongActor() {
     191                try {
     192                        phase.checkAction(party1, new Accept(party2, bid), 1);
     193                } catch (ProtocolException e) {
     194                        assertTrue(
     195                                        e.getMessage().contains("Incorrect actor info in action"));
     196                        return;
     197                }
     198                fail("checkAction did not throw as expected");
     199        }
     200
     201        @Test
     202        public void testAllowedActorAlreadyActed() {
     203                OfferPhase testphase = phase.with(party1, offer, 1);
     204
     205                try {
     206                        testphase.checkAction(party1, offer, 2);
     207                } catch (ProtocolException e) {
     208                        assertTrue(e.getMessage().contains("can not act anymore"));
     209                        return;
     210                }
     211                fail("checkAction did not throw as expected");
     212        }
     213
     214        @Test
     215        public void testAllowedActorAlreadyActed1() {
     216                // as theoprevious test, but using with() instead of checkAction
     217                OfferPhase testphase = phase.with(party1, offer, 1);
     218
     219                OfferPhase newphase = testphase.with(party1, offer, 2);
     220                // the party must remain as acted, because we can't retract his
     221                // action...
     222                assertEquals(1, newphase.getPartyStates().getActions().size());
     223                assertEquals(offer, newphase.getPartyStates().getActions().get(0));
     224                assertFalse(
     225                                newphase.getPartyStates().getExceptions().containsKey(party1));
     226        }
     227
     228        @Test
     229        public void testAllowedActingTooLate() {
     230
     231                try {
     232                        phase.checkAction(party1, offer, DEADLINE + 1);
     233                } catch (ProtocolException e) {
     234                        assertTrue(e.getMessage().contains("passed deadline"));
     235                        return;
     236                }
     237                fail("checkAction did not throw as expected");
     238        }
     239
     240        @Test
     241        public void getOffersTest() {
     242                assertEquals(Collections.emptyList(), phase.getOffers());
     243                List<Bid> offs = phase.with(party1, offer, 1).getOffers();
     244                assertEquals(Arrays.asList(bid), offs);
     245        }
     246
     247        @Test(expected = IllegalArgumentException.class)
     248        public void testNextTooShortDuration() {
     249                phase.next(1, Phase.PHASE_MINTIME - 1);
     250        }
     251
     252        @Test(expected = IllegalStateException.class)
     253        public void testNextNotFinished() {
     254                phase.next(1, Phase.PHASE_MINTIME + 1);
     255        }
     256
     257        @Test(expected = IllegalStateException.class)
     258        public void testNext() {
     259                phase.next(11, Phase.PHASE_MINTIME + 1);
     260        }
     261
     262        @Test
     263        public void testDeserialize() throws IOException {
     264                Phase obj = jackson.readValue(serialized, Phase.class);
     265                System.out.println(obj);
     266                assertEquals(phase1, obj);
     267        }
     268
     269        @Test
     270        public void testSerialize()
     271                        throws JsonProcessingException, URISyntaxException {
     272
     273                String string = jackson.writeValueAsString(phase1);
     274                System.out.println(string);
     275                assertEquals(serialized, string);
     276        }
    67277}
  • protocol/src/test/java/geniusweb/protocol/session/saop/SAOPTest.java

    r21 r24  
    3434import geniusweb.events.CurrentState;
    3535import geniusweb.events.ProtocolEvent;
     36import geniusweb.inform.Agreements;
    3637import geniusweb.inform.Finished;
    3738import geniusweb.inform.Inform;
     
    177178                when(state.toString()).thenReturn(asText);
    178179                when(state.with(any(ProtocolException.class))).thenReturn(failstate);
     180                when(state.getAgreements()).thenReturn(mock(Agreements.class));
    179181        }
    180182
     
    260262        @Test
    261263        public void testActionRequestWrongActor() {
    262 
    263264                saop.actionRequest(conn2, mock(EndNegotiation.class));
    264265
     
    290291                when(state.with(any(PartyId.class), any(EndNegotiation.class)))
    291292                                .thenReturn(finalstate);
     293                // when(finalstate.getAgreements()).thenReturn(mock(Agreements.class));
    292294
    293295                saop.actionRequest(conn1, mock(EndNegotiation.class));
     
    311313                doThrow(new IOException("fail sending yourturn")).when(conn1)
    312314                                .send(any(YourTurn.class));
    313 
     315                // CHECK is the state really final after an exception?
     316                when(state.with(any(ProtocolException.class))).thenReturn(finalstate);
     317                // when(state.getAgreements()).thenReturn(mock(Agreements.class));
    314318                saop.actionRequest(conn1, mock(Accept.class));
    315319
     
    322326                doThrow(new IOException("fail sending yourturn")).when(conn1)
    323327                                .send(any(YourTurn.class));
     328                // when(failstate.getAgreements()).thenReturn(mock(Agreements.class));
    324329                // not turn of conn2.
    325330                saop.actionRequest(conn2, mock(EndNegotiation.class));
     
    332337        public void testActionInFinalState() throws IOException {
    333338                saop = new SAOP(finalstate, new ReportToLogger("test"));
     339                // when(finalstate.getAgreements()).thenReturn(mock(Agreements.class));
    334340
    335341                saop.actionRequest(conn1, mock(Offer.class));
Note: See TracChangeset for help on using the changeset viewer.