blob: 61ef3c9ad91a8cd510d236f7e4d87686ce050552 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.netbeans.modules.javascript2.json.parser;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
import java.util.Deque;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.netbeans.api.annotations.common.NonNull;
import org.openide.util.Parameters;
import org.openide.xml.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
*
* @author Tomas Zezula
*/
public class ParseTreeToXml extends JsonBaseVisitor<Document> {
private final JsonLexer lexer;
private final JsonParser parser;
private Document doc;
private final Deque<Element> currentNode;
public ParseTreeToXml (
@NonNull final JsonLexer lexer,
@NonNull final JsonParser parser) {
Parameters.notNull("lexer", lexer); //NOI18N
Parameters.notNull("parser", parser); //NOI18N
this.lexer = lexer;
this.parser = parser;
currentNode = new ArrayDeque<>();
}
@Override
public Document visitJson(JsonParser.JsonContext ctx) {
final Element e = copyAttrs(
getRuleContextElement(ctx.getRuleIndex()),
ctx);
currentNode.addLast(e);
super.visitJson(ctx);
currentNode.removeLast();
return doc;
}
@Override
public Document visitObject(JsonParser.ObjectContext ctx) {
final Element e = copyAttrs(
getRuleContextElement(ctx.getRuleIndex()),
ctx);
currentNode.addLast(e);
super.visitObject(ctx);
currentNode.removeLast();
return doc;
}
@Override
public Document visitArray(JsonParser.ArrayContext ctx) {
final Element e = copyAttrs(
getRuleContextElement(ctx.getRuleIndex()),
ctx);
currentNode.addLast(e);
super.visitArray(ctx);
currentNode.removeLast();
return doc;
}
@Override
public Document visitKey(JsonParser.KeyContext ctx) {
final Element e = copyAttrs(
getRuleContextElement(ctx.getRuleIndex()),
ctx);
currentNode.addLast(e);
super.visitKey(ctx);
currentNode.removeLast();
return doc;
}
@Override
public Document visitValue(JsonParser.ValueContext ctx) {
final Element e = copyAttrs(
getRuleContextElement(ctx.getRuleIndex()),
ctx);
currentNode.addLast(e);
super.visitValue(ctx);
currentNode.removeLast();
return doc;
}
@Override
public Document visitPair(JsonParser.PairContext ctx) {
final Element e = copyAttrs(
getRuleContextElement(ctx.getRuleIndex()),
ctx);
currentNode.addLast(e);
super.visitPair(ctx);
currentNode.removeLast();
return doc;
}
@Override
public Document visitTerminal(TerminalNode node) {
if (node.getSymbol().getType() != Token.EOF) {
copyAttrs(
getTerminalNodeElement(node),
node);
}
super.visitTerminal(node);
return doc;
}
@NonNull
public static String stringify(@NonNull final Document doc) throws IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
XMLUtil.write(doc, out, "UTF-8"); //NOI18N
return new String(out.toByteArray(), StandardCharsets.UTF_8);
}
private static Element copyAttrs(
@NonNull final Element e,
@NonNull final ParserRuleContext ctx) {
e.setAttribute("start", Integer.toString(ctx.start.getStartIndex())); //NOI18N
e.setAttribute("stop", Integer.toString(ctx.stop.getStopIndex())); //NOI18N
return e;
}
private static Element copyAttrs(
@NonNull final Element e,
@NonNull final TerminalNode ctx) {
e.setAttribute("start", Integer.toString(ctx.getSymbol().getStartIndex())); //NOI18N
e.setAttribute("stop", Integer.toString(ctx.getSymbol().getStopIndex())); //NOI18N
e.setAttribute("text", ctx.getSymbol().getText()); //NOI18N
return e;
}
@NonNull
private Element getRuleContextElement(final int ruleIndex) {
return getParseTreeElement(parser.getRuleNames()[ruleIndex]);
}
@NonNull
private Element getTerminalNodeElement(@NonNull final TerminalNode node) {
return getParseTreeElement(lexer.getVocabulary().getSymbolicName(
node.getSymbol().getType()));
}
@NonNull
private Element getParseTreeElement(@NonNull final String name) {
if (!currentNode.isEmpty()) {
Element parent = currentNode.peekLast();
Element me = doc.createElement(name);
parent.appendChild(me);
return me;
} else if (doc != null) {
Element parent = doc.getDocumentElement();
Element me = doc.createElement(name);
parent.appendChild(me);
return me;
} else {
doc = XMLUtil.createDocument(name, null, null, null);
return doc.getDocumentElement();
}
}
}