{
throw new IllegalArgumentException("JSON format must have a root 'ncube' field containing the String name of the NCube.");
}
NCube ncube = new NCube(cubeName);
ncube.setVersion("file");
ncube.metaProps = new CaseInsensitiveMap();
ncube.metaProps.putAll(jsonNCube);
ncube.metaProps.remove("ncube");
ncube.metaProps.remove("defaultCellValue");
ncube.metaProps.remove("defaultCellValueType");
ncube.metaProps.remove("ruleMode");
ncube.metaProps.remove("axes");
ncube.metaProps.remove("cells");
if (ncube.metaProps.size() < 1)
{ // No additional props, don't even waste space for additional meta properties.
ncube.metaProps = null;
}
String defType = (String) jsonNCube.get("defaultCellValueType");
ncube.defaultCellValue = parseJsonValue(jsonNCube.get("defaultCellValue"), null, defType, false);
ncube.ruleMode = getBoolean(jsonNCube, "ruleMode");
if (!(jsonNCube.get("axes") instanceof JsonObject))
{
throw new IllegalArgumentException("Must specify a list of axes for the ncube, under the key 'axes' as [{axis 1}, {axis 2}, ... {axis n}].");
}
JsonObject axes = (JsonObject) jsonNCube.get("axes");
Object[] items = axes.getArray();
if (ArrayUtilities.isEmpty(items))
{
throw new IllegalArgumentException("Must be at least one axis defined in the JSON format.");
}
// Read axes
for (Object item : items)
{
Map jsonAxis = (Map) item;
String name = getString(jsonAxis, "name");
AxisType type = AxisType.valueOf(getString(jsonAxis, "type"));
boolean hasDefault = getBoolean(jsonAxis, "hasDefault");
AxisValueType valueType = AxisValueType.valueOf(getString(jsonAxis, "valueType"));
final int preferredOrder = getLong(jsonAxis, "preferredOrder").intValue();
final Boolean multiMatch = getBoolean(jsonAxis, "multiMatch");
Axis axis = new Axis(name, type, valueType, hasDefault, preferredOrder, multiMatch);
ncube.addAxis(axis);
axis.metaProps = new CaseInsensitiveMap();
axis.metaProps.putAll(jsonAxis);
axis.metaProps.remove("name");
axis.metaProps.remove("type");
axis.metaProps.remove("hasDefault");
axis.metaProps.remove("valueType");
axis.metaProps.remove("preferredOrder");
axis.metaProps.remove("multiMatch");
axis.metaProps.remove("columns");
if (axis.metaProps.size() < 1)
{
axis.metaProps = null;
}
if (!(jsonAxis.get("columns") instanceof JsonObject))
{
throw new IllegalArgumentException("'columns' must be specified, axis '" + name + "', NCube '" + cubeName + "'");
}
JsonObject colMap = (JsonObject) jsonAxis.get("columns");
if (!colMap.isArray())
{
throw new IllegalArgumentException("'columns' must be an array, axis '" + name + "', NCube '" + cubeName + "'");
}
// Read columns
Object[] cols = colMap.getArray();
for (Object col : cols)
{
Map jsonColumn = (Map) col;
Object value = jsonColumn.get("value");
String url = (String)jsonColumn.get("url");
String colType = (String) jsonColumn.get("type");
Object id = jsonColumn.get("id");
if (value == null)
{
if (id == null)
{
throw new IllegalArgumentException("Missing 'value' field on column or it is null, axis '" + name + "', NCube '" + cubeName + "'");
}
else
{ // Allows you to skip setting both id and value to the same value.
value = id;
}
}
boolean cache = true;
if (jsonColumn.containsKey("cache"))
{
if (jsonColumn.get("cache") instanceof Boolean)
{
cache = (Boolean) jsonColumn.get("cache");
}
else if (jsonColumn.get("cache") instanceof String)
{ // Allow setting it as a String too
cache = "true".equalsIgnoreCase((String)jsonColumn.get("cache"));
}
else
{
throw new IllegalArgumentException("'cache' parameter must be set to 'true' or 'false', or not used (defaults to 'true')");
}
}
Column colAdded;
if (type == AxisType.DISCRETE || type == AxisType.NEAREST)
{
colAdded = ncube.addColumn(axis.getName(), (Comparable) parseJsonValue(value, null, colType, false));
}
else if (type == AxisType.RANGE)
{
Object[] rangeItems = ((JsonObject)value).getArray();
if (rangeItems.length != 2)
{
throw new IllegalArgumentException("Range must have exactly two items, axis '" + name +"', NCube '" + cubeName + "'");
}
Comparable low = (Comparable) parseJsonValue(rangeItems[0], null, colType, false);
Comparable high = (Comparable) parseJsonValue(rangeItems[1], null, colType, false);
colAdded = ncube.addColumn(axis.getName(), new Range(low, high));
}
else if (type == AxisType.SET)
{
Object[] rangeItems = ((JsonObject)value).getArray();
RangeSet rangeSet = new RangeSet();
for (Object pt : rangeItems)
{
if (pt instanceof Object[])
{
Object[] rangeValues = (Object[]) pt;
Comparable low = (Comparable) parseJsonValue(rangeValues[0], null, colType, false);
Comparable high = (Comparable) parseJsonValue(rangeValues[1], null, colType, false);
Range range = new Range(low, high);
rangeSet.add(range);
}
else
{
rangeSet.add((Comparable)parseJsonValue(pt, null, colType, false));
}
}
colAdded = ncube.addColumn(axis.getName(), rangeSet);
}
else if (type == AxisType.RULE)
{
Object cmd = parseJsonValue(value, url, colType, cache);
if (!(cmd instanceof CommandCell))
{
throw new IllegalArgumentException("Column values on a RULE axis must be of type CommandCell, axis '" + name + "', NCube '" + cubeName + "'");
}
colAdded = ncube.addColumn(axis.getName(), (CommandCell)cmd);
}
else
{
throw new IllegalArgumentException("Unsupported Axis Type '" + type + "' for simple JSON input, axis '" + name + "', NCube '" + cubeName + "'");
}
if (id != null)
{
long sysId = colAdded.getId();
userIdToUniqueId.put(id, sysId);
}
colAdded.metaProps = new CaseInsensitiveMap();
colAdded.metaProps.putAll(jsonColumn);
colAdded.metaProps.remove("id");
colAdded.metaProps.remove("value");
colAdded.metaProps.remove("type");
colAdded.metaProps.remove("url");