/*******************************************************************************
* Copyright (c) 2006-2010 eBay Inc. All Rights Reserved.
* 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
*******************************************************************************/
package org.ebayopensource.turmeric.runtime.binding.impl.parser.json;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Stack;
import javax.xml.namespace.QName;
import org.ebayopensource.turmeric.runtime.binding.BindingConstants;
import org.ebayopensource.turmeric.runtime.binding.impl.parser.NamespaceConvention;
import org.ebayopensource.turmeric.runtime.binding.impl.parser.ParseException;
import org.ebayopensource.turmeric.runtime.binding.objectnode.impl.ObjectNodeImpl;
import org.ebayopensource.turmeric.runtime.binding.utils.CollectionUtils;
/**
* @author wdeng
*/
public class JSONStreamReadContext {
public static final String KEY_VALUE_KEY = "valueKey";
private JSONLexer m_lexer;
private NamespaceConvention m_convention;
private JSONToken m_currentToken;
private Stack<ObjectNodeImpl> m_nodes; // The object node that is builting or built.
private String m_singleNamespace;
String m_valueKey = BindingConstants.JSON_VALUE_KEY;
public JSONStreamReadContext(InputStream in, NamespaceConvention convention, Charset charset) {
this(in, convention, charset, CollectionUtils.EMPTY_STRING_MAP);
}
public JSONStreamReadContext(InputStream in, NamespaceConvention convention, Charset charset, Map<String, String> options) {
setupOptions(options);
m_lexer = new JSONLexer(new InputStreamReader(in, charset));
m_convention = convention;
m_singleNamespace = m_convention.getSingleNamespace();
m_nodes = new Stack<ObjectNodeImpl>();
getNextToken();
if (null == m_currentToken) {
m_currentToken = JSONToken.END_TOKEN;
}
}
public JSONTokenType getCurrentTokenType() {
if (null == m_currentToken) {
throw new ParseException(m_lexer.yytext(), m_lexer.getRow(), m_lexer.getColumn(), "Unexpected end of input stream.");
}
return m_currentToken.m_type;
}
public JSONToken getCurrentToken() {
return m_currentToken;
}
public QName createQName(String prefix, String localPart, boolean isTopNode) {
if ((null == prefix || prefix.length() == 0) && m_singleNamespace != null) {
if (isTopNode) {
return new QName(m_singleNamespace, localPart);
}
return new QName("", localPart);
}
return JSONStreamWriter.createQName(m_convention, prefix, localPart);
}
public JSONToken getNextToken() {
try {
m_currentToken = m_lexer.yylex();
// LogManager.getInstance(JSONStreamReadContext.class).log(Level.FINE, "Token read: " + m_currentToken);
return m_currentToken;
} catch (IOException ioe) {
throw new ParseException(m_lexer.yytext(), m_lexer.getRow(), m_lexer.getColumn(), ioe);
}
}
public void newNodeCreated(ObjectNodeImpl newNode) {
// LogManager.getInstance(JSONStreamReadContext.class).log(Level.INFO, "Push: " + newNode + " to " + m_nodes);
m_nodes.push(newNode);
}
public void nodeBuildingCompleted(ObjectNodeImpl node) {
ObjectNodeImpl currentNode = m_nodes.pop();
// LogManager.getInstance(JSONStreamReadContext.class).log(Level.INFO, "Pop: " + node + " from " + m_nodes);
assert(currentNode==node);
}
public void buildValue(JSONStreamObjectNodeImpl caller, QName key, int idxToFind, boolean singleChildPolicyApplied) {
buildAndFindParent(caller, singleChildPolicyApplied);
caller.buildValue(key, idxToFind, false);
}
public void buildNextChild(JSONStreamObjectNodeImpl caller) {
if (m_currentToken == JSONToken.END_TOKEN) {
return;
}
buildAndFindParent(caller, true);
caller.buildValue(null, Integer.MAX_VALUE, true);
}
private void buildAndFindParent(JSONStreamObjectNodeImpl caller, boolean singleChildPolicyApplied) {
JSONStreamObjectNodeImpl node = (JSONStreamObjectNodeImpl) m_nodes.peek();
while (node != caller) {
node.buildValue(null, Integer.MAX_VALUE, false);
node.nodeBuildingCompleted(singleChildPolicyApplied);
if (m_nodes.empty()) {
break;
}
node = (JSONStreamObjectNodeImpl) m_nodes.peek();
}
}
private void setupOptions(Map<String, String>options) {
String valueKey = options.get(KEY_VALUE_KEY);
if (null != valueKey && valueKey.length() > 0) {
m_valueKey = valueKey;
}
}
}