From b2e11d7f32db65a6be001dfdf74b74f16f4c9ec3 Mon Sep 17 00:00:00 2001 From: Mateusz Piekos Date: Mon, 16 Jul 2012 14:14:05 +0200 Subject: Extended classes handling synchronization with update operation diff --git a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp index 037eae2..5d4aef1 100644 --- a/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp +++ b/Swiften/Parser/PayloadParsers/WhiteboardParser.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,15 @@ namespace Swift { } catch (boost::bad_lexical_cast&) { } operation = insertOp; + } else if (type == "update") { + WhiteboardUpdateOperation::ref updateOp = boost::make_shared(); + try { + updateOp->setID(attributes.getAttributeValue("id").get_value_or("")); + updateOp->setParentID(attributes.getAttributeValue("parentid").get_value_or("")); + updateOp->setPos(boost::lexical_cast(attributes.getAttributeValue("pos").get_value_or("0"))); + } catch (boost::bad_lexical_cast&) { + } + operation = updateOp; } } else if (level_ == 2) { if (element == "line") { @@ -42,15 +52,21 @@ namespace Swift { int y1 = 0; int x2 = 0; int y2 = 0; + int xShift = 0; + int yShift = 0; try { x1 = boost::lexical_cast(attributes.getAttributeValue("x1").get_value_or("0")); y1 = boost::lexical_cast(attributes.getAttributeValue("y1").get_value_or("0")); x2 = boost::lexical_cast(attributes.getAttributeValue("x2").get_value_or("0")); y2 = boost::lexical_cast(attributes.getAttributeValue("y2").get_value_or("0")); + xShift = boost::lexical_cast(attributes.getAttributeValue("xshift").get_value_or("0")); + yShift = boost::lexical_cast(attributes.getAttributeValue("yshift").get_value_or("0")); } catch (boost::bad_lexical_cast&) { } WhiteboardLineElement::ref whiteboardElement = boost::make_shared(x1, y1, x2, y2); + whiteboardElement->setShift(xShift, yShift); + Color color(attributes.getAttributeValue("stroke").get_value_or("#000000")); color.setAlpha(opacityToAlpha(attributes.getAttributeValue("opacity").get_value_or("1"))); whiteboardElement->setColor(color); @@ -253,6 +269,11 @@ namespace Swift { if (insertOp) { insertOp->setElement(wbElement); } + + WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast(operation); + if (updateOp) { + updateOp->setElement(wbElement); + } getPayloadInternal()->setOperation(operation); } else if (level_ == 2) { if (element == "text") { diff --git a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp index 0cd4779..965939a 100644 --- a/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/WhiteboardSerializer.cpp @@ -10,6 +10,7 @@ #include #include #include +#include namespace Swift { void WhiteboardElementSerializingVisitor::visit(WhiteboardLineElement& line) { @@ -19,6 +20,8 @@ namespace Swift { element->setAttribute("y1", boost::lexical_cast(line.y1())); element->setAttribute("x2", boost::lexical_cast(line.x2())); element->setAttribute("y2", boost::lexical_cast(line.y2())); + element->setAttribute("xshift", boost::lexical_cast(line.getXShift())); + element->setAttribute("yshift", boost::lexical_cast(line.getYShift())); element->setAttribute("id", line.getID()); element->setAttribute("stroke", line.getColor().toHex()); element->setAttribute("stroke-width", boost::lexical_cast(line.getPenWidth())); @@ -151,6 +154,19 @@ namespace Swift { insertOp->getElement()->accept(visitor); operationNode->addNode(visitor.getResult()); } + WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast(payload->getOperation()); + if (updateOp) { + try { + operationNode->setAttribute("type", "update"); + operationNode->setAttribute("pos", boost::lexical_cast(updateOp->getPos())); + operationNode->setAttribute("id", updateOp->getID()); + operationNode->setAttribute("parentid", updateOp->getParentID()); + } catch (boost::bad_lexical_cast&) { + } + updateOp->getElement()->accept(visitor); + operationNode->addNode(visitor.getResult()); + + } element.addNode(operationNode); } element.setAttribute("type", typeToString(payload->getType())); diff --git a/Swiften/Whiteboard/Elements/WhiteboardLineElement.h b/Swiften/Whiteboard/Elements/WhiteboardLineElement.h index 20455b6..85e6302 100644 --- a/Swiften/Whiteboard/Elements/WhiteboardLineElement.h +++ b/Swiften/Whiteboard/Elements/WhiteboardLineElement.h @@ -37,6 +37,19 @@ namespace Swift { return y2_; } + int getXShift() const { + return xShift_; + } + + int getYShift() const { + return yShift_; + } + + void setShift(int x, int y) { + xShift_ = x; + yShift_ = y; + } + const Color& getColor() const { return color_; } @@ -67,6 +80,7 @@ namespace Swift { private: int x1_, y1_, x2_, y2_; + int xShift_, yShift_; Color color_; int penWidth_; std::string id_; diff --git a/Swiften/Whiteboard/IncomingWhiteboardSession.cpp b/Swiften/Whiteboard/IncomingWhiteboardSession.cpp index 60faa2e..42f5934 100644 --- a/Swiften/Whiteboard/IncomingWhiteboardSession.cpp +++ b/Swiften/Whiteboard/IncomingWhiteboardSession.cpp @@ -26,21 +26,21 @@ namespace Swift { void IncomingWhiteboardSession::handleIncomingOperation(WhiteboardOperation::ref operation) { // std::cout << "incoming pos: " << operation->getPos() << std::endl; - WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast(operation); - if (insertOp) { - WhiteboardOperation::ref op = server.handleClientOperationReceived(insertOp); +// WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast(operation); +// if (insertOp) { + WhiteboardOperation::ref op = server.handleClientOperationReceived(operation); //std::cout << "in1: " << operation->getID() << " " << operation->getPos() << " " << operation->getParentID() << std::endl; //std::cout << "in2: " << op->getID() << " " << op->getPos() << " " << op->getParentID() << std::endl; onOperationReceived(op); WhiteboardPayload::ref payload = boost::make_shared(); payload->setOperation(op); sendPayload(payload); - } else { - std::cout << "unknown operation" << std::endl; - } +// } else { +// std::cout << "unknown operation" << std::endl; +// } } - void IncomingWhiteboardSession::handleSendOperationRequest(WhiteboardOperation::ref operation) { + void IncomingWhiteboardSession::sendOperation(WhiteboardOperation::ref operation) { //std::cout << "out: " << operation->getID() << " " << operation->getPos() << " " << operation->getParentID()<< std::endl; server.handleLocalOperationReceived(operation); WhiteboardPayload::ref payload = boost::make_shared(); diff --git a/Swiften/Whiteboard/IncomingWhiteboardSession.h b/Swiften/Whiteboard/IncomingWhiteboardSession.h index 33c1a78..99d3e44 100644 --- a/Swiften/Whiteboard/IncomingWhiteboardSession.h +++ b/Swiften/Whiteboard/IncomingWhiteboardSession.h @@ -24,7 +24,7 @@ namespace Swift { private: void handleIncomingOperation(WhiteboardOperation::ref operation); - void handleSendOperationRequest(WhiteboardOperation::ref operation); + void sendOperation(WhiteboardOperation::ref operation); WhiteboardServer server; }; diff --git a/Swiften/Whiteboard/Operations/WhiteboardUpdateOperation.h b/Swiften/Whiteboard/Operations/WhiteboardUpdateOperation.h new file mode 100644 index 0000000..7c4b088 --- /dev/null +++ b/Swiften/Whiteboard/Operations/WhiteboardUpdateOperation.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012 Mateusz Piękos + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include + +#include + +namespace Swift { + class WhiteboardUpdateOperation : public WhiteboardOperation { + public: + typedef boost::shared_ptr ref; + public: + ~WhiteboardUpdateOperation() { + } + + WhiteboardElement::ref getElement() const { + return element_; + } + + void setElement(WhiteboardElement::ref element) { + element_ = element; + } + + private: + WhiteboardElement::ref element_; + }; +} diff --git a/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp b/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp index da4d3cf..b3722ac 100644 --- a/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp +++ b/Swiften/Whiteboard/OutgoingWhiteboardSession.cpp @@ -51,7 +51,7 @@ namespace Swift { } } - void OutgoingWhiteboardSession::handleSendOperationRequest(WhiteboardOperation::ref operation) { + void OutgoingWhiteboardSession::sendOperation(WhiteboardOperation::ref operation) { //std::cout << "out1: " << operation->getID() << " " << operation->getPos() << " " << operation->getParentID() << std::endl; WhiteboardOperation::ref result = client.handleLocalOperationReceived(operation); diff --git a/Swiften/Whiteboard/OutgoingWhiteboardSession.h b/Swiften/Whiteboard/OutgoingWhiteboardSession.h index fbd0f20..66b2d3f 100644 --- a/Swiften/Whiteboard/OutgoingWhiteboardSession.h +++ b/Swiften/Whiteboard/OutgoingWhiteboardSession.h @@ -25,7 +25,7 @@ namespace Swift { private: void handleRequestResponse(boost::shared_ptr payload, ErrorPayload::ref error); void handleIncomingOperation(WhiteboardOperation::ref operation); - void handleSendOperationRequest(WhiteboardOperation::ref operation); + void sendOperation(WhiteboardOperation::ref operation); WhiteboardClient client; }; diff --git a/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp b/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp index 1b89ae4..996d8a3 100644 --- a/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp +++ b/Swiften/Whiteboard/UnitTest/WhiteboardClientTest.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include using namespace Swift; @@ -22,6 +23,7 @@ class WhiteboardClientTest : public CppUnit::TestFixture { CPPUNIT_TEST(testSynchronize_nonInterrupted); CPPUNIT_TEST(testSynchronize_clientInterruption); CPPUNIT_TEST(testSynchronize_serverInterruption); + CPPUNIT_TEST(testSynchronize_nonInterruptedMixOperations); CPPUNIT_TEST_SUITE_END(); public: @@ -481,6 +483,95 @@ public: } + /*! + * /\ + * / \ + * \ / + * \/ + */ + void testSynchronize_nonInterruptedMixOperations() { + WhiteboardClient client; + WhiteboardInsertOperation::ref serverOp; + serverOp = createInsertOperation("0", "", 0); + WhiteboardClient::Result pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(serverOp, boost::dynamic_pointer_cast(pairResult.client)); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives first local operation, because it's parented off "0" which exists + //in server history and client doesn't wait for any operation ack from server, + //so this operation could be send + WhiteboardInsertOperation::ref clientOp; + clientOp = createInsertOperation("a", "0", 1); + clientOp->setOrigin(WhiteboardOperation::Local); + WhiteboardEllipseElement::ref aElement = boost::make_shared(0,0,0,0); + clientOp->setElement(aElement); + checkOperation(client.handleLocalOperationReceived(clientOp), "a", "0", 1, aElement); + + //Client receives second local operation, client didn't receive ack about previous + //operation from the server so it can't be send. + WhiteboardUpdateOperation::ref clientUpdateOp = createUpdateOperation("b", "a", 0); + WhiteboardEllipseElement::ref bElement = boost::make_shared(0,0,0,0); + clientUpdateOp->setElement(bElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), client.handleLocalOperationReceived(clientUpdateOp)); + + //Client receives new operation from server, it should be transformed against + //"a" and "b" before adding to local operations history because it's parented off "0". + //Because client is waiting for ack of "a", there is no operation to send to server + WhiteboardUpdateOperation::ref serverUpdateOp = createUpdateOperation("c", "0", 0); + WhiteboardEllipseElement::ref cElement = boost::make_shared(0,0,0,0); + serverUpdateOp->setElement(cElement); + pairResult = client.handleServerOperationReceived(serverUpdateOp); + checkOperation(pairResult.client, "c", "b", 0, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives new operation from server, it should be transformed against + //results of previous transformations, returned operation should be parented off + //"c" existing in local history. + //Because client is waiting for ack of "a", there is no operation to send to server + serverOp = createInsertOperation("d", "c", 1); + serverOp->setOrigin(WhiteboardOperation::Other); + WhiteboardEllipseElement::ref dElement = boost::make_shared(0,0,0,0); + serverOp->setElement(dElement); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.client, "d", "c", 2, dElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client receives confirmation about processing "a", it should send next operation + //to server which is "b", but it should be version parented of transformed "a" + serverOp = createInsertOperation("a", "d", 1); + serverOp->setOrigin(WhiteboardOperation::Other); + pairResult = client.handleServerOperationReceived(serverOp); + checkOperation(pairResult.server, "b", "a", 0, cElement); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + + + //Client receives confirmation about processing "b", there aren't any operations + //waiting so it should return nothing. + serverUpdateOp = createUpdateOperation("b", "a", 0); + serverUpdateOp->setOrigin(WhiteboardOperation::Other); + pairResult = client.handleServerOperationReceived(serverOp); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.client); + CPPUNIT_ASSERT_EQUAL(WhiteboardOperation::ref(), pairResult.server); + + //Client operations: + //ID pos + //0 0 + //a 1 + //b 2 + //c 3 + //d 4 + // + //Server operations: + //ID pos + //0 0 + //c 1 + //d 2 + //a 1 + //b 2 + // + //what gives 0abcd on both sides. + } + WhiteboardInsertOperation::ref createInsertOperation(std::string id, std::string parent, int pos) { WhiteboardInsertOperation::ref operation = boost::make_shared(); operation->setParentID(parent); @@ -489,6 +580,14 @@ public: return operation; } + WhiteboardUpdateOperation::ref createUpdateOperation(std::string id, std::string parent, int pos) { + WhiteboardUpdateOperation::ref operation = boost::make_shared(); + operation->setParentID(parent); + operation->setID(id); + operation->setPos(pos); + return operation; + } + void checkOperation(WhiteboardOperation::ref operation, std::string id, std::string parent, int pos = -1, WhiteboardElement::ref element = WhiteboardElement::ref()) { CPPUNIT_ASSERT_EQUAL(id, operation->getID()); CPPUNIT_ASSERT_EQUAL(parent, operation->getParentID()); @@ -497,7 +596,15 @@ public: } if (element) { - CPPUNIT_ASSERT_EQUAL(element, boost::dynamic_pointer_cast(operation)->getElement()); + WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast(operation); + if (insertOp) { + CPPUNIT_ASSERT_EQUAL(element, insertOp->getElement()); + } + + WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast(operation); + if (updateOp) { + CPPUNIT_ASSERT_EQUAL(element, updateOp->getElement()); + } } } }; diff --git a/Swiften/Whiteboard/WhiteboardClient.cpp b/Swiften/Whiteboard/WhiteboardClient.cpp index 9610247..2dd9e45 100644 --- a/Swiften/Whiteboard/WhiteboardClient.cpp +++ b/Swiften/Whiteboard/WhiteboardClient.cpp @@ -12,7 +12,16 @@ namespace Swift { WhiteboardOperation::ref WhiteboardClient::handleLocalOperationReceived(WhiteboardOperation::ref operation) { localOperations_.push_back(operation); // if (bridge_.size() > 0) { - WhiteboardOperation::ref op = boost::make_shared(*boost::dynamic_pointer_cast(operation).get()); + WhiteboardOperation::ref op; + WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast(operation); + if (insertOp) { + op = boost::make_shared(*insertOp.get()); + } + WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast(operation); + if (updateOp) { + op = boost::make_shared(*updateOp.get()); + } + if (bridge_.size() > 0) { op->setParentID(bridge_.back()->getID()); } @@ -20,7 +29,15 @@ namespace Swift { // } if (lastSentOperationID_.empty()) { - WhiteboardOperation::ref op = boost::make_shared(*boost::dynamic_pointer_cast(operation).get()); + WhiteboardInsertOperation::ref insertOp = boost::dynamic_pointer_cast(operation); + if (insertOp) { + op = boost::make_shared(*insertOp.get()); + } + WhiteboardUpdateOperation::ref updateOp = boost::dynamic_pointer_cast(operation); + if (updateOp) { + op = boost::make_shared(*updateOp.get()); + } + if (serverOperations_.size() > 0) { op->setParentID(serverOperations_.back()->getID()); } @@ -62,23 +79,22 @@ namespace Swift { result.server = bridge_.front(); result.server->setOrigin(WhiteboardOperation::Other); } - if (!result.server) { lastSentOperationID_.clear(); } } else { if (bridge_.size() > 0 && bridge_.front()->getParentID() == operation->getParentID()) { std::list::iterator it = bridge_.begin(); - std::pair opPair; - WhiteboardInsertOperation::ref temp; - opPair = WhiteboardTransformer::transform(boost::dynamic_pointer_cast(*it), boost::dynamic_pointer_cast(operation)); + std::pair opPair; + WhiteboardOperation::ref temp; + opPair = WhiteboardTransformer::transform(*it, operation); temp = opPair.first; *it = opPair.second; std::string previousID = (*it)->getID(); ++it; for (; it != bridge_.end(); ++it) { - opPair = WhiteboardTransformer::transform(boost::dynamic_pointer_cast(*it), temp); + opPair = WhiteboardTransformer::transform(*it, temp); temp = opPair.first; *it = opPair.second; (*it)->setParentID(previousID); @@ -90,7 +106,7 @@ namespace Swift { result.client = temp; } else { //doesn't get executed - std::list::reverse_iterator it; +/* std::list::reverse_iterator it; std::pair opPair; WhiteboardInsertOperation::ref temp = boost::dynamic_pointer_cast(operation); bool end = false; @@ -113,8 +129,9 @@ namespace Swift { } if (end) { break; - } - } + }*/ + + } } diff --git a/Swiften/Whiteboard/WhiteboardServer.cpp b/Swiften/Whiteboard/WhiteboardServer.cpp index 36dea87..e84ddb3 100644 --- a/Swiften/Whiteboard/WhiteboardServer.cpp +++ b/Swiften/Whiteboard/WhiteboardServer.cpp @@ -12,7 +12,7 @@ namespace Swift { operations_.push_back(operation); } - WhiteboardOperation::ref WhiteboardServer::handleClientOperationReceived(WhiteboardInsertOperation::ref newOperation) { + WhiteboardOperation::ref WhiteboardServer::handleClientOperationReceived(WhiteboardOperation::ref newOperation) { std::list::reverse_iterator it; if (operations_.size() == 0 || newOperation->getParentID() == operations_.back()->getID()) { operations_.push_back(newOperation); @@ -21,9 +21,9 @@ namespace Swift { for (it = operations_.rbegin(); it != operations_.rend(); ++it) { WhiteboardOperation::ref operation = *it; while (newOperation->getParentID() == operation->getParentID()) { - WhiteboardInsertOperation::ref insertOperation = boost::dynamic_pointer_cast(operation); - if (insertOperation) { - std::pair tResult = WhiteboardTransformer::transform(newOperation, insertOperation); +// WhiteboardInsertOperation::ref insertOperation = boost::dynamic_pointer_cast(operation); +// if (insertOperation) { + std::pair tResult = WhiteboardTransformer::transform(newOperation, operation); if (it == operations_.rbegin()) { operations_.push_back(tResult.second); @@ -33,10 +33,10 @@ namespace Swift { --it; operation = *it; } - } else { - operations_.push_back(operation); - return *it; - } +// } else { +// operations_.push_back(operation); +// return *it; +// } } } return WhiteboardOperation::ref(); diff --git a/Swiften/Whiteboard/WhiteboardServer.h b/Swiften/Whiteboard/WhiteboardServer.h index 11ef64d..6ee4ac6 100644 --- a/Swiften/Whiteboard/WhiteboardServer.h +++ b/Swiften/Whiteboard/WhiteboardServer.h @@ -14,7 +14,7 @@ namespace Swift { class WhiteboardServer { public: void handleLocalOperationReceived(WhiteboardOperation::ref operation); - WhiteboardOperation::ref handleClientOperationReceived(WhiteboardInsertOperation::ref operation); + WhiteboardOperation::ref handleClientOperationReceived(WhiteboardOperation::ref operation); private: std::list operations_; diff --git a/Swiften/Whiteboard/WhiteboardSession.cpp b/Swiften/Whiteboard/WhiteboardSession.cpp index 2828436..492aec5 100644 --- a/Swiften/Whiteboard/WhiteboardSession.cpp +++ b/Swiften/Whiteboard/WhiteboardSession.cpp @@ -44,14 +44,9 @@ namespace Swift { request->send(); } - void WhiteboardSession::sendOperation(const WhiteboardOperation::ref operation) { -/* boost::shared_ptr payload = boost::make_shared(); - // payload->setElement(operation->getElement()); - payload->setOperation(operation); - boost::shared_ptr > request = boost::make_shared >(IQ::Set, toJID_, payload, router_); - request->send();*/ +/* void WhiteboardSession::sendOperation(const WhiteboardOperation::ref operation) { handleSendOperationRequest(operation); - } + }*/ void WhiteboardSession::sendPayload(boost::shared_ptr payload) { boost::shared_ptr > request = boost::make_shared >(IQ::Set, toJID_, payload, router_); diff --git a/Swiften/Whiteboard/WhiteboardSession.h b/Swiften/Whiteboard/WhiteboardSession.h index 7fb03e6..1eb76a4 100644 --- a/Swiften/Whiteboard/WhiteboardSession.h +++ b/Swiften/Whiteboard/WhiteboardSession.h @@ -28,7 +28,7 @@ namespace Swift { virtual ~WhiteboardSession(); void handleIncomingAction(boost::shared_ptr payload); void sendElement(const WhiteboardElement::ref element); - void sendOperation(WhiteboardOperation::ref operation); + virtual void sendOperation(WhiteboardOperation::ref operation) = 0; void cancel(); const JID& getTo() const; virtual std::string getClientID() const = 0; @@ -43,7 +43,7 @@ namespace Swift { private: virtual void handleIncomingOperation(WhiteboardOperation::ref operation) = 0; - virtual void handleSendOperationRequest(WhiteboardOperation::ref operation) = 0; + //virtual void handleSendOperationRequest(WhiteboardOperation::ref operation) = 0; protected: void sendPayload(boost::shared_ptr payload); diff --git a/Swiften/Whiteboard/WhiteboardTransformer.cpp b/Swiften/Whiteboard/WhiteboardTransformer.cpp index 32e9815..32b1183 100644 --- a/Swiften/Whiteboard/WhiteboardTransformer.cpp +++ b/Swiften/Whiteboard/WhiteboardTransformer.cpp @@ -8,7 +8,25 @@ #include namespace Swift { - std::pair WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { + std::pair WhiteboardTransformer::transform(WhiteboardOperation::ref clientOp, WhiteboardOperation::ref serverOp) { + WhiteboardInsertOperation::ref clientInsert = boost::dynamic_pointer_cast(clientOp); + WhiteboardInsertOperation::ref serverInsert = boost::dynamic_pointer_cast(serverOp); + WhiteboardUpdateOperation::ref clientUpdate = boost::dynamic_pointer_cast(clientOp); + WhiteboardUpdateOperation::ref serverUpdate = boost::dynamic_pointer_cast(serverOp); + if (clientInsert && serverInsert) { + return transform(clientInsert, serverInsert); + } else if (clientUpdate && serverUpdate) { + return transform(clientUpdate, serverUpdate); + } else if (clientInsert && serverUpdate) { + return transform(clientInsert, serverUpdate); + } else if (clientUpdate && serverInsert) { + return transform(clientUpdate, serverInsert); + } else { + return std::pair(); + } + } + + std::pair WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { std::pair result; result.first = boost::make_shared(*serverOp.get()); result.first->setParentID(clientOp->getID()); @@ -17,4 +35,44 @@ namespace Swift { result.second->setParentID(serverOp->getID()); return result; } + + std::pair WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { + std::pair result; + result.first = boost::make_shared(*serverOp.get()); + result.first->setParentID(clientOp->getID()); + + if (clientOp->getPos() == serverOp->getPos()) { + result.second = boost::make_shared(*serverOp.get()); + result.second->setID(clientOp->getID()); + result.second->setParentID(serverOp->getID()); + } else { + result.second = boost::make_shared(*clientOp.get()); + result.second->setParentID(serverOp->getID()); + } + return result; + } + + std::pair WhiteboardTransformer::transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp) { + std::pair result; + result.first = boost::make_shared(*serverOp.get()); + result.first->setParentID(clientOp->getID()); + result.second = boost::make_shared(*clientOp.get()); + result.second->setParentID(serverOp->getID()); + if (serverOp->getPos() <= clientOp->getPos()) { + result.second->setPos(result.second->getPos()+1); + } + return result; + } + + std::pair WhiteboardTransformer::transform(WhiteboardInsertOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp) { + std::pair result; + result.first = boost::make_shared(*serverOp.get()); + result.first->setParentID(clientOp->getID()); + result.second = boost::make_shared(*clientOp.get()); + result.second->setParentID(serverOp->getID()); + if (serverOp->getPos() >= clientOp->getPos()) { + result.first->setPos(result.first->getPos()+1); + } + return result; + } } diff --git a/Swiften/Whiteboard/WhiteboardTransformer.h b/Swiften/Whiteboard/WhiteboardTransformer.h index 33086d8..0bab4d3 100644 --- a/Swiften/Whiteboard/WhiteboardTransformer.h +++ b/Swiften/Whiteboard/WhiteboardTransformer.h @@ -7,11 +7,16 @@ #pragma once #include +#include #include namespace Swift { class WhiteboardTransformer { public: - static std::pair transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); +static std::pair transform(WhiteboardOperation::ref clientOp, WhiteboardOperation::ref serverOp); + static std::pair transform(WhiteboardInsertOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); + static std::pair transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); + static std::pair transform(WhiteboardUpdateOperation::ref clientOp, WhiteboardInsertOperation::ref serverOp); + static std::pair transform(WhiteboardInsertOperation::ref clientOp, WhiteboardUpdateOperation::ref serverOp); }; } -- cgit v0.10.2-6-g49f6