/*
* Copyright 2008-2011 the original author or authors.
*
* 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.
*
*/
package com.nominanuda.zen.obj;
import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
public class JsonSaxAdapter implements JixHandler {
public static final String JSON_SAX = "urn:JSON_SAX_NS";
public static final String JSON_SAX_NS = "urn:JSON_SAX_NS";
public static final String OBJECT_TAG = "obj";
public static final String OBJECT_ENTRY_TAG = "entry";
public static final String OBJECT_ENTRY_KEY_TAG = "key";
public static final String OBJECT_ENTRY_VALUE_TAG = "val";
public static final String ARRAY_TAG = "arr";
public static final String NULL_VALUE = "null";
private final Attributes EMPTY_ATTRS = new AttributesImpl();
private final ContentHandler ch;
private int nestingLevel = -1;
private Stack<Integer> entryNestingLevels = new Stack<>();
public JsonSaxAdapter(ContentHandler ch) {
this.ch = ch;
}
private void beforeEnterValue() {
nestingLevel++;
if(nestingLevel == 0) {
startJSON();
}
}
private void beforeEnterKey() {
entryNestingLevels.push(nestingLevel);
}
private void afterExitValue() {
if(nestingLevel == 0) {
endJSON();
} else {
if(nestingLevel == entryNestingLevels.peek()) {
entryNestingLevels.pop();
endObjectEntry();
}
}
nestingLevel--;
}
private void startJSON() throws RuntimeException {
try {
ch.startDocument();
ch.startPrefixMapping(JSON_SAX, JSON_SAX_NS);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
private void endJSON() throws RuntimeException {
try {
ch.endPrefixMapping(JSON_SAX);
ch.endDocument();
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
private String qname(String localName) {
return JSON_SAX_NS + ":" + localName;
}
@Override
public void startObj() throws RuntimeException {
beforeEnterValue();
try {
ch.startElement(JSON_SAX_NS, OBJECT_TAG, qname(OBJECT_TAG),
EMPTY_ATTRS);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
@Override
public void endObj() throws RuntimeException {
try {
ch.endElement(JSON_SAX_NS, OBJECT_TAG, qname(OBJECT_TAG));
} catch (SAXException e) {
throw new RuntimeException(e);
}
afterExitValue();
}
@Override
public void key(Key key) throws RuntimeException {
beforeEnterKey();
try {
String _key = key.get();
ch.startElement(JSON_SAX_NS, OBJECT_ENTRY_TAG,
qname(OBJECT_ENTRY_TAG), EMPTY_ATTRS);
ch.startElement(JSON_SAX_NS, OBJECT_ENTRY_KEY_TAG,
qname(OBJECT_ENTRY_KEY_TAG), EMPTY_ATTRS);
ch.characters(_key.toCharArray(), 0, _key.length());
ch.endElement(JSON_SAX_NS, OBJECT_ENTRY_KEY_TAG,
qname(OBJECT_ENTRY_KEY_TAG));
ch.startElement(JSON_SAX_NS, OBJECT_ENTRY_VALUE_TAG,
qname(OBJECT_ENTRY_VALUE_TAG), EMPTY_ATTRS);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
private void endObjectEntry() throws RuntimeException {
try {
ch.endElement(JSON_SAX_NS, OBJECT_ENTRY_VALUE_TAG,
qname(OBJECT_ENTRY_VALUE_TAG));
ch.endElement(JSON_SAX_NS, OBJECT_ENTRY_TAG,
qname(OBJECT_ENTRY_TAG));
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
@Override
public void startArr() throws RuntimeException {
beforeEnterValue();
try {
ch.startElement(JSON_SAX_NS, ARRAY_TAG, qname(ARRAY_TAG),
EMPTY_ATTRS);
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
@Override
public void endArr() throws RuntimeException {
try {
ch.endElement(JSON_SAX_NS, ARRAY_TAG, qname(ARRAY_TAG));
} catch (SAXException e) {
throw new RuntimeException(e);
}
afterExitValue();
}
@Override
public void val(Val value) throws RuntimeException {
try {
beforeEnterValue();
JsonType t = value.getType();
if(value.isNull()) {
ch.startElement(JSON_SAX_NS, NULL_VALUE, qname(NULL_VALUE),
EMPTY_ATTRS);
ch.endElement(JSON_SAX_NS, NULL_VALUE, qname(NULL_VALUE));
} else {
String v = value.toJavaObjModel().toString();
ch.startElement(JSON_SAX_NS, t.name(), qname(t.name()),
EMPTY_ATTRS);
ch.characters(v.toCharArray(), 0, v.length());
ch.endElement(JSON_SAX_NS, t.name(), qname(t.name()));
}
afterExitValue();
} catch (SAXException e) {
throw new RuntimeException(e);
}
}
}