summaryrefslogtreecommitdiffstats
blob: 7b7bb10d0e0b3a3b970fa059ed282f3868af3a87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*  Copyright (c) 2016, Isode Limited, London, England.
 *  All rights reserved.
 *
 *  Acquisition and use of this software and related materials for any
 *  purpose requires a written license agreement from Isode Limited,
 *  or a written license from an organisation licensed by Isode Limited
 *  to grant such a license.
 *
 */
package com.isode.stroke.whiteboard;

import java.util.ArrayList;
import java.util.List;

import com.isode.stroke.elements.WhiteboardDeleteOperation;
import com.isode.stroke.elements.WhiteboardInsertOperation;
import com.isode.stroke.elements.WhiteboardOperation;
import com.isode.stroke.elements.WhiteboardUpdateOperation;
import com.isode.stroke.whiteboard.WhiteboardTransformer.Pair;

public class WhiteboardClient {
    
    private final List<WhiteboardOperation> localOperations_ = new ArrayList<WhiteboardOperation>();
    private final List<WhiteboardOperation> serverOperations_ = new ArrayList<WhiteboardOperation>();
    private final List<WhiteboardOperation> bridge_ = new ArrayList<WhiteboardOperation>();
    private String lastSentOperationID_ = "";

    public static class Result {
        public final WhiteboardOperation client;
        public final WhiteboardOperation server;
        public Result(WhiteboardOperation client,WhiteboardOperation server) {
            this.client = client;
            this.server = server;
        }
    }
    
    public WhiteboardOperation handleLocalOperationReceived(WhiteboardOperation operation) {
        localOperations_.add(operation);
        
        WhiteboardOperation op = null;
        if (operation instanceof WhiteboardInsertOperation) {
            op = new WhiteboardInsertOperation((WhiteboardInsertOperation) operation);
        }
        else if (operation instanceof WhiteboardUpdateOperation) {
            op = new WhiteboardUpdateOperation((WhiteboardUpdateOperation) operation);
        }
        else if (operation instanceof WhiteboardDeleteOperation) {
            op = new WhiteboardDeleteOperation((WhiteboardDeleteOperation) operation);
        }
        
        if (!bridge_.isEmpty()) {
            WhiteboardOperation back = bridge_.get(bridge_.size()-1);
            op.setParentID(back.getID());
        }
        bridge_.add(op);
        
        if (lastSentOperationID_.isEmpty()) {
            if (operation instanceof WhiteboardInsertOperation) {
                op = new WhiteboardInsertOperation((WhiteboardInsertOperation) operation);
            }
            else if (operation instanceof WhiteboardUpdateOperation) {
                op = new WhiteboardUpdateOperation((WhiteboardUpdateOperation) operation);
            }
            else if (operation instanceof WhiteboardDeleteOperation) {
                op = new WhiteboardDeleteOperation((WhiteboardDeleteOperation) operation);
            }
            
            if (!serverOperations_.isEmpty()) {
                WhiteboardOperation back = serverOperations_.get(serverOperations_.size()-1);
                op.setParentID(back.getID());
            }
            lastSentOperationID_ = operation.getID();
            return op;
        }
        else{
            return null;
        }
    }
    
    public Result handleServerOperationReceived(WhiteboardOperation operation) {
        serverOperations_.add(operation);
        WhiteboardOperation clientResult = null, serverResult = null;
        if (localOperations_.size() == (serverOperations_.size()-1) ) {
            localOperations_.add(operation);
            clientResult = operation;
        }
        else if (lastSentOperationID_ == operation.getID()) {
          //Client received confirmation about own operation and it sends next operation to server
          if (!bridge_.isEmpty() && lastSentOperationID_ .equals(bridge_.get(0).getID())) {
              bridge_.remove(0);
          }

          if (!bridge_.isEmpty() && lastSentOperationID_ .equals(bridge_.get(0).getParentID())) {
              lastSentOperationID_ = bridge_.get(0).getID();
              serverResult = bridge_.get(0);
          }
          if (serverResult == null) {
              lastSentOperationID_ = "";
          }            
        }
        else if (!bridge_.isEmpty()) {
            WhiteboardOperation temp;
            Pair opPair = WhiteboardTransformer.transform(bridge_.get(0), operation);
            temp = opPair.first;
            
            bridge_.set(0, opPair.second);
            String previousID = bridge_.get(0).getID();
            for (int i = 1; i < bridge_.size(); ++i) {
                opPair = WhiteboardTransformer.transform(bridge_.get(i), temp);
                temp = opPair.first;
                bridge_.set(i, opPair.second);
                bridge_.get(i).setParentID(previousID);
                previousID = bridge_.get(i).getID();
            }
            
            WhiteboardOperation localBack = localOperations_.get(localOperations_.size()-1);
            temp.setParentID(localBack.getID());
            localOperations_.add(temp);
            clientResult = temp;
        }
        
        return new Result(clientResult, serverResult);
    }
    
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Client\n");
        for (WhiteboardOperation op : localOperations_) {
            builder.append(op.getID());
            builder.append(' ');
            builder.append(op.getPos());
            builder.append('\n');
        }
        builder.append("Server\n");
        for (WhiteboardOperation op : serverOperations_) {
            builder.append(op.getID());
            builder.append(' ');
            builder.append(op.getPos());
            builder.append('\n');
        }
        return builder.toString();
    }
    
    public void print() {
        System.out.println(this);
    }
    
}