From 87539db93ddba3debe59cbf950599948d155b977 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Thu, 12 Mar 2015 18:15:33 +0100 Subject: [PATCH] Refactor check offer availability --- .../trade/takeoffer/TakeOfferDataModel.java | 2 +- .../java/io/bitsquare/trade/TradeManager.java | 148 ++++++++---------- .../offer/CheckOfferAvailabilityModel.java | 74 +++++++++ .../offer/CheckOfferAvailabilityProtocol.java | 102 ++++++++++++ .../ReportOfferAvailabilityMessage.java} | 6 +- .../RequestIsOfferAvailableMessage.java | 2 +- .../protocol/offer/tasks/GetPeerAddress.java | 55 +++++++ .../tasks/RequestIsOfferAvailable.java | 27 ++-- .../tasks/IsOfferAvailableResponse.java | 51 ------ .../RequestIsOfferAvailableProtocol.java | 116 -------------- .../trade/taker/SellerAsTakerProtocol.java | 1 - .../trade/taker/tasks/GetPeerAddress.java | 29 +--- .../io/bitsquare/util/tasks/TaskRunner.java | 9 +- 13 files changed, 320 insertions(+), 302 deletions(-) create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityModel.java create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityProtocol.java rename gui/src/main/java/io/bitsquare/trade/protocol/{trade/offerer/messages/IsOfferAvailableResponseMessage.java => offer/messages/ReportOfferAvailabilityMessage.java} (83%) rename gui/src/main/java/io/bitsquare/trade/protocol/{trade/taker => offer}/messages/RequestIsOfferAvailableMessage.java (95%) create mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/GetPeerAddress.java rename gui/src/main/java/io/bitsquare/trade/protocol/{trade/taker => offer}/tasks/RequestIsOfferAvailable.java (59%) delete mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/IsOfferAvailableResponse.java delete mode 100644 gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java diff --git a/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java index 0d410fbe01..e339518664 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java @@ -134,7 +134,7 @@ class TakeOfferDataModel implements Activatable, DataModel { offer.getStateProperty().addListener((observable, oldValue, newValue) -> { offerIsAvailable.set(newValue); }); - tradeManager.onGetOfferAvailableStateRequested(offer); + tradeManager.onCheckOfferAvailability(offer); } void takeOffer() { diff --git a/gui/src/main/java/io/bitsquare/trade/TradeManager.java b/gui/src/main/java/io/bitsquare/trade/TradeManager.java index ec1308cf40..fb17297f41 100644 --- a/gui/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/gui/src/main/java/io/bitsquare/trade/TradeManager.java @@ -30,16 +30,16 @@ import io.bitsquare.offer.OfferBookService; import io.bitsquare.offer.OpenOffer; import io.bitsquare.persistence.Persistence; import io.bitsquare.trade.handlers.TransactionResultHandler; +import io.bitsquare.trade.listeners.SendMessageListener; +import io.bitsquare.trade.protocol.offer.CheckOfferAvailabilityModel; +import io.bitsquare.trade.protocol.offer.CheckOfferAvailabilityProtocol; +import io.bitsquare.trade.protocol.offer.messages.ReportOfferAvailabilityMessage; +import io.bitsquare.trade.protocol.offer.messages.RequestIsOfferAvailableMessage; import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol; -import io.bitsquare.trade.protocol.trade.OfferMessage; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererModel; import io.bitsquare.trade.protocol.trade.offerer.BuyerAsOffererProtocol; -import io.bitsquare.trade.protocol.trade.offerer.messages.IsOfferAvailableResponseMessage; -import io.bitsquare.trade.protocol.trade.offerer.tasks.IsOfferAvailableResponse; -import io.bitsquare.trade.protocol.trade.taker.RequestIsOfferAvailableProtocol; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerProtocol; -import io.bitsquare.trade.protocol.trade.taker.messages.RequestIsOfferAvailableMessage; import io.bitsquare.user.User; import io.bitsquare.util.handlers.ErrorMessageHandler; import io.bitsquare.util.handlers.ResultHandler; @@ -55,8 +55,6 @@ import javax.inject.Inject; import javafx.collections.FXCollections; import javafx.collections.ObservableMap; -import org.jetbrains.annotations.Nullable; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -81,7 +79,7 @@ public class TradeManager { //TODO store TakerAsSellerProtocol in trade private final Map takerAsSellerProtocolMap = new HashMap<>(); private final Map offererAsBuyerProtocolMap = new HashMap<>(); - private final Map requestIsOfferAvailableProtocolMap = new HashMap<>(); + private final Map checkOfferAvailabilityProtocolMap = new HashMap<>(); private final ObservableMap openOffers = FXCollections.observableHashMap(); private final ObservableMap pendingTrades = FXCollections.observableHashMap(); @@ -124,16 +122,7 @@ public class TradeManager { closedTrades.putAll((Map) closedTradesObject); } - tradeMessageService.addMessageHandler(this::handleNewMessage); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Public Methods - /////////////////////////////////////////////////////////////////////////////////////////// - - public void cleanup() { - tradeMessageService.removeMessageHandler(this::handleNewMessage); + tradeMessageService.addMessageHandler(this::handleMessage); } @@ -141,20 +130,23 @@ public class TradeManager { // Called from UI /////////////////////////////////////////////////////////////////////////////////////////// - public void onGetOfferAvailableStateRequested(Offer offer) { - if (!requestIsOfferAvailableProtocolMap.containsKey(offer.getId())) { - RequestIsOfferAvailableProtocol protocol = new RequestIsOfferAvailableProtocol(offer, tradeMessageService); - requestIsOfferAvailableProtocolMap.put(offer.getId(), protocol); - protocol.start(); + public void onCheckOfferAvailability(Offer offer) { + if (!checkOfferAvailabilityProtocolMap.containsKey(offer.getId())) { + + CheckOfferAvailabilityModel model = new CheckOfferAvailabilityModel(offer, tradeMessageService, () -> { + }); + CheckOfferAvailabilityProtocol protocol = new CheckOfferAvailabilityProtocol(model); + checkOfferAvailabilityProtocolMap.put(offer.getId(), protocol); + protocol.onCheckOfferAvailability(); } else { - log.warn("requestIsOfferAvailable already called for offer with ID:" + offer.getId()); + log.error("onGetOfferAvailableStateRequested already called for offer with ID:" + offer.getId()); } } // When closing take offer view, we are not interested in the requestIsOfferAvailable result anymore, so remove from the map public void onGetOfferAvailableStateRequestCanceled(Offer offer) { - requestIsOfferAvailableProtocolMap.remove(offer.getId()); + cleanupCheckOfferAvailabilityProtocolMap(offer); } public void onPlaceOfferRequested(String id, @@ -201,7 +193,6 @@ public class TradeManager { removeOpenOffer(offerId, resultHandler, errorMessageHandler, true); } - public Trade onTakeOfferRequested(Coin amount, Offer offer) { Trade trade = createTrade(offer); trade.setTradeAmount(amount); @@ -263,16 +254,42 @@ public class TradeManager { closeTrade(trade, false); } - /////////////////////////////////////////////////////////////////////////////////////////// - // Called from Offerbook (DHT) - /////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////// + // Called from Offerbook when offer gets removed from DHT + /////////////////////////////////////////////////////////////////////////////////////////// public void onOfferRemovedFromRemoteOfferBook(Offer offer) { - requestIsOfferAvailableProtocolMap.remove(offer.getId()); + cleanupCheckOfferAvailabilityProtocolMap(offer); } + /////////////////////////////////////////////////////////////////////////////////////////// + // Process new tradeMessages + /////////////////////////////////////////////////////////////////////////////////////////// + + // Routes the incoming messages to the responsible protocol + private void handleMessage(Message message, Peer sender) { + if (message instanceof RequestIsOfferAvailableMessage) { + String offerId = ((RequestIsOfferAvailableMessage) message).getOfferId(); + checkNotNull(offerId); + + ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = new ReportOfferAvailabilityMessage(offerId, isOfferOpen(offerId)); + tradeMessageService.sendMessage(sender, reportOfferAvailabilityMessage, new SendMessageListener() { + @Override + public void handleResult() { + log.trace("ReportOfferAvailabilityMessage successfully arrived at peer"); + } + + @Override + public void handleFault() { + log.warn("Sending ReportOfferAvailabilityMessage failed."); + } + }); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////// // Private /////////////////////////////////////////////////////////////////////////////////////////// @@ -291,12 +308,14 @@ public class TradeManager { offerBookService.removeOffer(openOffers.get(offerId).getOffer(), () -> { if (openOffers.containsKey(offerId)) { - openOffers.remove(offerId); + OpenOffer openOffer = openOffers.remove(offerId); + cleanupCheckOfferAvailabilityProtocolMap(openOffer.getOffer()); persistOpenOffers(); if (removeFromOffererAsBuyerProtocolMap && offererAsBuyerProtocolMap.containsKey(offerId)) { offererAsBuyerProtocolMap.get(offerId).cleanup(); offererAsBuyerProtocolMap.remove(offerId); } + resultHandler.handleResult(); } else { @@ -400,7 +419,6 @@ public class TradeManager { offererAsBuyerProtocolMap.remove(trade.getId()); } - if (!failed) { closedTrades.put(trade.getId(), trade); persistClosedTrades(); @@ -410,51 +428,19 @@ public class TradeManager { } } - /////////////////////////////////////////////////////////////////////////////////////////// - // Process new tradeMessages - /////////////////////////////////////////////////////////////////////////////////////////// - - // TODO remove - // Routes the incoming messages to the responsible protocol - private void handleNewMessage(Message message, Peer sender) { - log.trace("handleNewMessage: message = " + message.getClass().getSimpleName()); - log.trace("handleNewMessage: sender = " + sender); - - - if (message instanceof OfferMessage) { - OfferMessage offerMessage = (OfferMessage) message; - // Before starting any take offer activity we check if the offer is still available. - if (offerMessage instanceof RequestIsOfferAvailableMessage) { - // That message arrives at the offerer and he returns if the offer is still available (if there is no trade already created with that offerId). - String offerId = offerMessage.getOfferId(); - checkNotNull(offerId); - boolean isOfferOpen = getTrade(offerId) == null; - // no handling of results or faults needed - IsOfferAvailableResponse.run(sender, tradeMessageService, offerId, isOfferOpen); - } - else if (offerMessage instanceof IsOfferAvailableResponseMessage) { - // That message arrives at the taker in response to a previous requestIsOfferAvailable call. - // It might be that the offer got removed form the offer book, so lets check if its still there. - if (requestIsOfferAvailableProtocolMap.containsKey(offerMessage.getOfferId())) { - RequestIsOfferAvailableProtocol protocol = requestIsOfferAvailableProtocolMap.get(offerMessage.getOfferId()); - protocol.handleIsOfferAvailableResponseMessage((IsOfferAvailableResponseMessage) offerMessage); - requestIsOfferAvailableProtocolMap.remove(offerMessage.getOfferId()); - } - else { - log.info("Offer might have been removed in the meantime. No protocol found for offer with ID:" + offerMessage.getOfferId()); - } - } - else { - log.error("Incoming offerMessage not supported. " + offerMessage); - } + private void cleanupCheckOfferAvailabilityProtocolMap(Offer offer) { + if (checkOfferAvailabilityProtocolMap.containsKey(offer.getId())) { + CheckOfferAvailabilityProtocol protocol = checkOfferAvailabilityProtocolMap.get(offer.getId()); + protocol.cancel(); + protocol.cleanup(); + checkOfferAvailabilityProtocolMap.remove(offer.getId()); } } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Setters - /////////////////////////////////////////////////////////////////////////////////////////// - + public boolean isOfferOpen(String offerId) { + // Don't use openOffers as the offer gets removed async from DHT, but is added sync to pendingTrades + return !pendingTrades.containsKey(offerId) && !closedTrades.containsKey(offerId); + } /////////////////////////////////////////////////////////////////////////////////////////// // Getters @@ -493,16 +479,4 @@ public class TradeManager { persistence.write(this, "closedTrades", (Map) new HashMap<>(closedTrades)); } - - @Nullable - public Trade getTrade(String tradeId) { - if (pendingTrades.containsKey(tradeId)) { - return pendingTrades.get(tradeId); - } - else { - return null; - } - } - - -} +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityModel.java b/gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityModel.java new file mode 100644 index 0000000000..dbc19b79fe --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityModel.java @@ -0,0 +1,74 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.offer; + +import io.bitsquare.network.Peer; +import io.bitsquare.offer.Offer; +import io.bitsquare.trade.TradeMessageService; +import io.bitsquare.trade.protocol.trade.OfferMessage; +import io.bitsquare.util.handlers.ResultHandler; +import io.bitsquare.util.tasks.SharedModel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckOfferAvailabilityModel extends SharedModel { + private static final Logger log = LoggerFactory.getLogger(CheckOfferAvailabilityModel.class); + + private final Offer offer; + private final TradeMessageService tradeMessageService; + private final ResultHandler resultHandler; + + private Peer peer; + private OfferMessage message; + + public CheckOfferAvailabilityModel(Offer offer, TradeMessageService tradeMessageService, ResultHandler resultHandler) { + this.offer = offer; + this.tradeMessageService = tradeMessageService; + this.resultHandler = resultHandler; + } + + // getter/setter + public Offer getOffer() { + return offer; + } + + public TradeMessageService getTradeMessageService() { + return tradeMessageService; + } + + public Peer getPeer() { + return peer; + } + + public void setPeer(Peer peer) { + this.peer = peer; + } + + public void setMessage(OfferMessage message) { + this.message = message; + } + + public OfferMessage getMessage() { + return message; + } + + public ResultHandler getResultHandler() { + return resultHandler; + } +} diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityProtocol.java b/gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityProtocol.java new file mode 100644 index 0000000000..4052a18c85 --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/offer/CheckOfferAvailabilityProtocol.java @@ -0,0 +1,102 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.offer; + +import io.bitsquare.network.Message; +import io.bitsquare.network.Peer; +import io.bitsquare.offer.Offer; +import io.bitsquare.trade.protocol.offer.messages.ReportOfferAvailabilityMessage; +import io.bitsquare.trade.protocol.offer.tasks.GetPeerAddress; +import io.bitsquare.trade.protocol.offer.tasks.RequestIsOfferAvailable; +import io.bitsquare.util.tasks.TaskRunner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static io.bitsquare.util.Validator.nonEmptyStringOf; + +public class CheckOfferAvailabilityProtocol { + private static final Logger log = LoggerFactory.getLogger(CheckOfferAvailabilityProtocol.class); + + private CheckOfferAvailabilityModel model; + private boolean isCanceled; + private TaskRunner sequence; + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + /////////////////////////////////////////////////////////////////////////////////////////// + + public CheckOfferAvailabilityProtocol(CheckOfferAvailabilityModel model) { + this.model = model; + } + + public void cleanup() { + model.getTradeMessageService().removeMessageHandler(this::handleMessage); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // Called from UI + /////////////////////////////////////////////////////////////////////////////////////////// + + public void onCheckOfferAvailability() { + model.getTradeMessageService().addMessageHandler(this::handleMessage); + + sequence = new TaskRunner<>(model, + () -> { + log.debug("sequence at onCheckOfferAvailability completed"); + }, + (message, throwable) -> { + log.error(message); + } + ); + sequence.addTasks( + GetPeerAddress.class, + RequestIsOfferAvailable.class + ); + sequence.run(); + } + + public void cancel() { + isCanceled = true; + sequence.cancel(); + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Incoming message handling + /////////////////////////////////////////////////////////////////////////////////////////// + + private void handleMessage(Message message, Peer sender) { + if (!isCanceled) { + if (message instanceof ReportOfferAvailabilityMessage) { + ReportOfferAvailabilityMessage reportOfferAvailabilityMessage = (ReportOfferAvailabilityMessage) message; + nonEmptyStringOf(reportOfferAvailabilityMessage.getOfferId()); + + if (model.getOffer().getState() != Offer.State.OFFER_REMOVED) { + if (reportOfferAvailabilityMessage.isOfferOpen()) + model.getOffer().setState(Offer.State.OFFER_AVAILABLE); + else + model.getOffer().setState(Offer.State.OFFER_NOT_AVAILABLE); + } + } + } + + model.getResultHandler().handleResult(); + } +} diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/messages/IsOfferAvailableResponseMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/offer/messages/ReportOfferAvailabilityMessage.java similarity index 83% rename from gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/messages/IsOfferAvailableResponseMessage.java rename to gui/src/main/java/io/bitsquare/trade/protocol/offer/messages/ReportOfferAvailabilityMessage.java index 61054dbf00..0160d85797 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/messages/IsOfferAvailableResponseMessage.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/offer/messages/ReportOfferAvailabilityMessage.java @@ -15,18 +15,18 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.protocol.trade.offerer.messages; +package io.bitsquare.trade.protocol.offer.messages; import io.bitsquare.trade.protocol.trade.OfferMessage; import java.io.Serializable; -public class IsOfferAvailableResponseMessage implements Serializable, OfferMessage { +public class ReportOfferAvailabilityMessage implements Serializable, OfferMessage { private static final long serialVersionUID = 6177387534187739018L; private final String offerId; private final boolean isOfferOpen; - public IsOfferAvailableResponseMessage(String offerId, boolean isOfferOpen) { + public ReportOfferAvailabilityMessage(String offerId, boolean isOfferOpen) { this.offerId = offerId; this.isOfferOpen = isOfferOpen; } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/messages/RequestIsOfferAvailableMessage.java b/gui/src/main/java/io/bitsquare/trade/protocol/offer/messages/RequestIsOfferAvailableMessage.java similarity index 95% rename from gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/messages/RequestIsOfferAvailableMessage.java rename to gui/src/main/java/io/bitsquare/trade/protocol/offer/messages/RequestIsOfferAvailableMessage.java index 3d759c2f74..9e174350db 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/messages/RequestIsOfferAvailableMessage.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/offer/messages/RequestIsOfferAvailableMessage.java @@ -15,7 +15,7 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.protocol.trade.taker.messages; +package io.bitsquare.trade.protocol.offer.messages; import io.bitsquare.trade.protocol.trade.OfferMessage; diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/GetPeerAddress.java b/gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/GetPeerAddress.java new file mode 100644 index 0000000000..d81bca781f --- /dev/null +++ b/gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/GetPeerAddress.java @@ -0,0 +1,55 @@ +/* + * This file is part of Bitsquare. + * + * Bitsquare is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bitsquare is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bitsquare. If not, see . + */ + +package io.bitsquare.trade.protocol.offer.tasks; + +import io.bitsquare.network.Peer; +import io.bitsquare.trade.listeners.GetPeerAddressListener; +import io.bitsquare.trade.protocol.offer.CheckOfferAvailabilityModel; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GetPeerAddress extends Task { + private static final Logger log = LoggerFactory.getLogger(GetPeerAddress.class); + + public GetPeerAddress(TaskRunner taskHandler, CheckOfferAvailabilityModel model) { + super(taskHandler, model); + } + + @Override + protected void run() { + model.getTradeMessageService().getPeerAddress(model.getOffer().getMessagePublicKey(), new GetPeerAddressListener() { + @Override + public void onResult(Peer peer) { + log.trace("Found peer: " + peer.toString()); + + model.setPeer(peer); + + complete(); + } + + @Override + public void onFailed() { + failed("DHT lookup for peer address failed."); + } + }); + } +} + diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestIsOfferAvailable.java b/gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/RequestIsOfferAvailable.java similarity index 59% rename from gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestIsOfferAvailable.java rename to gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/RequestIsOfferAvailable.java index 59ce87902b..324c7f1e71 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/RequestIsOfferAvailable.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/offer/tasks/RequestIsOfferAvailable.java @@ -15,36 +15,37 @@ * along with Bitsquare. If not, see . */ -package io.bitsquare.trade.protocol.trade.taker.tasks; +package io.bitsquare.trade.protocol.offer.tasks; -import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.SendMessageListener; -import io.bitsquare.trade.protocol.trade.taker.messages.RequestIsOfferAvailableMessage; -import io.bitsquare.util.handlers.ErrorMessageHandler; +import io.bitsquare.trade.protocol.offer.CheckOfferAvailabilityModel; +import io.bitsquare.trade.protocol.offer.messages.RequestIsOfferAvailableMessage; +import io.bitsquare.util.tasks.Task; +import io.bitsquare.util.tasks.TaskRunner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RequestIsOfferAvailable { +public class RequestIsOfferAvailable extends Task { private static final Logger log = LoggerFactory.getLogger(RequestIsOfferAvailable.class); - public static void run(ErrorMessageHandler errorMessageHandler, - Peer peer, TradeMessageService tradeMessageService, String offerId) { - log.trace("Run RequestIsOfferAvailable task"); + public RequestIsOfferAvailable(TaskRunner taskHandler, CheckOfferAvailabilityModel model) { + super(taskHandler, model); + } - tradeMessageService.sendMessage(peer, new RequestIsOfferAvailableMessage(offerId), + @Override + protected void run() { + model.getTradeMessageService().sendMessage(model.getPeer(), new RequestIsOfferAvailableMessage(model.getOffer().getId()), new SendMessageListener() { @Override public void handleResult() { log.trace("RequestIsOfferAvailableMessage successfully arrived at peer"); - // nothing to do + complete(); } @Override public void handleFault() { - log.error("RequestIsOfferAvailableMessage did not arrive at peer"); - errorMessageHandler.handleErrorMessage("RequestIsOfferAvailableMessage did not arrive at peer"); + failed("Sending RequestIsOfferAvailableMessage failed."); } }); } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/IsOfferAvailableResponse.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/IsOfferAvailableResponse.java deleted file mode 100644 index ee9189503b..0000000000 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/offerer/tasks/IsOfferAvailableResponse.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package io.bitsquare.trade.protocol.trade.offerer.tasks; - -import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; -import io.bitsquare.trade.listeners.SendMessageListener; -import io.bitsquare.trade.protocol.trade.offerer.messages.IsOfferAvailableResponseMessage; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class IsOfferAvailableResponse { - private static final Logger log = LoggerFactory.getLogger(IsOfferAvailableResponse.class); - - public static void run(Peer peer, - TradeMessageService tradeMessageService, - String offerId, - boolean isOfferOpen) { - log.trace("Run RespondToIsOfferAvailable task"); - IsOfferAvailableResponseMessage message = new IsOfferAvailableResponseMessage(offerId, isOfferOpen); - tradeMessageService.sendMessage(peer, message, new SendMessageListener() { - @Override - public void handleResult() { - log.trace("RespondToIsOfferAvailableMessage successfully arrived at peer"); - // Nothing to do. Taker knows now offer available state. - } - - @Override - public void handleFault() { - log.error("RespondToIsOfferAvailableMessage did not arrive at peer"); - // Ignore that. Taker might have gone offline - } - }); - } -} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java deleted file mode 100644 index 68ee43a75b..0000000000 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is part of Bitsquare. - * - * Bitsquare is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bitsquare is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bitsquare. If not, see . - */ - -package io.bitsquare.trade.protocol.trade.taker; - -import io.bitsquare.network.Peer; -import io.bitsquare.offer.Offer; -import io.bitsquare.trade.TradeMessageService; -import io.bitsquare.trade.protocol.trade.offerer.messages.IsOfferAvailableResponseMessage; -import io.bitsquare.trade.protocol.trade.taker.tasks.GetPeerAddress; -import io.bitsquare.trade.protocol.trade.taker.tasks.RequestIsOfferAvailable; - -import java.security.PublicKey; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Responsible for the correct execution of the sequence of tasks, message passing to the peer and message processing - * from the peer. - * That class handles the role of the taker as the Bitcoin seller. - * It uses sub tasks to not pollute the main class too much with all the async result/fault handling. - * Any data from incoming messages as well data used to send to the peer need to be validated before further processing. - */ -public class RequestIsOfferAvailableProtocol { - private static final Logger log = LoggerFactory.getLogger(RequestIsOfferAvailableProtocol.class); - - - // provided data - private final Offer offer; - private final TradeMessageService tradeMessageService; - - // derived - private final String offerId; - private final PublicKey offererMessagePublicKey; - - // written/read by task - private Peer peer; - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Constructor - /////////////////////////////////////////////////////////////////////////////////////////// - - public RequestIsOfferAvailableProtocol(Offer offer, - TradeMessageService tradeMessageService) { - this.offer = offer; - this.tradeMessageService = tradeMessageService; - offerId = offer.getId(); - offererMessagePublicKey = offer.getMessagePublicKey(); - } - - public void start() { - getPeerAddress(); - } - - // 1. GetPeerAddress - // Async - // In case of an error: Don't repeat call for now, maybe in production repeat once. - private void getPeerAddress() { - log.debug("getPeerAddress called"); - GetPeerAddress.run(this::onResultGetPeerAddress, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey); - } - - /* private void onGetPeerAddressFault(String errorMessage) { - GetPeerAddress.run(this::onResultGetPeerAddress, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey); - }*/ - - - // 2. RequestTakeOffer - // Async - // In case of an error: Don't repeat call for now, maybe in production repeat once. - public void onResultGetPeerAddress(Peer peer) { - log.debug("onResultGetPeerAddress called"); - this.peer = peer; - - RequestIsOfferAvailable.run(this::handleErrorMessage, peer, tradeMessageService, offerId); - } - - /* private void onRequestIsOfferAvailableFault(String errorMessage) { - RequestIsOfferAvailable.run(this::handleErrorMessage, peer, tradeMessageService, offerId); - }*/ - - // generic - private void handleErrorMessage(String errorMessage) { - offer.setState(Offer.State.OFFER_NOT_AVAILABLE); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // Incoming message from peer - /////////////////////////////////////////////////////////////////////////////////////////// - - public void handleIsOfferAvailableResponseMessage(IsOfferAvailableResponseMessage offerMessage) { - if (offer.getState() != Offer.State.OFFER_REMOVED) { - if (offerMessage.isOfferOpen()) - offer.setState(Offer.State.OFFER_AVAILABLE); - else - offer.setState(Offer.State.OFFER_NOT_AVAILABLE); - } - } -} diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerAsTakerProtocol.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerAsTakerProtocol.java index 4975deb55c..d603aaa94d 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerAsTakerProtocol.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/SellerAsTakerProtocol.java @@ -47,7 +47,6 @@ import org.slf4j.LoggerFactory; import static io.bitsquare.util.Validator.nonEmptyStringOf; - public class SellerAsTakerProtocol { private static final Logger log = LoggerFactory.getLogger(SellerAsTakerProtocol.class); diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java index 29878ecda9..f1ae72c553 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/tasks/GetPeerAddress.java @@ -18,15 +18,11 @@ package io.bitsquare.trade.protocol.trade.taker.tasks; import io.bitsquare.network.Peer; -import io.bitsquare.trade.TradeMessageService; import io.bitsquare.trade.listeners.GetPeerAddressListener; import io.bitsquare.trade.protocol.trade.taker.SellerAsTakerModel; -import io.bitsquare.util.handlers.ErrorMessageHandler; import io.bitsquare.util.tasks.Task; import io.bitsquare.util.tasks.TaskRunner; -import java.security.PublicKey; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,32 +45,9 @@ public class GetPeerAddress extends Task { @Override public void onFailed() { - failed("DHT lookup for peer address failed.", null); + failed("DHT lookup for peer address failed."); } }); } - - - public static void run(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler, - TradeMessageService tradeMessageService, PublicKey messagePublicKey) { - log.trace("Run GetPeerAddress task"); - tradeMessageService.getPeerAddress(messagePublicKey, new GetPeerAddressListener() { - @Override - public void onResult(Peer peer) { - log.trace("Received peer = " + peer.toString()); - resultHandler.onResult(peer); - } - - @Override - public void onFailed() { - log.error("DHT lookup for peer address failed."); - errorMessageHandler.handleErrorMessage("DHT lookup for peer address failed."); - } - }); - } - - public interface ResultHandler { - void onResult(Peer peer); - } } diff --git a/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java b/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java index 315afb69bf..add2a7b098 100644 --- a/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java +++ b/gui/src/main/java/io/bitsquare/util/tasks/TaskRunner.java @@ -41,6 +41,8 @@ public class TaskRunner { private Class currentTask; private Class previousTask; + private boolean isCanceled; + public TaskRunner(T sharedModel, ResultHandler resultHandler, FaultHandler faultHandler) { this.sharedModel = sharedModel; this.resultHandler = resultHandler; @@ -56,7 +58,7 @@ public class TaskRunner { } protected void next() { - if (!failed) { + if (!failed && !isCanceled) { if (tasks.size() > 0) { try { setCurrentTask(tasks.poll()); @@ -74,6 +76,10 @@ public class TaskRunner { } } + public void cancel() { + isCanceled = true; + } + protected void setPreviousTask(Class task) { previousTask = task; } @@ -103,4 +109,5 @@ public class TaskRunner { failed = true; faultHandler.handleFault(message, throwable); } + }