/** * Copyright (C) 2012-2014 Gist Labs, LLC. (http://gistlabs.com) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.gistlabs.mechanize.document.json.node.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.gistlabs.mechanize.document.json.exceptions.JsonArrayException; import com.gistlabs.mechanize.document.json.exceptions.JsonException; import com.gistlabs.mechanize.document.json.node.JsonNode; public class ObjectNodeImpl extends AbstractJsonNode { private final JSONObject obj; private final Map<String,List<JsonNode>> children = new HashMap<String, List<JsonNode>>(); public ObjectNodeImpl(final JSONObject obj) { this("root", obj); } public ObjectNodeImpl(final String name, final JSONObject obj) { this(null, name, obj); } public ObjectNodeImpl(final JsonNode parent, final String name, final JSONObject obj) { super(parent, name); if (obj==null) throw new NullPointerException("JSONObject can't be null"); this.obj = obj; } @Override public String toString() { return obj.toString(); } @Override public String getAttribute(final String key) { try { Object value = obj.get(key); if (value==JSONObject.NULL) return null; return value.toString(); } catch (JSONException e) { throw new JsonException(e); } } @Override public void setAttribute(final String key, final String value) { try { obj.put(key, value==null ? JSONObject.NULL : value); } catch (JSONException e) { throw new JsonException(e); } } @Override public boolean hasAttribute(final String key) { return obj.has(key); } @Override public List<String> getAttributeNames() { try { List<String> result = new ArrayList<String>(); @SuppressWarnings("unchecked") Iterator<String> keys = this.obj.keys(); while(keys.hasNext()) { String key = keys.next(); if (isPrimitive(this.obj.get(key))) result.add(key); } return result; } catch (JSONException e) { throw new JsonException(e); } } @Override public String getValue() { return null; } @Override public void setValue(final String value) { throw new JsonException("JSON Objects can't directly have coSntent"); } @SuppressWarnings("unchecked") @Override public JsonNode getChild(final String key) { List<JsonNode> result = getChildren(key); if (result.size()>=2) throw new JsonException("More than one result"); else if (result.isEmpty()) return null; else return result.get(0); } protected boolean isPrimitive(final Object jsonObject) { return !(jsonObject instanceof JSONObject || jsonObject instanceof JSONArray); } @Override public List<JsonNode> getChildren() { try { List<JsonNode> result = new ArrayList<JsonNode>(); @SuppressWarnings("unchecked") Iterator<String> keys = this.obj.keys(); while(keys.hasNext()) { String key = keys.next(); // if (!isPrimitive(this.obj.get(key))) result.addAll(getChildren(key)); } return result; } catch (Exception e) { throw new JsonException(e); } } @Override public List<JsonNode> getChildren(final String... names) { int length = names.length; if (length==0) return getChildren(); if (length==1) { if ("*".equalsIgnoreCase(names[0])) return getChildren(); return lookupChildren(names[0]); } List<String> namesColl = Arrays.asList(names); List<JsonNode> result = new ArrayList<JsonNode>(); for(JsonNode node : getChildren()) if (namesColl.contains(node.getName())) result.add(node); return result; } protected List<JsonNode> lookupChildren(final String key) { if (!children.containsKey(key)) if ("*".equalsIgnoreCase(key)) children.put(key, getChildren()); else children.put(key, factory(key)); return children.get(key); } protected List<JsonNode> factory(final String key) { try { ArrayList<JsonNode> result = new ArrayList<JsonNode>(); try { JsonNode n = factory(this.obj, key); if (n!=null) result.add(n); } catch(JsonArrayException e) { if (e.getArray()==null) throw e; JSONArray array = e.getArray(); for(int i=0;i < array.length();i++){ Object obj = array.get(i); result.add(factory(key, obj, array, i)); } } return result; } catch (JSONException e) { throw new JsonException(e); } } }