/*
* eXist Open Source Native XML Database
* Copyright (C) 2011 The eXist Project
* http://exist-db.org
*
* This program 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
* of the License, or (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $Id$
*/
package org.exist.util.serializer.json;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
public class JSONObject extends JSONNode {
protected JSONNode firstChild = null;
private boolean asSimpleValue = false;
public JSONObject() {
super(Type.OBJECT_TYPE, ANONYMOUS_OBJECT);
}
public JSONObject(String name) {
super(Type.OBJECT_TYPE, name);
}
public JSONObject(String name, boolean asSimpleValue) {
super(Type.OBJECT_TYPE, name);
this.asSimpleValue = asSimpleValue;
}
public void addObject(JSONNode node) {
JSONNode childNode = findChild(node.getName());
if (childNode == null) {
childNode = getLastChild();
if (childNode == null)
firstChild = node;
else
childNode.setNext(node);
} else
childNode.setNextOfSame(node);
}
public JSONNode findChild(String nameToFind) {
JSONNode nextNode = firstChild;
while (nextNode != null) {
if (nextNode.getName().equals(nameToFind))
return nextNode;
nextNode = nextNode.getNext();
}
return null;
}
public JSONNode getLastChild() {
JSONNode nextNode = firstChild;
JSONNode currentNode = null;
while (nextNode != null) {
currentNode = nextNode;
nextNode = currentNode.getNext();
}
return currentNode;
}
public int getChildCount() {
int count = 0;
JSONNode nextNode = firstChild;
while (nextNode != null) {
count++;
nextNode = nextNode.getNext();
}
return count;
}
public void serialize(Writer writer, boolean isRoot) throws IOException {
if (!isRoot && isNamed()) {
writer.write('"');
writer.write(getName());
writer.write("\" : ");
}
if (getNextOfSame() != null || getSerializationType() == SerializationType.AS_ARRAY) {
writer.write("[");
JSONNode next = this;
while (next != null) {
next.serializeContent(writer);
next = next.getNextOfSame();
if (next != null)
writer.write(", ");
}
writer.write("]");
} else
serializeContent(writer);
}
public void serializeContent(Writer writer) throws IOException {
if (firstChild == null)
// an empty node gets a null value
writer.write("null");
else if (firstChild.getNext() == null &&
(
firstChild.getType() == Type.VALUE_TYPE ||
(firstChild.isArray() && !firstChild.isNamed())
)
)
// if there's only one child and if it is text, it is serialized as simple value
firstChild.serialize(writer, false);
else {
// complex object
writer.write("{ ");
JSONNode next = firstChild;
boolean allowText = false;
boolean skipMixedContentText = false;
while (next != null) {
if (next.getType() == Type.VALUE_TYPE) {
// if an element has attributes and text content, the text
// node is serialized as property "#text".
// Text in mixed content nodes is ignored though.
if (allowText) {
writer.write("\"#text\" : ");
next.serialize(writer, false);
allowText = false;
} else {
//writer.write("\"#mixed-content-text\" : ");
skipMixedContentText = true;
}
} else
next.serialize(writer, false);
if (next.getType() == Type.SIMPLE_PROPERTY_TYPE)
allowText = true;
next = next.getNext();
if (next != null && !skipMixedContentText && !isMixedContentTextLast(next, allowText)) {
writer.write(", ");
}
skipMixedContentText = false;
}
writer.write(" }");
}
}
private boolean isMixedContentTextLast(final JSONNode node, final boolean allowText) {
if (node.getType() == Type.VALUE_TYPE && !allowText && node.equals(getLastChild()))
return true;
return false;
}
@Override
public String toString() {
StringWriter writer = new StringWriter();
try {
serialize(writer, false);
} catch (IOException e) {
e.printStackTrace();
}
return writer.toString();
}
}