/**
* JsonFieldConverter
* Copyright 09.04.2015 by Dang Hai An, @zyzo
* <p/>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* <p/>
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* <p/>
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21.txt
* If not, see <http://www.gnu.org/licenses/>.
*/
package org.loklak.harvester;
import org.json.JSONArray;
import org.json.JSONObject;
import org.loklak.data.DAO;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
public class JsonFieldConverter {
public enum JsonConversionSchemaEnum {
FOSSASIA("fossasia.json"),
OPENWIFIMAP("openwifimap.json"),
NODELIST_NODE("nodelist-node.json"),
FREIFUNK_NODE("freifunk-node.json"),
NETMON_NODE("netmon-node.json"),
;
private String filename;
JsonConversionSchemaEnum(String filename) {
this.filename = filename;
}
public String getFilename() { return filename; }
}
private Map<String, List<String>> conversionRules;
@SuppressWarnings("unchecked")
public JsonFieldConverter(JsonConversionSchemaEnum conversionSchema) throws IOException {
final JSONObject convSchema = DAO.getConversionSchema(conversionSchema.getFilename());
List<List<?>> convRules = (List<List<?>>) convSchema.get("rules");
this.conversionRules = new HashMap<>();
for (List<?> rule : convRules) {
List<String> toInsert = new ArrayList<>();
this.conversionRules.put((String) rule.get(0), toInsert);
// the 2nd rule can be either a string
if (rule.get(1) instanceof String) {
toInsert.add((String) rule.get(1));
} else {
// or an array
for (String afterField : (List<String>) rule.get(1)) {
toInsert.add(afterField);
}
}
}
}
public JSONArray convert(JSONArray initialJson) throws IOException {
JSONArray result = new JSONArray();
for (Object o : initialJson) {
result.put(this.convert((JSONObject) o));
}
return result;
}
public JSONObject convert(JSONObject initialJson) throws IOException {
Iterator<Map.Entry<String, List<String>>> it = this.conversionRules.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, List<String>> entry = (Map.Entry<String, List<String>>) it.next();
String key = entry.getKey();
Object value = getFieldValue(initialJson, key);
if (value == null) { continue; } // field not found
for (String newKey : entry.getValue()) {
putToField(initialJson, newKey, value);
}
}
return initialJson;
}
private static Object getFieldValue(JSONObject object, String key) {
if (key.contains(".")) {
String[] deepFields = key.split(Pattern.quote("."));
JSONObject currentLevel = object;
for (int lvl = 0; lvl < deepFields.length; lvl++) {
if (lvl == deepFields.length - 1) {
return currentLevel.get(deepFields[lvl]);
} else {
if (currentLevel.get(deepFields[lvl]) == null) {
return null;
}
currentLevel = (JSONObject) currentLevel.get(deepFields[lvl]);
}
}
} else {
return object.get(key);
}
// unreachable code
return null;
}
private static void putToField(JSONObject object, String key, Object value) {
if (key.contains(".")) {
String[] deepFields = key.split(Pattern.quote("."));
JSONObject currentLevel = object;
for (int lvl = 0; lvl < deepFields.length; lvl++) {
if (lvl == deepFields.length - 1) {
currentLevel.put(deepFields[lvl], value);
} else {
if (currentLevel.get(deepFields[lvl]) == null) {
currentLevel.put(deepFields[lvl], new HashMap<>());
}
currentLevel = (JSONObject) currentLevel.get(deepFields[lvl]);
}
}
} else {
object.put(key, value);
}
}
}