4A Server -  2.0
 All Classes Namespaces Files Functions Variables Enumerator
LastTextModifications.java
Go to the documentation of this file.
1 /*
2  * Project: Server for annotations sharing
3  * Author: Bc. Lukáš Kubík
4  * File: LastTextModifications.java
5  * Description: Class representing last 3 applied modification sets on a document
6  */
7 
8 /**
9  * @file LastTextModifications.java
10  *
11  * @brief Class representing last 3 applied modification sets on a document
12  */
13 
14 package cz.vutbr.fit.knot.annotations.app;
15 
16 import java.util.ArrayList;
17 import java.util.Iterator;
18 
19 /**
20  * Class representing last 3 applied modification sets on a document
21  *
22  * @brief Class representing last applied modifications on a document
23  * @author xkubik22
24  */
25 public class LastTextModifications {
26 
27  /**
28  * ID of the affected document
29  */
30  private Integer documentID = null;
31 
32  /**
33  * List of applied modification set ID's
34  */
35  private ArrayList<Integer> modificationsID = new ArrayList<Integer>();
36 
37  /**
38  * List of applied modification sets
39  */
40  private ArrayList<ArrayList<TextModification>> appliedModifications = new ArrayList<ArrayList<TextModification>>();
41 
42  /**
43  * Empty constructor
44  */
46 
47  }
48 
49  /**
50  * Constructor for first applied modifications
51  *
52  * @param documentID id of the changed document
53  * @param firstModificationID first modification set ID
54  * @param firstModifications first modification set
55  */
56  public LastTextModifications(int documentID, int firstModificationID, ArrayList<TextModification> firstModifications){
57  this.documentID = documentID;
58  this.modificationsID.add(firstModificationID);
59  this.appliedModifications.add(firstModifications);
60  }
61 
62  /**
63  * Adds next applied modification
64  * If are there already three modifications then it deletes the oldest one.
65  *
66  * @param modificationID modification set ID
67  * @param modifications modification set
68  */
69  public synchronized void addNextModificationSet(int modificationID, ArrayList<TextModification> modifications){
70  this.appliedModifications.add(modifications);
71  this.modificationsID.add(modificationID);
72  if(appliedModifications.size() > 3){
73  this.appliedModifications.remove(0);
74  this.modificationsID.remove(0);
75  }
76  }
77 
78  /**
79  * Checks whetever last modification sets contains passed ID
80  *
81  * @param modificationID modification set ID
82  */
83  public synchronized boolean containsSet(int modificationID){
84  return this.modificationsID.contains(modificationID);
85  }
86 
87 
88  /**
89  * Checks whetever the modification sets applied after modification
90  * identified by the passed setID contains conflicts with passed modification set.
91  *
92  * @param setID ID of the set preceding the checked sets
93  * @param modifications Checked modification set
94  * @return true if are there conflicts otherwise false
95  */
96  public synchronized boolean hasModificationSetsConflicts(int setID,
97  ArrayList<TextModification> modifications)
98  {
99  if(modifications.isEmpty()){
100  return false;
101  }
102  int modIndex = this.modificationsID.indexOf(setID);
103  if(modIndex > -1){
104  ++modIndex;
105  for(int i = modIndex; i < this.modificationsID.size(); i++){
106  if(compareTwoSetsForConflicts(modifications, this.appliedModifications.get(i))){
107  return true;
108  }
109  }
110  }
111  return false;
112  }
113 
114  /**
115  * Compares two modification sets for conflicts
116  * firstModSet should be applied before secondModSet.
117  * Checks for compatibility.
118  *
119  * @param firstModSet First modification set
120  * @param secondModSet Second modification set
121  * @return true if is there some conflict otherwise false
122  */
123  private synchronized boolean compareTwoSetsForConflicts(ArrayList<TextModification> firstModSet,
124  ArrayList<TextModification> secondModSet)
125  {
126  Iterator<TextModification> firstIT = firstModSet.iterator();
127  while(firstIT.hasNext()){
128  TextModification firstMod = firstIT.next();
129  Iterator<TextModification> secondIT = secondModSet.iterator();
130  while(secondIT.hasNext()){
131  TextModification secondMod = secondIT.next();
132  if(compareTwoModsForConflicts(firstMod, secondMod)){
133  return true;
134  }
135  }
136  }
137  return false;
138  }
139 
140  /**
141  * Compares two modifications for conflicts
142  * firstMod should be applied before secondMod.
143  * Checks for compatibility.
144  *
145  * @param firstMod First modification
146  * @param secondMod Second modification
147  * @return true if is there some conflict otherwise false
148  */
149  private synchronized boolean compareTwoModsForConflicts(TextModification firstMod,
150  TextModification secondMod)
151  {
152  /** Replace options:
153  * Replacement of whole node (0 - n xpath change)
154  Delete whole node (1 xpath change)
155  Insertion to node (only change of the content of the node)
156  Replacement of part of node (only change of the content of the node)
157  */
158  int pathComp = (firstMod.getPath() + "z").compareTo(secondMod.getPath() + "z");
159  switch(firstMod.getMode()){
160  case Constants.TEXT_MOD_REPLACE:
161  switch(secondMod.getMode()){
162  case Constants.TEXT_MOD_REPLACE://done
163  // same node
164  if(pathComp == 0){
165  return true;
166  }
167  // first node is before second node xpath
168  else if(pathComp < 0){
169  //delete or replace first == conflict
170  //otherwise false
171  if(firstMod.getOffset() == null && firstMod.getLength() == null){
172  return true;
173  }
174  }
175  break;
176  case Constants.TEXT_MOD_INS_BEFORE://done
177  // first is before second
178  if(pathComp < 0){
179  //delete or replace first == conflict
180  //otherwise false
181  if(firstMod.getOffset() == null && firstMod.getLength() == null){
182  return true;
183  }
184  }
185  //first = delete the same node
186  else if(pathComp == 0 && firstMod.getOffset() == null &&
187  firstMod.getLength() == null && firstMod.getNewContent() == null)
188  {
189  return true;
190  }
191  break;
192  case Constants.TEXT_MOD_INS_AFTER:
193  // first is before second or the same node
194  if(pathComp <= 0){
195  //delete or replace first == conflict
196  //otherwise false
197  if(firstMod.getOffset() == null && firstMod.getLength() == null){
198  return true;
199  }
200  }
201  break;
202  }
203  break;
204  case Constants.TEXT_MOD_INS_BEFORE:
205  // first is before second or the same node
206  if(pathComp <= 0){
207  return true;
208  }
209  break;
210  case Constants.TEXT_MOD_INS_AFTER:
211  switch(secondMod.getMode()){
212  case Constants.TEXT_MOD_REPLACE:
213  case Constants.TEXT_MOD_INS_BEFORE:
214  // first is before second
215  if(pathComp < 0){
216  return true;
217  }
218  break;
219  case Constants.TEXT_MOD_INS_AFTER:
220  // first is before second or the same node
221  if(pathComp <= 0){
222  return true;
223  }
224  break;
225  }
226  break;
227  }
228  return false;
229  }
230 
231 } // public class LastTextModifications
synchronized void addNextModificationSet(int modificationID, ArrayList< TextModification > modifications)
synchronized boolean compareTwoModsForConflicts(TextModification firstMod, TextModification secondMod)
LastTextModifications(int documentID, int firstModificationID, ArrayList< TextModification > firstModifications)
ArrayList< ArrayList< TextModification > > appliedModifications
Class representing modification of annotated document text.
synchronized boolean containsSet(int modificationID)
Class representing last applied modifications on a document.
synchronized boolean hasModificationSetsConflicts(int setID, ArrayList< TextModification > modifications)
synchronized boolean compareTwoSetsForConflicts(ArrayList< TextModification > firstModSet, ArrayList< TextModification > secondModSet)