Skip to content

Commit

Permalink
Merge pull request #14 from doubledutch/feat-deep-equals
Browse files Browse the repository at this point in the history
Feat deep equals
  • Loading branch information
kasperjj authored Feb 17, 2017
2 parents e25cbe7 + 20c42a6 commit 4157a5e
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 3 deletions.
30 changes: 30 additions & 0 deletions src/main/java/me/doubledutch/lazyjson/LazyArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,36 @@ public LazyType getType(){
return LazyType.ARRAY;
}

public int hashCode(){
int code=2;
for(int i=0;i<length();i++){
LazyType t1=getType(i);
switch(t1){
case STRING:code+=getString(i).hashCode();
break;
case INTEGER:
long l=getLong(i);
code+=(int)(l ^ (l >>> 32));
break;
case FLOAT:
double d=getDouble(i);
l=Double.doubleToLongBits(d);
code+=(int)(l ^ (l >>> 32));
break;
case BOOLEAN:
if(getBoolean(i)){
code+=1;
}
break;
case OBJECT:code+=37*getJSONObject(i).hashCode();
break;
case ARRAY:code+=37*getJSONArray(i).hashCode();
break;
}
}
return code;
}

/**
* Returns the value type of the given field.
*
Expand Down
65 changes: 65 additions & 0 deletions src/main/java/me/doubledutch/lazyjson/LazyElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,69 @@ public byte[] toByteArray(){
root.writeToBuffer(buf);
return buf.array();
}

public abstract int hashCode();

private boolean equalObjects(LazyObject o1,LazyObject o2){
if(o1.length()!=o2.length())return false;
for(String key:o1.keySet()){
if(!o2.has(key))return false;
LazyType t1=o1.getType(key);
if(t1!=o2.getType(key))return false;
switch(t1){
// NULL, implicitly true
case STRING:if(!o1.getString(key).equals(o2.getString(key)))return false;
break;
case INTEGER:if(o1.getLong(key)!=o2.getLong(key))return false;
break;
case FLOAT:if(o1.getDouble(key)!=o2.getDouble(key))return false;
break;
case BOOLEAN:if(o1.getBoolean(key)!=o2.getBoolean(key))return false;
break;
case OBJECT:if(!o1.getJSONObject(key).equals(o2.getJSONObject(key)))return false;
break;
case ARRAY:if(!o1.getJSONArray(key).equals(o2.getJSONArray(key)))return false;
break;
}
}
return true;
}

private boolean equalArrays(LazyArray a1,LazyArray a2){
if(a1.length()!=a2.length())return false;
for(int i=0;i<length();i++){
LazyType t1=a1.getType(i);
if(t1!=a2.getType(i))return false;
switch(t1){
// NULL, implicitly true
case STRING:if(!a1.getString(i).equals(a2.getString(i)))return false;
break;
case INTEGER:if(a1.getLong(i)!=a2.getLong(i))return false;
break;
case FLOAT:if(a1.getDouble(i)!=a2.getDouble(i))return false;
break;
case BOOLEAN:if(a1.getBoolean(i)!=a2.getBoolean(i))return false;
break;
case OBJECT:if(!a1.getJSONObject(i).equals(a2.getJSONObject(i)))return false;
break;
case ARRAY:if(!a1.getJSONArray(i).equals(a2.getJSONArray(i)))return false;
break;
}
}
return true;
}

public boolean equals(Object obj){
// Verify both are LazyElement
if(!(obj instanceof LazyElement))return false;
LazyElement el=(LazyElement)obj;
// Verify both are same type
if(el.getType()!=getType())return false;
// Do a deep comparison
if(getType()==LazyType.OBJECT){
return equalObjects((LazyObject)this,(LazyObject)el);
}else{
return equalArrays((LazyArray)this,(LazyArray)el);
}
}
}
31 changes: 31 additions & 0 deletions src/main/java/me/doubledutch/lazyjson/LazyObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,37 @@ public Set<String> keySet(){
return set;
}

public int hashCode(){
int code=1;
for(String key:keySet()){
LazyType t1=getType(key);
switch(t1){
case STRING:code+=getString(key).hashCode();
break;
case INTEGER:
long l=getLong(key);
code+=(int)(l ^ (l >>> 32));
break;
case FLOAT:
double d=getDouble(key);
l=Double.doubleToLongBits(d);
code+=(int)(l ^ (l >>> 32));
break;
case BOOLEAN:
if(getBoolean(key)){
code+=1;
}
break;
case OBJECT:code+=37*getJSONObject(key).hashCode();
break;
case ARRAY:code+=37*getJSONArray(key).hashCode();
break;
}
}
return code;
}


/**
* Utility method to evaluate wether a given string matches the value
* of a field.
Expand Down
6 changes: 3 additions & 3 deletions src/main/resources/lazyjson_version.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Wed Feb 15 11:35:37 PST 2017
#Thu Feb 16 16:00:59 PST 2017
BUILD_VERSION=1.2.7
BUILD_DATE=2017-02-15T19\:35\:37Z
BUILD_NUMBER=677
BUILD_DATE=2017-02-17T00\:00\:59Z
BUILD_NUMBER=707
108 changes: 108 additions & 0 deletions src/test/java/me/doubledutch/lazyjson/DeepEqualsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package me.doubledutch.lazyjson;


import java.io.File;
import org.junit.*;
import static org.junit.Assert.*;
import java.util.List;
import java.util.ArrayList;
import java.net.*;

public class DeepEqualsTest{
@Test
public void testObjectKeyOrderEquality() throws LazyException{
LazyObject o1=new LazyObject("{\"foo\":13,\"bar\":42}");
LazyObject o2=new LazyObject("{\"bar\":42,\"foo\":13}");
LazyObject o3=new LazyObject("{\"bar\":41,\"foo\":13}");
assertTrue(o1.equals(o2));
assertFalse(o1.equals(o3));

assertEquals(o1.hashCode(),o2.hashCode());
assertNotEquals(o1.hashCode(),o3.hashCode());
}
@Test
public void testObjectValueTypesEquality() throws LazyException{
LazyObject o1=new LazyObject("{\"int\":13,\"float\":3.1415,\"string\":\"Hello World\",\"bool\":false,\"null\":null}");
LazyObject o2=new LazyObject("{\"int\":13,\"float\":3.1415,\"string\":\"Hello World\",\"bool\":false,\"null\":null}");
LazyObject o3=new LazyObject("{\"int\":14,\"float\":3.1415,\"string\":\"Hello World\",\"bool\":false,\"null\":null}");
LazyObject o4=new LazyObject("{\"int\":13,\"float\":3.1415,\"string\":\"Hello World!\",\"bool\":false,\"null\":null}");
LazyObject o5=new LazyObject("{\"int\":13,\"float\":3.1415,\"string\":\"Hello World\",\"bool\":true,\"null\":null}");
LazyObject o6=new LazyObject("{\"int\":13,\"float\":3.1416,\"string\":\"Hello World\",\"bool\":false,\"null\":null}");
LazyObject o7=new LazyObject("{\"int\":13,\"float\":3.1415,\"string\":\"Hello World\",\"bool\":false,\"null\":false}");

assertTrue(o1.equals(o2));
assertFalse(o1.equals(o3));
assertFalse(o1.equals(o4));
assertFalse(o1.equals(o5));
assertFalse(o1.equals(o6));
assertFalse(o1.equals(o7));

assertEquals(o1.hashCode(),o2.hashCode());
assertNotEquals(o1.hashCode(),o3.hashCode());
assertNotEquals(o1.hashCode(),o4.hashCode());
assertNotEquals(o1.hashCode(),o5.hashCode());
assertNotEquals(o1.hashCode(),o6.hashCode());
// TODO: false and null is the same value in the hashcode - should we change this?
// assertNotEquals(o1.hashCode(),o7.hashCode());
}

@Test
public void testNestedObjectEquality() throws LazyException{
LazyObject o1=new LazyObject("{\"foo\":13,\"bar\":{\"baz\":42}}");
LazyObject o2=new LazyObject("{\"bar\":{\"baz\":42},\"foo\":13}");
LazyObject o3=new LazyObject("{\"bar\":{\"baz\":99},\"foo\":13}");
assertTrue(o1.equals(o2));
assertFalse(o1.equals(o3));

assertEquals(o1.hashCode(),o2.hashCode());
assertNotEquals(o1.hashCode(),o3.hashCode());
}

@Test
public void testArrayValueTypesEquality() throws LazyException{
LazyArray o1=new LazyArray("[13,3.1415,\"Hello World\",false,null]");
LazyArray o2=new LazyArray("[13,3.1415,\"Hello World\",false,null]");
LazyArray o3=new LazyArray("[14,3.1415,\"Hello World\",false,null]");
LazyArray o4=new LazyArray("[13,3.1416,\"Hello World\",false,null]");
LazyArray o5=new LazyArray("[13,3.1415,\"Hello World!\",false,null]");
LazyArray o6=new LazyArray("[13,3.1415,\"Hello World\",true,null]");
LazyArray o7=new LazyArray("[13,3.1415,\"Hello World\",false,false]");

assertTrue(o1.equals(o2));
assertFalse(o1.equals(o3));
assertFalse(o1.equals(o4));
assertFalse(o1.equals(o5));
assertFalse(o1.equals(o6));
assertFalse(o1.equals(o7));

assertEquals(o1.hashCode(),o2.hashCode());
assertNotEquals(o1.hashCode(),o3.hashCode());
assertNotEquals(o1.hashCode(),o4.hashCode());
assertNotEquals(o1.hashCode(),o5.hashCode());
assertNotEquals(o1.hashCode(),o6.hashCode());
}

@Test
public void testArrayInObjectEquality() throws LazyException{
LazyObject o1=new LazyObject("{\"foo\":13,\"bar\":[\"baz\",42]}");
LazyObject o2=new LazyObject("{\"bar\":[\"baz\",42],\"foo\":13}");
LazyObject o3=new LazyObject("{\"bar\":[\"baz\",99],\"foo\":13}");
assertTrue(o1.equals(o2));
assertFalse(o1.equals(o3));

assertEquals(o1.hashCode(),o2.hashCode());
assertNotEquals(o1.hashCode(),o3.hashCode());
}

@Test
public void testObjectInArrayEquality() throws LazyException{
LazyArray o1=new LazyArray("[{\"foo\":13,\"bar\":[\"baz\",42]},3]");
LazyArray o2=new LazyArray("[{\"bar\":[\"baz\",42],\"foo\":13},3]");
LazyArray o3=new LazyArray("[{\"bar\":[\"baz\",99],\"foo\":13},3]");
assertTrue(o1.equals(o2));
assertFalse(o1.equals(o3));

assertEquals(o1.hashCode(),o2.hashCode());
assertNotEquals(o1.hashCode(),o3.hashCode());
}
}

0 comments on commit 4157a5e

Please sign in to comment.