-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
src/main/java/com/sangupta/jerry/settings/ConflictResolution.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package com.sangupta.jerry.settings; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
public @interface ConflictResolution { | ||
|
||
public ConflictResolutionPolicy policy(); | ||
|
||
} |
27 changes: 27 additions & 0 deletions
27
src/main/java/com/sangupta/jerry/settings/ConflictResolutionPolicy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.sangupta.jerry.settings; | ||
|
||
public enum ConflictResolutionPolicy { | ||
|
||
BLIND_COPY, // for everything | ||
|
||
MIN, // for numbers | ||
|
||
MAX, // for numbers | ||
|
||
GREATER_THAN, // for comparable | ||
|
||
LESS_THAN, // for comparable | ||
|
||
NON_ZERO, // for numbers | ||
|
||
NON_NULL, // for objects | ||
|
||
NON_NEGATIVE, // for numbers | ||
|
||
NON_EMPTY, // for strings | ||
|
||
UNION, // for collection | ||
|
||
INTERSECTION // for collection | ||
|
||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/sangupta/jerry/settings/MergeComparable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.sangupta.jerry.settings; | ||
|
||
public interface MergeComparable { | ||
|
||
public int compareForMerge(MergeComparable other); | ||
|
||
} |
94 changes: 94 additions & 0 deletions
94
src/main/java/com/sangupta/jerry/settings/ObjectMerge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package com.sangupta.jerry.settings; | ||
|
||
import java.lang.reflect.Field; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
|
||
import com.sangupta.jerry.util.AssertUtils; | ||
import com.sangupta.jerry.util.ReflectionUtils; | ||
|
||
public class ObjectMerge { | ||
|
||
public static <T> T merge(Class<T> classOfT, T instance, List<T> settings) throws InstantiationException, IllegalAccessException { | ||
if(AssertUtils.isEmpty(settings)) { | ||
return instance; | ||
} | ||
|
||
// check if we can sort this list or not | ||
if(MergeComparable.class.isAssignableFrom(classOfT)) { | ||
// sort settings list | ||
settings.sort(new Comparator<T>() { | ||
|
||
@Override | ||
public int compare(T o1, T o2) { | ||
MergeComparable p1 = (MergeComparable) o1; | ||
MergeComparable p2 = (MergeComparable) o2; | ||
return p1.compareForMerge(p2); | ||
} | ||
|
||
}); | ||
} | ||
|
||
// now start copying fields | ||
List<Field> fields = ReflectionUtils.getAllFields(classOfT); | ||
for(Field field : fields) { | ||
// for each field, find the value in each object | ||
for(T setting : settings) { | ||
copyFieldIfApplicable(field, instance, setting); | ||
} | ||
} | ||
|
||
|
||
return instance; | ||
} | ||
|
||
private static <T> void copyFieldIfApplicable(Field field, T destination, T source) throws IllegalArgumentException, IllegalAccessException { | ||
Class<?> type = field.getType(); | ||
|
||
// set accessible so that we can work with private fields | ||
field.setAccessible(true); | ||
|
||
// obtain current source value | ||
Object srcValue = field.get(source); | ||
|
||
ConflictResolution resolution = field.getAnnotation(ConflictResolution.class); | ||
ConflictResolutionPolicy policy = resolution.policy(); | ||
|
||
switch (policy) { | ||
case BLIND_COPY: | ||
field.set(destination, srcValue); | ||
return; | ||
|
||
case INTERSECTION: | ||
break; | ||
|
||
case MAX: | ||
break; | ||
|
||
case MIN: | ||
break; | ||
|
||
case NON_ZERO: | ||
if(ReflectionUtils.isFieldNumber(type)) { | ||
if(ReflectionUtils.isEqualNumber(srcValue, 0)) { | ||
|
||
} | ||
} | ||
break; | ||
|
||
case NON_NULL: | ||
if(srcValue != null) { | ||
field.set(destination, srcValue); | ||
} | ||
return; | ||
|
||
case UNION: | ||
break; | ||
|
||
default: | ||
throw new RuntimeException("Unknown conflict resolution policy"); | ||
|
||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
src/test/java/com/sangupta/jerry/settings/TestObjectMerge.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package com.sangupta.jerry.settings; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import org.junit.Assert; | ||
import org.junit.Test; | ||
|
||
public class TestObjectMerge { | ||
|
||
@Test | ||
public void test() throws InstantiationException, IllegalAccessException { | ||
TestSettingsObject highest = new TestSettingsObject(100); | ||
highest.x1 = 100; | ||
highest.x2 = 100; | ||
highest.x3 = 100; | ||
highest.x4 = 100; | ||
highest.x5 = 100; | ||
highest.x6 = 100; | ||
highest.x7 = true; | ||
|
||
TestSettingsObject medium = new TestSettingsObject(50); | ||
medium.x1 = 50; | ||
medium.x2 = 50; | ||
medium.x3 = 50; | ||
medium.x4 = 50; | ||
medium.x5 = 50; | ||
medium.x6 = 50; | ||
medium.x7 = false; | ||
|
||
TestSettingsObject lowest = new TestSettingsObject(10); | ||
lowest.x1 = 500; | ||
lowest.x2 = 500; | ||
lowest.x3 = 500; | ||
lowest.x4 = 5; | ||
lowest.x5 = 500; | ||
lowest.x6 = 500; | ||
lowest.x7 = false; | ||
|
||
// where everything is copied | ||
TestSettingsObject destination = new TestSettingsObject(0); | ||
|
||
List<TestSettingsObject> list = new ArrayList<>(); | ||
list.add(lowest); | ||
list.add(highest); | ||
list.add(medium); | ||
|
||
ObjectMerge.merge(TestSettingsObject.class, destination, list); | ||
|
||
Assert.assertEquals(100, destination.x1); | ||
Assert.assertEquals(100, destination.x2); | ||
Assert.assertEquals(100, destination.x3); | ||
Assert.assertEquals(100, destination.x4); | ||
Assert.assertEquals(100, destination.x5, 0.01f); | ||
Assert.assertEquals(100, destination.x6, 0.01d); | ||
Assert.assertTrue(destination.x7); | ||
|
||
} | ||
|
||
private static class TestSettingsObject implements MergeComparable { | ||
|
||
final int weight; | ||
|
||
TestSettingsObject(int weight) { | ||
this.weight = weight; | ||
} | ||
|
||
@ConflictResolution(policy = ConflictResolutionPolicy.MIN) | ||
int x1; | ||
|
||
@ConflictResolution(policy = ConflictResolutionPolicy.MAX) | ||
long x2; | ||
|
||
@ConflictResolution(policy = ConflictResolutionPolicy.BLIND_COPY) | ||
char x3; | ||
|
||
@ConflictResolution(policy = ConflictResolutionPolicy.NON_ZERO) | ||
byte x4; | ||
|
||
float x5; | ||
|
||
double x6; | ||
|
||
boolean x7; | ||
|
||
@Override | ||
public int compareForMerge(MergeComparable other) { | ||
if (!(other instanceof TestSettingsObject)) { | ||
throw new RuntimeException("Invalid object to compare"); | ||
} | ||
|
||
TestSettingsObject tso = (TestSettingsObject) other; | ||
return Integer.compare(this.weight, tso.weight); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Priority: " + this.weight; | ||
} | ||
|
||
} | ||
} |