/******************************************************************************* * Copyright 2012 University of Southern California * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This code was developed by the Information Integration Group as part * of the Karma project at the Information Sciences Institute of the * University of Southern California. For more information, publications, * and related projects, please see: http://www.isi.edu/integration ******************************************************************************/ /** * */ package edu.isi.karma.imp.json; import java.util.Iterator; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.isi.karma.rep.HNode; import edu.isi.karma.rep.HTable; import edu.isi.karma.rep.RepFactory; import edu.isi.karma.rep.Row; import edu.isi.karma.rep.Table; import edu.isi.karma.rep.Worksheet; import edu.isi.karma.rep.Workspace; import edu.isi.karma.util.JSONUtil; /** * @author szekely * */ public class JsonImport { private static Logger logger = LoggerFactory.getLogger(JsonImport.class); private final Object json; private final RepFactory factory; private final Worksheet worksheet; public JsonImport(Object json, String worksheetName, Workspace workspace) { super(); this.json = json; this.factory = workspace.getFactory(); this.worksheet = factory.createWorksheet(worksheetName, workspace); } public JsonImport(String jsonString, String worksheetName, Workspace workspace) { this(JSONUtil.createJson(jsonString), worksheetName, workspace); } public JsonImport(String jsonString, Worksheet wk, RepFactory repFactory) { this.worksheet = wk; this.factory = repFactory; json = JSONUtil.createJson(jsonString); try { populateWorksheet(); } catch (JSONException e) { logger.error("Error in populating the worksheet with Json"); } } public Worksheet generateWorksheet() throws JSONException { if (json instanceof JSONArray) { JSONArray a = (JSONArray) json; for (int i = 0; i < a.length(); i++) { addListElement(a.get(i), worksheet.getHeaders(), worksheet.getDataTable()); } } else if (json instanceof JSONObject) { addKeysAndValues((JSONObject) json, worksheet.getHeaders(), worksheet.getDataTable()); } else { throw new Error("Can only import objects or arrays."); } writeJsonFile(json); return worksheet; } public void populateWorksheet() throws JSONException { if (json instanceof JSONArray) { JSONArray a = (JSONArray) json; for (int i = 0; i < a.length(); i++) { addListElement(a.get(i), worksheet.getHeaders(), worksheet.getDataTable()); } } else if (json instanceof JSONObject) { addKeysAndValues((JSONObject) json, worksheet.getHeaders(), worksheet.getDataTable()); } else { throw new Error("Can only import objects or arrays."); } writeJsonFile(json); } private static void writeJsonFile(Object o) { JSONUtil.writeJsonFile(o, "lastJsonImport.json"); } private void addObjectElement(String key, Object value, HTable headers, Row row) throws JSONException { HNode hNode = addHNode(headers, key); String hNodeId = hNode.getId(); if (value instanceof String) { row.setValue(hNodeId, (String) value, factory); } else if (value instanceof Integer) { row.setValue(hNodeId, value.toString(), factory); } else if (value instanceof Double) { row.setValue(hNodeId, value.toString(), factory); } else if (value instanceof Long) { row.setValue(hNodeId, value.toString(), factory); } else if (value instanceof Boolean) { row.setValue(hNodeId, value.toString(), factory); } else if (value instanceof JSONObject) { HTable nestedHTable = addNestedHTable(hNode, key); Table nestedTable = row.getNode(hNodeId).getNestedTable(); addKeysAndValues((JSONObject) value, nestedHTable, nestedTable); } else if (value instanceof JSONArray) { HTable nestedHTable = addNestedHTable(hNode, key); Table nestedTable = row.getNode(hNodeId).getNestedTable(); JSONArray a = (JSONArray) value; for (int i = 0; i < a.length(); i++) { addListElement(a.get(i), nestedHTable, nestedTable); } } else if (value == JSONObject.NULL) { // Ignore } else { throw new Error("Cannot handle " + key + ": " + value + " yet."); } } private void addKeysAndValues(JSONObject object, HTable nestedHTable, Table nestedTable) throws JSONException { Row nestedRow = nestedTable.addRow(factory); @SuppressWarnings("unchecked") Iterator<String> it = object.sortedKeys(); while (it.hasNext()) { String nestedKey = it.next(); addObjectElement(nestedKey, object.get(nestedKey), nestedHTable, nestedRow); } } private void addListElement(Object listValue, HTable headers, Table dataTable) throws JSONException { if (listValue instanceof JSONObject) { Row row = dataTable.addRow(factory); JSONObject o = (JSONObject) listValue; @SuppressWarnings("unchecked") Iterator<String> it = o.sortedKeys(); while (it.hasNext()) { String key = it.next(); addObjectElement(key, o.get(key), headers, row); } } else if (isPrimitiveValue(listValue)) { HNode hNode = addHNode(headers, "values"); String hNodeId = hNode.getId(); Row row = dataTable.addRow(factory); // TODO, conserve the types of the primitive types. String value = ""; if (listValue instanceof String || listValue instanceof Boolean) value = (String) listValue; else if (listValue instanceof Double) value = Double.toString((Double) listValue); else if (listValue instanceof Integer) value = Integer.toString((Integer) listValue); else if (listValue instanceof Long) value = Long.toString((Long) listValue); else { // Pedro 2012/09/14 logger.error("Unexpected value in JSON array:" + listValue.toString()); } row.setValue(hNodeId, value, factory); } else if (listValue instanceof JSONArray) { HNode hNode = addHNode(headers, "nested array"); String hNodeId = hNode.getId(); HTable nestedHTable = addNestedHTable(hNode, "nested array values"); Row row = dataTable.addRow(factory); Table nestedTable = row.getNode(hNodeId).getNestedTable(); JSONArray a = (JSONArray) listValue; for (int i = 0; i < a.length(); i++) { addListElement(a.get(i), nestedHTable, nestedTable); } } else { logger.error("Cannot handle whatever case is not covered by the if statements. Sorry."); } } private boolean isPrimitiveValue(Object value) { return value instanceof String || value instanceof Boolean || value instanceof Integer || value instanceof Double || value instanceof Long; } private HTable addNestedHTable(HNode hNode, String key) { HTable ht = hNode.getNestedTable(); if (ht == null) { ht = hNode.addNestedTable(createNestedTableName(key), worksheet, factory); } return ht; } private HNode addHNode(HTable headers, String key) { HNode hn = headers.getHNodeFromColumnName(key); if (hn == null) { hn = headers.addHNode(key, worksheet, factory); } return hn; } private String createNestedTableName(String key) { return "Table for " + key; } }