/*
* Copyright (c) 2014 Oculus Info Inc. http://www.oculusinfo.com/
*
* Released under the MIT License.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.oculusinfo.binning.metadata;
import com.oculusinfo.binning.metadata.updaters.MetaDataF0p0T1p0;
import com.oculusinfo.factory.util.Pair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class MetaDataMutationTests {
private static final double EPSILON = 1E-12;
@Test
public void testVersionMutationPath () {
PyramidMetaDataVersionMutator.ALL_MUTATORS.clear();
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v0", "v1"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v1", "v2"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v2", "v2a"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v2", "v2b"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v2", "v2c"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v2a", "v3a"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v2b", "v3a"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v2c", "v3b"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v3a", "v4"));
PyramidMetaDataVersionMutator.ALL_MUTATORS.add(new PyramidMetaDataVersionMutator("v4", "v5"));
// Register the real 0.0 -> 1.0 mutator for testing
MetaDataF0p0T1p0.register();
List<PyramidMetaDataVersionMutator> path = PyramidMetaDataVersionMutator.getMutators("v2", "v5");
Assert.assertEquals(4, path.size());
Assert.assertTrue(new Pair<String, String>("v2", "v2a").equals(path.get(0).getVersionBounds()) ||
new Pair<String, String>("v2", "v2b").equals(path.get(0).getVersionBounds()));
Assert.assertTrue(new Pair<String, String>("v2a", "v3a").equals(path.get(1).getVersionBounds()) ||
new Pair<String, String>("v2b", "v3a").equals(path.get(1).getVersionBounds()));
Assert.assertEquals(new Pair<String, String>("v3a", "v4"), path.get(2).getVersionBounds());
Assert.assertEquals(new Pair<String, String>("v4", "v5"), path.get(3).getVersionBounds());
Assert.assertNull(PyramidMetaDataVersionMutator.getMutators("v2c", "v5"));
}
@Test
public void testV0_0ToV1_0Update () throws JSONException {
String initialText = ("{"+
" \"name\":\"bitcoin.time.amount\","+
" \"description\":\"Binned bitcoin.time.amount data showing time vs. amount\","+
" \"tilesize\":256,"+
" \"scheme\":\"TMS\","+
" \"projection\":\"EPSG:4326\","+
" \"minzoom\":0,"+
" \"maxzoom\":18,"+
" \"bounds\": [ 1231002905000.0, 0.0, 1365618170007.8, 500000.0 ],"+
" \"meta\": {"+
" \"levelMinimums\": {"+
" \"0\": \"0.0\","+
" \"1\": \"0.0\","+
" \"2\": \"0.0\","+
" \"3\": \"0.0\","+
" \"4\": \"0.0\","+
" \"5\": \"0.0\","+
" \"6\": \"0.0\","+
" \"7\": \"0.0\","+
" \"8\": \"0.0\","+
" \"9\": \"0.0\","+
" \"10\": \"0.0\","+
" \"11\": \"0.0\","+
" \"12\": \"0.0\""+
" },"+
" \"levelMaximums\": {"+
" \"0\": \"1016406.0\","+
" \"1\": \"556010.0\","+
" \"2\": \"283705.0\","+
" \"3\": \"154580.0\","+
" \"4\": \"81997.0\","+
" \"5\": \"59372.0\","+
" \"6\": \"48793.0\","+
" \"7\": \"32744.0\","+
" \"8\": \"18850.0\","+
" \"9\": \"15743.0\","+
" \"10\": \"15671.0\","+
" \"11\": \"14388.0\","+
" \"12\": \"12861.0\""+
" }"+
" }"+
"}");
JSONObject expected = new JSONObject("{"+
" \"name\":\"bitcoin.time.amount\","+
" \"description\":\"Binned bitcoin.time.amount data showing time vs. amount\","+
" \"version\":\"1.0\","+
" \"tilesizex\":256,"+
" \"tilesizey\":256,"+
" \"scheme\":\"TMS\","+
" \"projection\":\"EPSG:4326\","+
" \"zoomlevels\":[0,1,2,3,4,5,6,7,8,9,10,11,12],"+
" \"bounds\": [ 1231002905000.0, 0.0, 1365618170007.8, 500000.0 ],"+
" \"meta\":{"+
" \"global\":{\"minimum\":\"0.0\",\"maximum\":\"1016406.0\"},"+
" \"0\": {\"minimum\":\"0.0\",\"maximum\":\"1016406.0\"},"+
" \"1\": {\"minimum\":\"0.0\",\"maximum\":\"556010.0\"},"+
" \"2\": {\"minimum\":\"0.0\",\"maximum\":\"283705.0\"},"+
" \"3\": {\"minimum\":\"0.0\",\"maximum\":\"154580.0\"},"+
" \"4\": {\"minimum\":\"0.0\",\"maximum\":\"81997.0\"},"+
" \"5\": {\"minimum\":\"0.0\",\"maximum\":\"59372.0\"},"+
" \"6\": {\"minimum\":\"0.0\",\"maximum\":\"48793.0\"},"+
" \"7\": {\"minimum\":\"0.0\",\"maximum\":\"32744.0\"},"+
" \"8\": {\"minimum\":\"0.0\",\"maximum\":\"18850.0\"},"+
" \"9\": {\"minimum\":\"0.0\",\"maximum\":\"15743.0\"},"+
" \"10\": {\"minimum\":\"0.0\",\"maximum\":\"15671.0\"},"+
" \"11\": {\"minimum\":\"0.0\",\"maximum\":\"14388.0\"},"+
" \"12\": {\"minimum\":\"0.0\",\"maximum\":\"12861.0\"}"+
" }"+
"}");
// Compare just as JSON
JSONObject initial = new JSONObject(initialText);
PyramidMetaDataVersionMutator.updateMetaData(initial, "1.0");
compareJson("", expected, initial);
// Compare as metadata
PyramidMetaData metaData = new PyramidMetaData(initialText);
compareJson("", expected, metaData.getRawData());
metaData = new PyramidMetaData(new JSONObject(initialText));
compareJson("", expected, metaData.getRawData());
}
private <T> void compareSets(String message, Set<T> expected, Set<T> actual) {
Assert.assertEquals(message+": length", expected.size(), actual.size());
Set<T> extra = new HashSet<>(expected);
extra.removeAll(actual);
Assert.assertEquals(message+": key mismatches", 0, extra.size());
}
private void compareJson (String curPath, JSONObject expected, JSONObject actual) throws JSONException {
Set<String> expectedKeys = new HashSet<>(Arrays.asList(JSONObject.getNames(expected)));
Set<String> actualKeys = new HashSet<>(Arrays.asList(JSONObject.getNames(expected)));
compareSets(curPath+" keys", expectedKeys, actualKeys);
for (String key: expectedKeys) {
Object expectedValue = expected.get(key);
Object actualValue = actual.get(key);
if (expectedValue instanceof JSONObject) {
String newPath = (curPath.isEmpty() ? key : curPath+"."+key);
compareJson(newPath, (JSONObject) expectedValue, (JSONObject) actualValue);
} else if (expectedValue instanceof JSONArray) {
String newPath = (curPath.isEmpty() ? key : curPath+"."+key);
compareJson(newPath, (JSONArray) expectedValue, (JSONArray) actualValue);
} else {
if (expectedValue instanceof Double || actualValue instanceof Double) {
double de = expected.getDouble(key);
double da = actual.getDouble(key);
Assert.assertEquals(curPath+" double value", de, da, EPSILON);
} else if (expectedValue instanceof Long || actualValue instanceof Long) {
long le = expected.getLong(key);
long la = actual.getLong(key);
Assert.assertEquals(curPath+" long value", le, la);
} else if (expectedValue instanceof Integer || actualValue instanceof Integer) {
int ie = expected.getInt(key);
int ia = actual.getInt(key);
Assert.assertEquals(curPath+" int value", ie, ia);
} else if (expectedValue instanceof Boolean || actualValue instanceof Boolean) {
boolean be = expected.getBoolean(key);
boolean ba = actual.getBoolean(key);
Assert.assertEquals(curPath+" boolean value", be, ba);
} else if (expectedValue instanceof String || actualValue instanceof String) {
String se = expected.getString(key);
String sa = actual.getString(key);
Assert.assertEquals(curPath+" string value", se, sa);
} else {
Assert.assertEquals(curPath+" value", expected, actual);
}
}
}
}
private void compareJson (String curPath, JSONArray expected, JSONArray actual) throws JSONException {
Assert.assertEquals(curPath+" length", expected.length(), actual.length());
for (int key=0; key<expected.length(); ++key) {
Object expectedValue = expected.get(key);
Object actualValue = actual.get(key);
if (expectedValue instanceof JSONObject) {
String newPath = (curPath.isEmpty() ? ""+key : curPath+"."+key);
compareJson(newPath, (JSONObject) expectedValue, (JSONObject) actualValue);
} else if (expectedValue instanceof JSONArray) {
String newPath = (curPath.isEmpty() ? ""+key : curPath+"."+key);
compareJson(newPath, (JSONArray) expectedValue, (JSONArray) actualValue);
} else {
if (expectedValue instanceof Double || actualValue instanceof Double) {
double de = expected.getDouble(key);
double da = actual.getDouble(key);
Assert.assertEquals(curPath+" double value", de, da, EPSILON);
} else if (expectedValue instanceof Long || actualValue instanceof Long) {
long le = expected.getLong(key);
long la = actual.getLong(key);
Assert.assertEquals(curPath+" long value", le, la);
} else if (expectedValue instanceof Integer || actualValue instanceof Integer) {
int ie = expected.getInt(key);
int ia = actual.getInt(key);
Assert.assertEquals(curPath+" int value", ie, ia);
} else if (expectedValue instanceof Boolean || actualValue instanceof Boolean) {
boolean be = expected.getBoolean(key);
boolean ba = actual.getBoolean(key);
Assert.assertEquals(curPath+" boolean value", be, ba);
} else if (expectedValue instanceof String || actualValue instanceof String) {
String se = expected.getString(key);
String sa = actual.getString(key);
Assert.assertEquals(curPath+" string value", se, sa);
} else {
Assert.assertEquals(curPath+" value", expected, actual);
}
}
}
}
}