package com.bagri.samples.ext.df;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.xml.xquery.XQItemType;
import com.bagri.core.api.BagriException;
import com.bagri.core.model.Data;
import com.bagri.core.model.Element;
import com.bagri.core.model.NodeKind;
import com.bagri.core.model.Occurrence;
import com.bagri.core.model.Path;
import com.bagri.core.server.api.ContentParser;
import com.bagri.core.server.api.ModelManagement;
import com.bagri.core.server.api.impl.ContentParserBase;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
public class JaksonParser extends ContentParserBase implements ContentParser<String> {
private static JsonFactory factory = new JsonFactory();
public static List<Data> parseDocument(ModelManagement model, String json) throws BagriException {
JaksonParser parser = new JaksonParser(model);
parser.init(new Properties());
return parser.parse(json);
}
public JaksonParser(ModelManagement model) {
super(model);
}
/**
* {@inheritDoc}
*/
@Override
public void init(Properties properties) {
for (Map.Entry prop: properties.entrySet()) {
String name = (String) prop.getKey();
JsonParser.Feature f = JsonParser.Feature.valueOf(name);
if (f != null) {
factory.configure(f, Boolean.valueOf((String) prop.getValue()));
}
}
}
private void closeParser(JsonParser jParser) {
if (jParser != null) {
try {
jParser.close();
} catch (IOException ex) {
logger.error("closeParser.error", ex);
}
}
}
@Override
public List<Data> parse(String json) throws BagriException {
JsonParser jParser = null;
try {
jParser = factory.createParser(json);
return parse(jParser);
} catch (IOException ex) {
throw new BagriException(ex, BagriException.ecInOut);
} finally {
closeParser(jParser);
}
}
@Override
public List<Data> parse(File file) throws BagriException {
JsonParser jParser = null;
try {
jParser = factory.createParser(file);
return parse(jParser);
} catch (IOException ex) {
throw new BagriException(ex, BagriException.ecInOut);
} finally {
closeParser(jParser);
}
}
@Override
public List<Data> parse(InputStream stream) throws BagriException {
JsonParser jParser = null;
try {
jParser = factory.createParser(stream);
return parse(jParser);
} catch (IOException ex) {
throw new BagriException(ex, BagriException.ecInOut);
} finally {
closeParser(jParser);
}
}
@Override
public List<Data> parse(Reader reader) throws BagriException {
JsonParser jParser = null;
try {
jParser = factory.createParser(reader);
return parse(jParser);
} catch (IOException ex) {
throw new BagriException(ex, BagriException.ecInOut);
} finally {
closeParser(jParser);
}
}
public List<Data> parse(JsonParser parser) throws BagriException {
logger.trace("parse.enter; context: {}; schema: {}", parser.getParsingContext(), parser.getSchema());
ParserContext ctx = initContext();
try {
while (parser.nextToken() != null) {
processToken(ctx, parser);
}
} catch (IOException ex) {
throw new BagriException(ex, BagriException.ecInOut);
}
return ctx.getDataList();
}
private void processToken(ParserContext ctx, JsonParser parser) throws IOException, BagriException { //, XMLStreamException {
JsonToken token = parser.getCurrentToken();
logger.trace("processToken; got token: {}; name: {}; value: {}", token.name(), parser.getCurrentName(), parser.getText());
switch (token) {
case START_OBJECT:
if (ctx.getTopData() == null) {
ctx.addDocument("/");
} else {
ctx.addElement();
}
break;
case START_ARRAY:
ctx.addArray();
break;
case NOT_AVAILABLE:
break;
case FIELD_NAME:
ctx.addData(parser.getCurrentName());
break;
case END_OBJECT:
case END_ARRAY:
ctx.endElement();
break;
case VALUE_EMBEDDED_OBJECT:
// ???
break;
case VALUE_FALSE:
ctx.addValue(false);
break;
case VALUE_NULL:
ctx.addValue();
break;
case VALUE_NUMBER_FLOAT:
ctx.addValue(parser.getDecimalValue());
break;
case VALUE_NUMBER_INT:
ctx.addValue(parser.getLongValue());
break;
case VALUE_TRUE:
ctx.addValue(true);
break;
case VALUE_STRING:
ctx.addValue(parser.getText());
break;
default:
logger.trace("processToken; unknown token: {}", token);
}
}
/*
private void processDocument(ParserContext ctx, String name) throws BagriException {
String root = "/" + (name == null ? "" : name);
ctx.setDocType(model.translateDocumentType(root));
Path path = model.translatePath(ctx.getDocType(), "", NodeKind.document, XQItemType.XQBASETYPE_ANYTYPE, Occurrence.onlyOne);
Element start = new Element();
Data data = new Data(path, start);
ctx.addStack(data);
ctx.addData(data);
}
private boolean isAttribute(String name) {
return name.startsWith("-") || name.startsWith("@");
}
private void processStartElement(ParserContext ctx, String name) throws BagriException {
if (name != null && !isAttribute(name)) {
Data parent = ctx.peekData();
if (name.equals("#text")) {
// add marker
ctx.addStack(null);
} else if (!name.equals(parent.getName())) {
Data current = addData(ctx, parent, NodeKind.element, "/" + name, null, XQItemType.XQBASETYPE_ANYTYPE, Occurrence.zeroOrOne);
ctx.addStack(current);
}
}
}
private void processEndElement(ParserContext ctx) {
ctx.popData();
}
private void processValueElement(ParserContext ctx, String name, String value) throws BagriException {
//value = value.replaceAll("&", "&");
if (name == null) {
Data current = ctx.peekData();
if (current == null) {
// #text in array; not sure it'll always work.
// use XDMJsonParser.getTopData instead ?
current = ctx.getStackElement(ctx.getStackSize() - 2);
// this is for Deque
//Iterator<Data> itr = dataStack.descendingIterator();
//itr.next();
//current = itr.next();
}
addData(ctx, current, NodeKind.text, "/text()", value, XQItemType.XQBASETYPE_ANYATOMICTYPE, Occurrence.zeroOrOne);
} else if (isAttribute(name)) {
Data current = ctx.peekData();
name = name.substring(1);
if (name.startsWith("xmlns")) {
addData(ctx, current, NodeKind.namespace, "/#" + name, value, XQItemType.XQBASETYPE_STRING, Occurrence.onlyOne);
} else {
addData(ctx, current, NodeKind.attribute, "/@" + name, value, XQItemType.XQBASETYPE_ANYATOMICTYPE, Occurrence.zeroOrOne);
}
} else {
Data current = ctx.popData();
if (current == null) {
// #text
current = ctx.peekData();
}
addData(ctx, current, NodeKind.text, "/text()", value, XQItemType.XQBASETYPE_ANYATOMICTYPE, Occurrence.zeroOrOne);
}
}
*/
}