2323import java .util .EnumSet ;
2424import java .util .HashMap ;
2525import java .util .Iterator ;
26- import java .util .LinkedList ;
2726import java .util .List ;
2827import java .util .Map ;
2928
30- import org .apache .commons .collections4 .ListUtils ;
3129import org .bson .BsonArray ;
3230import org .bson .BsonDocument ;
3331import org .bson .BsonString ;
3432import org .bson .BsonValue ;
3533
36- import com .google .common .base .Function ;
37- import com .google .common .base .Joiner ;
38- import com .google .common .base .Preconditions ;
39- import com .google .common .collect .Iterables ;
40- import com .google .common .collect .Lists ;
4134
4235public final class BsonDiff {
4336
44- private static final EncodePathFunction ENCODE_PATH_FUNCTION = new EncodePathFunction ();
45-
4637 private BsonDiff () {
4738 }
4839
49- private final static class EncodePathFunction implements Function <Object , String > {
50- @ Override
51- public String apply (Object object ) {
52- String path = object .toString (); // see http://tools.ietf.org/html/rfc6901#section-4
53- return path .replaceAll ("~" , "~0" ).replaceAll ("/" , "~1" );
54- }
55- }
56-
5740 public static BsonArray asBson (final BsonValue source , final BsonValue target ) {
5841 return asBson (source , target , DiffFlags .defaults ());
5942 }
6043
6144 public static BsonArray asBson (final BsonValue source , final BsonValue target , EnumSet <DiffFlags > flags ) {
6245 final List <Diff > diffs = new ArrayList <Diff >();
63- List <Object > path = new LinkedList <Object >();
64- /*
65- * generating diffs in the order of their occurrence
66- */
46+ List <Object > path = new ArrayList <Object >(0 );
47+
48+ // generating diffs in the order of their occurrence
6749 generateDiffs (diffs , path , source , target );
6850
6951 if (!flags .contains (DiffFlags .OMIT_MOVE_OPERATION )) {
70- /*
71- * Merging remove & add to move operation
72- */
52+ // Merging remove & add to move operation
7353 compactDiffs (diffs );
7454 }
7555
7656 if (!flags .contains (DiffFlags .OMIT_COPY_OPERATION )) {
77- /*
78- * Introduce copy operation
79- */
57+ // Introduce copy operation
8058 introduceCopyOperation (source , target , diffs );
8159 }
8260
@@ -91,7 +69,7 @@ private static void introduceCopyOperation(BsonValue source, BsonValue target, L
9169 Map <BsonValue , List <Object >> unchangedValues = getUnchangedPart (source , target );
9270 for (int i = 0 ; i < diffs .size (); i ++) {
9371 Diff diff = diffs .get (i );
94- if (Operation .ADD . equals ( diff .getOperation () )) {
72+ if (Operation .ADD == diff .getOperation ()) {
9573 List <Object > matchingValuePath = getMatchingValuePath (unchangedValues , diff .getValue ());
9674 if (matchingValuePath != null && isAllowed (matchingValuePath , diff .getPath ())) {
9775 diffs .set (i , new Diff (Operation .COPY , matchingValuePath , diff .getPath ()));
@@ -138,7 +116,7 @@ private static boolean isAllowed(List<Object> source, List<Object> destination)
138116
139117 private static Map <BsonValue , List <Object >> getUnchangedPart (BsonValue source , BsonValue target ) {
140118 Map <BsonValue , List <Object >> unchangedValues = new HashMap <BsonValue , List <Object >>();
141- computeUnchangedValues (unchangedValues , Lists . newArrayList (), source , target );
119+ computeUnchangedValues (unchangedValues , new ArrayList < Object > (), source , target );
142120 return unchangedValues ;
143121 }
144122
@@ -158,7 +136,7 @@ private static void computeUnchangedValues(Map<BsonValue, List<Object>> unchange
158136 case ARRAY :
159137 computeArray (unchangedValues , path , source , target );
160138 default :
161- /* nothing */
139+ /* nothing */
162140 }
163141 }
164142 }
@@ -192,8 +170,8 @@ private static void compactDiffs(List<Diff> diffs) {
192170 Diff diff1 = diffs .get (i );
193171
194172 // if not remove OR add, move to next diff
195- if (!(Operation .REMOVE . equals ( diff1 .getOperation () ) ||
196- Operation .ADD . equals ( diff1 .getOperation () ))) {
173+ if (!(Operation .REMOVE == diff1 .getOperation () ||
174+ Operation .ADD == diff1 .getOperation ())) {
197175 continue ;
198176 }
199177
@@ -204,13 +182,13 @@ private static void compactDiffs(List<Diff> diffs) {
204182 }
205183
206184 Diff moveDiff = null ;
207- if (Operation .REMOVE . equals ( diff1 .getOperation () ) &&
208- Operation .ADD . equals ( diff2 .getOperation () )) {
185+ if (Operation .REMOVE == diff1 .getOperation () &&
186+ Operation .ADD == diff2 .getOperation ()) {
209187 computeRelativePath (diff2 .getPath (), i + 1 , j - 1 , diffs );
210188 moveDiff = new Diff (Operation .MOVE , diff1 .getPath (), diff2 .getPath ());
211189
212- } else if (Operation .ADD . equals ( diff1 .getOperation () ) &&
213- Operation .REMOVE . equals ( diff2 .getOperation () )) {
190+ } else if (Operation .ADD == diff1 .getOperation () &&
191+ Operation .REMOVE == diff2 .getOperation ()) {
214192 computeRelativePath (diff2 .getPath (), i , j - 1 , diffs ); // diff1's add should also be considered
215193 moveDiff = new Diff (Operation .MOVE , diff2 .getPath (), diff1 .getPath ());
216194 }
@@ -226,14 +204,14 @@ private static void compactDiffs(List<Diff> diffs) {
226204 //Note : only to be used for arrays
227205 //Finds the longest common Ancestor ending at Array
228206 private static void computeRelativePath (List <Object > path , int startIdx , int endIdx , List <Diff > diffs ) {
229- List <Integer > counters = new ArrayList <Integer >();
207+ List <Integer > counters = new ArrayList <Integer >(path . size () );
230208
231209 resetCounters (counters , path .size ());
232210
233211 for (int i = startIdx ; i <= endIdx ; i ++) {
234212 Diff diff = diffs .get (i );
235213 //Adjust relative path according to #ADD and #Remove
236- if (Operation .ADD . equals ( diff .getOperation ()) || Operation .REMOVE . equals ( diff .getOperation () )) {
214+ if (Operation .ADD == diff .getOperation () || Operation .REMOVE == diff .getOperation ()) {
237215 updatePath (path , diff , counters );
238216 }
239217 }
@@ -277,10 +255,10 @@ private static void updatePath(List<Object> path, Diff pseudo, List<Integer> cou
277255 }
278256
279257 private static void updateCounters (Diff pseudo , int idx , List <Integer > counters ) {
280- if (Operation .ADD . equals ( pseudo .getOperation () )) {
258+ if (Operation .ADD == pseudo .getOperation ()) {
281259 counters .set (idx , counters .get (idx ) - 1 );
282260 } else {
283- if (Operation .REMOVE . equals ( pseudo .getOperation () )) {
261+ if (Operation .REMOVE == pseudo .getOperation ()) {
284262 counters .set (idx , counters .get (idx ) + 1 );
285263 }
286264 }
@@ -302,20 +280,22 @@ private static BsonDocument getBsonNode(Diff diff, EnumSet<DiffFlags> flags) {
302280 switch (diff .getOperation ()) {
303281 case MOVE :
304282 case COPY :
305- bsonNode .put (Constants .FROM , new BsonString (getArrayNodeRepresentation (diff .getPath ()))); // required {from} only in case of Move Operation
306- bsonNode .put (Constants .PATH , new BsonString (getArrayNodeRepresentation (diff .getToPath ()))); // destination Path
283+ bsonNode .put (Constants .FROM , new BsonString (PathUtils . getPathRepresentation (diff .getPath ()))); // required {from} only in case of Move Operation
284+ bsonNode .put (Constants .PATH , new BsonString (PathUtils . getPathRepresentation (diff .getToPath ()))); // destination Path
307285 break ;
308286
309287 case REMOVE :
310- bsonNode .put (Constants .PATH , new BsonString (getArrayNodeRepresentation (diff .getPath ())));
288+ bsonNode .put (Constants .PATH , new BsonString (PathUtils . getPathRepresentation (diff .getPath ())));
311289 if (!flags .contains (DiffFlags .OMIT_VALUE_ON_REMOVE ))
312290 bsonNode .put (Constants .VALUE , diff .getValue ());
313291 break ;
314-
315- case ADD :
316292 case REPLACE :
293+ if (flags .contains (DiffFlags .ADD_ORIGINAL_VALUE_ON_REPLACE )) {
294+ bsonNode .put (Constants .FROM_VALUE , diff .getSrcValue ());
295+ }
296+ case ADD :
317297 case TEST :
318- bsonNode .put (Constants .PATH , new BsonString (getArrayNodeRepresentation (diff .getPath ())));
298+ bsonNode .put (Constants .PATH , new BsonString (PathUtils . getPathRepresentation (diff .getPath ())));
319299 bsonNode .put (Constants .VALUE , diff .getValue ());
320300 break ;
321301
@@ -327,12 +307,6 @@ private static BsonDocument getBsonNode(Diff diff, EnumSet<DiffFlags> flags) {
327307 return bsonNode ;
328308 }
329309
330- private static String getArrayNodeRepresentation (List <Object > path ) {
331- return Joiner .on ('/' ).appendTo (new StringBuilder ().append ('/' ),
332- Iterables .transform (path , ENCODE_PATH_FUNCTION )).toString ();
333- }
334-
335-
336310 private static void generateDiffs (List <Diff > diffs , List <Object > path , BsonValue source , BsonValue target ) {
337311 if (!source .equals (target )) {
338312 if (source .isArray () && target .isArray ()) {
@@ -344,7 +318,7 @@ private static void generateDiffs(List<Diff> diffs, List<Object> path, BsonValue
344318 } else {
345319 //can be replaced
346320
347- diffs .add (Diff .generateDiff (Operation .REPLACE , path , target ));
321+ diffs .add (Diff .generateDiff (Operation .REPLACE , path , source , target ));
348322 }
349323 }
350324 }
@@ -452,17 +426,13 @@ private static void compareDocuments(List<Diff> diffs, List<Object> path, BsonVa
452426 }
453427
454428 private static List <Object > getPath (List <Object > path , Object key ) {
455- List <Object > toReturn = new ArrayList <Object >();
429+ List <Object > toReturn = new ArrayList <Object >(path . size () + 1 );
456430 toReturn .addAll (path );
457431 toReturn .add (key );
458432 return toReturn ;
459433 }
460434
461435 private static List <BsonValue > getLCS (final BsonValue first , final BsonValue second ) {
462-
463- Preconditions .checkArgument (first .isArray (), "LCS can only work on BSON arrays" );
464- Preconditions .checkArgument (second .isArray (), "LCS can only work on BSON arrays" );
465-
466- return ListUtils .longestCommonSubsequence (Lists .newArrayList (first .asArray ()), Lists .newArrayList (second .asArray ()));
436+ return InternalUtils .longestCommonSubsequence (InternalUtils .toList (first .asArray ()), InternalUtils .toList (second .asArray ()));
467437 }
468438}
0 commit comments