package edu.brown.utils; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.util.*; import java.util.Map.Entry; import org.apache.commons.collections15.set.ListOrderedSet; import org.json.*; import org.voltdb.catalog.Database; import edu.brown.BaseTestCase; public class TestJSONUtilComplex extends BaseTestCase { private static final int NUM_ELEMENTS = 5; public static class TestObject implements JSONSerializable { public enum Members { LIST_SET, LIST_MAP, LIST_LIST, SET_SET, SET_MAP, SET_LIST, MAP_SET, MAP_MAP, MAP_LIST, } public static final Set<Members> LISTS = new ListOrderedSet<Members>(); public static final Set<Members> SETS = new ListOrderedSet<Members>(); public static final Set<Members> MAPS = new ListOrderedSet<Members>(); static { for (Members e : Members.values()) { String name = e.name(); if (name.startsWith("LIST")) { LISTS.add(e); } else if (name.startsWith("SET")) { SETS.add(e); } else if (name.startsWith("MAP")) { MAPS.add(e); } else { assert(false) : "Unexpected Member '" + e + "'"; } } // FOR assert(!LISTS.isEmpty()) : "No list members selected"; assert(!SETS.isEmpty()) : "No set members selected"; assert(!MAPS.isEmpty()) : "No map members selected"; } // -------------------------------------------------------------------------------- // Data Members // -------------------------------------------------------------------------------- // Lists public List<Set<Integer>> list_set = new ArrayList<Set<Integer>>(); public List<Map<Integer, Integer>> list_map = new ArrayList<Map<Integer, Integer>>(); public List<List<Integer>> list_list = new ArrayList<List<Integer>>(); // Sets public Set<Set<Integer>> set_set = new ListOrderedSet<Set<Integer>>(); public Set<Map<Integer, Integer>> set_map = new ListOrderedSet<Map<Integer, Integer>>(); public Set<List<Integer>> set_list = new ListOrderedSet<List<Integer>>(); // Maps public Map<Integer, Set<Integer>> map_set = new HashMap<Integer, Set<Integer>>(); public Map<Integer, Map<Integer, Integer>> map_map = new HashMap<Integer, Map<Integer, Integer>>(); public Map<Integer, List<Integer>> map_list = new HashMap<Integer, List<Integer>>(); // -------------------------------------------------------------------------------- // JSONSerializable Methods // -------------------------------------------------------------------------------- @Override public void load(File input_path, Database catalog_db) throws IOException { JSONUtil.load(this, catalog_db, input_path); } @Override public void save(File output_path) throws IOException { JSONUtil.save(this, output_path); } @Override public void fromJSON(JSONObject json_object, Database catalog_db) throws JSONException { this.fromJSON(json_object, catalog_db, Arrays.asList(Members.values())); } @Override public void toJSON(JSONStringer stringer) throws JSONException { this.toJSON(stringer, Arrays.asList(Members.values())); } @Override public String toJSONString() { return (this.toJSONString(Arrays.asList(Members.values()))); } public void fromJSON(JSONObject json_object, Database catalog_db, Collection<Members> members) throws JSONException { Members members_arr[] = new Members[members.size()]; members.toArray(members_arr); JSONUtil.fieldsFromJSON(json_object, catalog_db, this, TestObject.class, members_arr); } public void toJSON(JSONStringer stringer, Collection<Members> members) throws JSONException { Members members_arr[] = new Members[members.size()]; members.toArray(members_arr); JSONUtil.fieldsToJSON(stringer, this, TestObject.class, members_arr); } public String toJSONString(Collection<Members> members) { JSONStringer stringer = new JSONStringer(); try { stringer.object(); this.toJSON(stringer, members); stringer.endObject(); } catch (JSONException e) { e.printStackTrace(); System.exit(-1); } return (stringer.toString()); } } private final Random rand = new Random(); private TestObject obj; @Override protected void setUp() throws Exception { this.obj = new TestObject(); for (int i = 0; i < NUM_ELEMENTS; i++) { this.obj.list_list.add(new ArrayList<Integer>()); this.obj.list_set.add(new HashSet<Integer>()); this.obj.list_map.add(new HashMap<Integer, Integer>()); this.obj.set_list.add(new ArrayList<Integer>()); this.obj.set_set.add(new HashSet<Integer>()); this.obj.set_map.add(new HashMap<Integer, Integer>()); this.obj.map_list.put(i, new ArrayList<Integer>()); this.obj.map_set.put(i, new HashSet<Integer>()); this.obj.map_map.put(i, new HashMap<Integer, Integer>()); for (int ii = 0, cnt = rand.nextInt(NUM_ELEMENTS) + 1; ii < cnt; ii++) { CollectionUtil.last(this.obj.list_list).add(rand.nextInt()); CollectionUtil.last(this.obj.list_set).add(rand.nextInt()); CollectionUtil.last(this.obj.list_map).put(rand.nextInt(), rand.nextInt()); CollectionUtil.last(this.obj.set_list).add(rand.nextInt()); CollectionUtil.last(this.obj.set_set).add(rand.nextInt()); CollectionUtil.last(this.obj.set_map).put(rand.nextInt(), rand.nextInt()); this.obj.map_list.get(i).add(rand.nextInt()); this.obj.map_set.get(i).add(rand.nextInt()); this.obj.map_map.get(i).put(rand.nextInt(), rand.nextInt()); } // FOR } // FOR } private JSONObject toJSONObject(TestObject orig, Collection<TestObject.Members> members) throws Exception { String json_string = orig.toJSONString(members); assert(json_string.length() > 0); JSONObject json_object = new JSONObject(json_string); assertNotNull(json_object); // if (members.size() == 2) System.err.println(json_object.toString(1)); assertEquals(members.size(), json_object.length()); return (json_object); } private TestObject clone(TestObject orig, Collection<TestObject.Members> members) throws Exception { assert(!members.isEmpty()); JSONObject json_object = new JSONObject(orig.toJSONString()); // System.err.println(json_object.toString(1)); TestObject clone = new TestObject(); clone.fromJSON(json_object, catalog_db, members); return (clone); } private void compareInnerObjects(TestObject.Members e, Object o0, Object o1) throws Exception { // MAP if (e.name().endsWith("MAP")) { Map<?,?> inner0 = (Map<?,?>)o0; Map<?,?> inner1 = (Map<?,?>)o1; assertEquals(inner0.keySet(), inner1.keySet()); for (Object inner_key : inner0.keySet()) { Object value0 = inner0.get(inner_key); Object value1 = inner1.get(inner_key); assertEquals(value0, value1); } // FOR // LIST + SET } else { Collection<?> inner0 = (Collection<?>)o0; Collection<?> inner1 = (Collection<?>)o1; assertEquals(inner0.size(), inner1.size()); assert(inner0.containsAll(inner1)); assert(inner1.containsAll(inner0)); } } // -------------------------------------------------------------------------------- // Test Cases // -------------------------------------------------------------------------------- /** * testListFieldsToJSON */ public void testListFieldsToJSON() throws Exception { JSONObject json_object = this.toJSONObject(obj, TestObject.LISTS); for (TestObject.Members e : TestObject.LISTS) { String json_key = e.name(); assert(json_object.has(json_key)); Field field = TestObject.class.getField(json_key.toLowerCase()); assertNotNull(field); Collection<?> collection = (Collection<?>)field.get(obj); List<String> collection_strings = new ArrayList<String>(); for (Object outer : collection) { if (outer instanceof Map) { Map<?,?> m = (Map<?,?>)outer; for (Object temp : m.entrySet()) { Entry<?, ?> entry = (Entry<?, ?>)temp; collection_strings.add(entry.getKey().toString()); collection_strings.add(entry.getValue().toString()); } // FOR } else { for (Object o : (Collection<?>)outer) { collection_strings.add(o.toString()); } // FOR } } // FOR JSONArray json_array = json_object.getJSONArray(json_key); assertEquals(collection.size(), json_array.length()); for (int i = 0, cnt = json_array.length(); i < cnt; i++) { // MAP if (e.name().endsWith("MAP")) { JSONObject inner_object = json_array.getJSONObject(i); for (String key : JSONObject.getNames(inner_object)) { assert(collection_strings.contains(key)) : "Missing key '" + key + "' from field " + e + ": " + collection_strings; String value = inner_object.getString(key); assertNotNull(value); assertFalse(value.isEmpty()); assert(collection_strings.contains(key)) : "Missing value '" + value + "' for key '" + key + "' in field " + e + ": " + collection_strings; } // FOR // SET + LIST } else { JSONArray inner_array = json_array.getJSONArray(i); for (int ii = 0, cnt2 = inner_array.length(); ii < cnt2; ii++) { String value = inner_array.getString(ii); assertNotNull(value); assertFalse(value.isEmpty()); assert(collection_strings.contains(value)) : "Missing element '" + value + "' from field " + e + ": " + collection_strings; } // FOR } } // FOR } // FOR } /** * testListFieldsFromJSON */ public void testListFieldsFromJSON() throws Exception { TestObject clone = this.clone(obj, TestObject.LISTS); for (TestObject.Members e : TestObject.LISTS) { String json_key = e.name(); Field field = TestObject.class.getField(json_key.toLowerCase()); assertNotNull(field); List<?> collection0 = (List<?>)field.get(obj); List<?> collection1 = (List<?>)field.get(clone); assertEquals(collection0.size(), collection1.size()); for (int i = 0, cnt = collection0.size(); i < cnt; i++) { compareInnerObjects(e, collection0.get(i), collection1.get(i)); } // FOR } // FOR } /** * testSetFieldsToJSON */ public void testSetFieldsToJSON() throws Exception { JSONObject json_object = this.toJSONObject(obj, TestObject.SETS); for (TestObject.Members e : TestObject.SETS) { String json_key = e.name(); assert(json_object.has(json_key)); Field field = TestObject.class.getField(json_key.toLowerCase()); assertNotNull(field); Collection<?> collection = (Collection<?>)field.get(obj); List<String> collection_strings = new ArrayList<String>(); for (Object outer : collection) { if (outer instanceof Map) { Map<?,?> m = (Map<?,?>)outer; for (Object temp : m.entrySet()) { Entry<?, ?> entry = (Entry<?, ?>)temp; collection_strings.add(entry.getKey().toString()); collection_strings.add(entry.getValue().toString()); } // FOR } else { for (Object o : (Collection<?>)outer) { collection_strings.add(o.toString()); } // FOR } } // FOR JSONArray json_array = json_object.getJSONArray(json_key); assertEquals(collection.size(), json_array.length()); for (int i = 0, cnt = json_array.length(); i < cnt; i++) { // MAP if (e.name().endsWith("MAP")) { JSONObject inner_object = json_array.getJSONObject(i); for (String key : JSONObject.getNames(inner_object)) { assert(collection_strings.contains(key)) : "Missing key '" + key + "' from field " + e + ": " + collection_strings; String value = inner_object.getString(key); assertNotNull(value); assertFalse(value.isEmpty()); assert(collection_strings.contains(key)) : "Missing value '" + value + "' for key '" + key + "' in field " + e + ": " + collection_strings; } // FOR // SET + LIST } else { JSONArray inner_array = json_array.getJSONArray(i); for (int ii = 0, cnt2 = inner_array.length(); ii < cnt2; ii++) { String value = inner_array.getString(ii); assertNotNull(value); assertFalse(value.isEmpty()); assert(collection_strings.contains(value)) : "Missing element '" + value + "' from field " + e + ": " + collection_strings; } // FOR } } // FOR } // FOR } /** * testSetFieldsFromJSON */ public void testSetFieldsFromJSON() throws Exception { TestObject clone = this.clone(obj, TestObject.SETS); for (TestObject.Members e : TestObject.SETS) { String json_key = e.name(); Field field = TestObject.class.getField(json_key.toLowerCase()); assertNotNull(field); Set<?> collection0 = (Set<?>)field.get(obj); Set<?> collection1 = (Set<?>)field.get(clone); assertEquals(collection0.size(), collection1.size()); for (int i = 0, cnt = collection0.size(); i < cnt; i++) { compareInnerObjects(e, CollectionUtil.get(collection0, i), CollectionUtil.get(collection1, i)); } // FOR } // FOR } /** * testMapFieldsToJSON */ public void testMapFieldsToJSON() throws Exception { JSONObject json_object = this.toJSONObject(obj, TestObject.MAPS); for (TestObject.Members e : TestObject.MAPS) { String json_key = e.name(); assert(json_object.has(json_key)); Field field = TestObject.class.getField(json_key.toLowerCase()); assertNotNull(field); Map<?,?> map = (Map<?,?>)field.get(obj); List<String> key_strings = new ArrayList<String>(); List<String> val_strings = new ArrayList<String>(); for (Object key : map.keySet()) { key_strings.add(key.toString()); Object val = map.get(key); if (val instanceof Map) { Map<?,?> m = (Map<?,?>)val; for (Object temp : m.entrySet()) { Entry<?, ?> entry = (Entry<?, ?>)temp; key_strings.add(entry.getKey().toString()); val_strings.add(entry.getValue().toString()); } // FOR } else { for (Object o : (Collection<?>)val) { val_strings.add(o.toString()); } // FOR } } // FOR JSONObject json_inner_obj = json_object.getJSONObject(json_key); for (String json_inner_key : JSONObject.getNames(json_inner_obj)) { assert(!json_inner_key.isEmpty()); if (e.name().endsWith("MAP")) { JSONObject json_map_obj = json_inner_obj.getJSONObject(json_inner_key); for (String key : JSONObject.getNames(json_map_obj)) { assert(key_strings.contains(key)) : "Missing key '" + key + "' from field " + e + ": " + key_strings; String value = json_map_obj.getString(key); assertNotNull(value); assertFalse(value.isEmpty()); assert(val_strings.contains(value)) : "Missing value '" + value + "' for key '" + key + "' in field " + e + ": " + val_strings; } // FOR } else { JSONArray inner_array = json_inner_obj.getJSONArray(json_inner_key); for (int ii = 0, cnt2 = inner_array.length(); ii < cnt2; ii++) { String value = inner_array.getString(ii); assertNotNull(value); assertFalse(value.isEmpty()); assert(val_strings.contains(value)) : "Missing element '" + value + "' from field " + e + ": " + val_strings; } // FOR } } // WHILE } // FOR } /** * testMapFieldsFromJSON */ public void testMapFieldsFromJSON() throws Exception { TestObject clone = this.clone(obj, TestObject.MAPS); for (TestObject.Members e : TestObject.MAPS) { String json_key = e.name(); Field field = TestObject.class.getField(json_key.toLowerCase()); assertNotNull(field); Map<?,?> map0 = (Map<?,?>)field.get(obj); assertNotNull(map0); Map<?,?> map1 = (Map<?,?>)field.get(clone); assertNotNull(map1); assertEquals(map0.size(), map1.size()); assertEquals(map0.keySet(), map1.keySet()); for (Object key : map0.keySet()) { compareInnerObjects(e, map0.get(key), map1.get(key)); } // FOR } // FOR } }