package com.shagaba.jacksync;

import java.util.Iterator;
import java.util.Map;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

public class MergeOperation extends PatchOperation {

    private JsonNode value;
    
    /**
	 * 
	 */
	public MergeOperation() {
		super();
	}

	/**
	 * @param value
	 */
	public MergeOperation(JsonNode value) {
		super();
		this.value = value;
	}

	/**
	 * @return the value
	 */
	public JsonNode getValue() {
		return value;
	}

	/**
	 * @param value the value to set
	 */
	public void setValue(JsonNode value) {
		this.value = value;
	}

	@Override
	public JsonNode apply(JsonNode objectJsonNode) {
		merge(objectJsonNode, value);
        return objectJsonNode;
      }
	
	/**
	 * 
	 * @param sourceJsonNode
	 * @param elementJsonNode
	 */
	private void merge(JsonNode sourceJsonNode, JsonNode elementJsonNode) {
 		for (Iterator<Map.Entry<String, JsonNode>> iterator = elementJsonNode.fields() ; iterator.hasNext();) {
     		Map.Entry<String, JsonNode> elementMapEntry = iterator.next();
 			if (sourceJsonNode.isArray()) {
 				sourceJsonNode = elementJsonNode;
 			} else {
 				ObjectNode sourceObjectNode = (ObjectNode) sourceJsonNode;
	     		JsonNode nextValueJsonNode = elementMapEntry.getValue();
	     		JsonNode nextSourceJsonNode = sourceJsonNode.get(elementMapEntry.getKey());

	     		if (sourceObjectNode.has(elementMapEntry.getKey())) {
	     			if (!nextValueJsonNode.isMissingNode() && !nextSourceJsonNode.isObject()) {
	     				sourceObjectNode.replace(elementMapEntry.getKey(), elementMapEntry.getValue());
		     			continue;
	     			} 
	     		} else {
	     			sourceObjectNode.replace(elementMapEntry.getKey(), elementMapEntry.getValue());
	     			continue;
	     		}
	 			merge(nextSourceJsonNode, nextValueJsonNode);
			}
		}
	}

}

@@ -75,24 +75,72 @@
 til.Map;%0D%0A%0D%0A
+import com.fasterxml.jackson.core.JsonPointer;%0D%0A
 import com.f
@@ -275,16 +275,20 @@
 ds Patch
+Path
 Operatio
@@ -338,24 +338,54 @@
    /**%0D%0A%09 * 
+Constructs the merge operation
 %0D%0A%09 */%0D%0A%09pub
@@ -436,28 +436,160 @@
 **%0D%0A%09 * 
-@param value
+Constructs the merge operation%0D%0A%09 * %0D%0A%09 * @param path the path where the value will be added. ('/foo/bar/4')%0D%0A%09 * @param value the value to add.
 %0D%0A%09 */%0D%0A
@@ -611,16 +611,34 @@
 eration(
+JsonPointer path, 
 JsonNode
@@ -652,24 +652,290 @@
  %7B%0D%0A%09%09super(
+path);%0D%0A%09%09this.value = value;%0D%0A%09%7D%0D%0A%0D%0A%09/**%0D%0A%09 * Constructs the merge operation%0D%0A%09 * %0D%0A%09 * @param path the path where the value will be added. ('/foo/bar/4')%0D%0A%09 * @param value the value to add.%0D%0A%09 */%0D%0A%09public MergeOperation(String path, JsonNode value) %7B%0D%0A%09%09super(path
 );%0D%0A%09%09this.v

add JsonPointer path with merge operation