Android Open Source - spring-sync Diff






From Project

Back to project page spring-sync.

License

The source code is released under:

Apache License

If you think the Android project spring-sync listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2014 the original author or authors.
 *//from   w  w  w  .  j  av  a 2s .  c o  m
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.sync;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import org.springframework.util.ObjectUtils;

import difflib.Delta;
import difflib.Delta.TYPE;
import difflib.DiffUtils;

/**
 * Provides support for producing a {@link Patch} from the comparison of two objects.
 * @author Craig Walls
 */
public class Diff {

  /**
   * Performs a difference operation between two objects, resulting in a {@link Patch} describing the differences.
   * 
   * @param original the original, unmodified object.
   * @param modified the modified object.
   * @return a {@link Patch} describing the differences between the two objects.
   * @throws PatchException if an error occurs while performing the difference.
   */
  public static Patch diff(Object original, Object modified) throws PatchException {
    try {
      List<PatchOperation> operations = new ArrayList<PatchOperation>();
      if (original instanceof List && modified instanceof List) {
        diffList(operations, "", (List<?>) original, (List<?>) modified);
      } else {
        diffNonList(operations, "", original, modified);
      }
      
      return new Patch(operations);
    } catch (Exception e) {
      throw new PatchException("Error performing diff:", e);
    }
  }
  
  // private helpers
  
  private static void diffList(List<PatchOperation> operations, String path, List<?> original, List<?> modified) throws IOException, IllegalAccessException {
  
    difflib.Patch diff = DiffUtils.diff(original, modified);
    List<Delta> deltas = diff.getDeltas();
    for (Delta delta : deltas) {
      TYPE type = delta.getType();
      int revisedPosition = delta.getRevised().getPosition();
      if (type == TYPE.CHANGE) {
        List<?> lines = delta.getRevised().getLines();
        for(int offset = 0; offset < lines.size(); offset++) {
          Object originalObject = original.get(revisedPosition + offset);
          Object revisedObject = modified.get(revisedPosition + offset);
          diffNonList(operations, path + "/" + (revisedPosition + offset), originalObject, revisedObject);          
        }
        
      } else if (type == TYPE.INSERT) {
        List<?> lines = delta.getRevised().getLines();
        for(int offset = 0; offset < lines.size(); offset++) {
          operations.add(new AddOperation(path + "/" + (revisedPosition + offset), lines.get(offset)));
        }
      } else if (type == TYPE.DELETE) {
        List<?> lines = delta.getOriginal().getLines();
        for(int offset = 0; offset < lines.size(); offset++) {
          Object originalObject = original.get(revisedPosition + offset);
          operations.add(new TestOperation(path + "/" + revisedPosition, originalObject));
          operations.add(new RemoveOperation(path + "/" + revisedPosition));
        }
      }
    }
  }
  
  private static void diffNonList(List<PatchOperation> operations, String path, Object original, Object modified) throws IOException, IllegalAccessException {
    if (!ObjectUtils.nullSafeEquals(original, modified)) {
      if (modified == null) {
        operations.add(new RemoveOperation(path));
        return;
      }
      
      if (isPrimitive(modified)) {
        
        operations.add(new TestOperation(path, original));
        if (original == null) {
          operations.add(new AddOperation(path, modified));
        } else {
          operations.add(new ReplaceOperation(path, modified));
        }
        return;
      }
            
      Class<? extends Object> originalType = original.getClass();
      Field[] fields = originalType.getDeclaredFields();
      for (Field field : fields) {
        field.setAccessible(true);
        Class<?> fieldType = field.getType();
        Object origValue = field.get(original);
        Object modValue = field.get(modified);
        if ((fieldType.isArray() || Collection.class.isAssignableFrom(fieldType)) && origValue != null && modValue != null) {
          if (Collection.class.isAssignableFrom(fieldType)) {
            diffList(operations, path + "/" + field.getName(), (List<?>) origValue, (List<?>) modValue);
          }
          else if (fieldType.isArray()) {
            diffList(operations, path + "/" + field.getName(), Arrays.asList((Object[]) origValue), Arrays.asList((Object[]) modValue));
          }
        } else {
          diffNonList(operations, path+"/"+field.getName(), origValue, modValue);
        }
      }
      
    }
  }

  private static boolean isPrimitive(Object o) {
    return o instanceof String || o instanceof Number || o instanceof Boolean;
  }
  
}




Java Source Code List

org.springframework.sync.AddOperationTest.java
org.springframework.sync.AddOperation.java
org.springframework.sync.CopyOperationTest.java
org.springframework.sync.CopyOperation.java
org.springframework.sync.DiffTest.java
org.springframework.sync.Diff.java
org.springframework.sync.FromOperation.java
org.springframework.sync.InverseTest.java
org.springframework.sync.JsonPatchTest.java
org.springframework.sync.LateObjectEvaluator.java
org.springframework.sync.MoveOperationTest.java
org.springframework.sync.MoveOperation.java
org.springframework.sync.PatchException.java
org.springframework.sync.PatchOperation.java
org.springframework.sync.Patch.java
org.springframework.sync.PathToSpEL.java
org.springframework.sync.PathToSpelTest.java
org.springframework.sync.RemoveOperationTest.java
org.springframework.sync.RemoveOperation.java
org.springframework.sync.ReplaceOperationTest.java
org.springframework.sync.ReplaceOperation.java
org.springframework.sync.TestOperationTest.java
org.springframework.sync.TestOperation.java
org.springframework.sync.Todo.java
org.springframework.sync.diffsync.AbstractShadowStore.java
org.springframework.sync.diffsync.DiffSync.java
org.springframework.sync.diffsync.Equivalency.java
org.springframework.sync.diffsync.IdPropertyEquivalency.java
org.springframework.sync.diffsync.PersistenceCallbackRegistry.java
org.springframework.sync.diffsync.PersistenceCallback.java
org.springframework.sync.diffsync.PersistenceStrategy.java
org.springframework.sync.diffsync.ShadowStore.java
org.springframework.sync.diffsync.Shadow.java
org.springframework.sync.diffsync.VersionedPatch.java
org.springframework.sync.diffsync.config.DiffSyncConfigurerAdapter.java
org.springframework.sync.diffsync.config.DiffSyncConfigurer.java
org.springframework.sync.diffsync.config.DifferentialSynchronizationRegistrar.java
org.springframework.sync.diffsync.config.EnableDifferentialSynchronization.java
org.springframework.sync.diffsync.config.package-info.java
org.springframework.sync.diffsync.shadowstore.GemfireShadowStore.java
org.springframework.sync.diffsync.shadowstore.MapBasedShadowStore.java
org.springframework.sync.diffsync.shadowstore.RedisShadowStore.java
org.springframework.sync.diffsync.shadowstore.package-info.java
org.springframework.sync.diffsync.web.DiffSyncController.java
org.springframework.sync.diffsync.web.JsonPatchHttpMessageConverter.java
org.springframework.sync.diffsync.web.package-info.java
org.springframework.sync.diffsync.package-info.java
org.springframework.sync.json.JsonLateObjectEvaluator.java
org.springframework.sync.json.JsonPatchPatchConverter.java
org.springframework.sync.json.PatchConverter.java
org.springframework.sync.json.package-info.java
org.springframework.sync.util.DeepCloneUtils.java
org.springframework.sync.package-info.java