From a39c0b5a72240f7f3e896157004359d4eb3cf1af Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Fri, 28 Oct 2016 14:42:04 +0200 Subject: [PATCH] BUG-7054: add YinStatementStreamSource This is a basic stream source, which traverses a DOM node and its children, emitting stream events. Change-Id: I536bd97c4b94a818cdf366b0028251f1100d9667 Signed-off-by: Robert Varga --- .../parser/impl/YinStatementParserImpl.java | 259 ------------------ .../repo/YinStatementStreamSource.java | 231 ++++++++++++++++ .../rfc6020/repo/YinTextToDomTransformer.java | 24 +- .../stmt/rfc6020/YinStatementSourceImpl.java | 146 +++++----- 4 files changed, 306 insertions(+), 354 deletions(-) delete mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YinStatementParserImpl.java create mode 100644 yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinStatementStreamSource.java diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YinStatementParserImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YinStatementParserImpl.java deleted file mode 100644 index d2631f6474..0000000000 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YinStatementParserImpl.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v1.0 which accompanies this distribution, - * and is available at http://www.eclipse.org/legal/epl-v10.html - */ - -package org.opendaylight.yangtools.yang.parser.impl; - -import com.google.common.base.Preconditions; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.common.YangConstants; -import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; -import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; -import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; -import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport; -import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource; -import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; -import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; -import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; -import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; -import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class YinStatementParserImpl { - - private static final Logger LOG = LoggerFactory.getLogger(YinStatementParserImpl.class); - - private final List toBeSkipped = new ArrayList<>(); - private final String sourceName; - private StatementWriter writer; - private QNameToStatementDefinition stmtDef; - private PrefixToModule prefixes; - private String uriStr; - private boolean isType = false; - private boolean action = true; - private boolean yinElement = false; - - public YinStatementParserImpl(final String sourceName) { - this.sourceName = Preconditions.checkNotNull(sourceName); - } - - /** - * - * This method is supposed to be called in pre-linkage phase, when YinStatementParserImpl instance has already been - * created. - * When done, start walking through YIN source - * - * @param writer - instance of StatementWriter to emit declared statements - * @param stmtDef - map of valid statement definitions for linkage phase - * - */ - public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef) { - this.writer = writer; - this.stmtDef = stmtDef; - } - - /** - * This method is supposed to be called in any phase but pre-linkage, when YinStatementParserImpl instance has already - * been created. - * When done, start walking through YIN source - * - * @param writer - instance of StatementWriter to emit declared statements - * @param stmtDef - map of valid statement definitions for any phase but linkage - * @param prefixes - map of valid prefixes for any phase but linkage - * - */ - public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) { - this.writer = writer; - this.stmtDef = stmtDef; - this.prefixes = prefixes; - } - - /** - * This method executes parsing YIN source and emitting declared statements via attached StatementWriter - * - * @param inputReader - instance of XMlStreamReader, allows forward, read-only access to XML. - */ - public void walk(final XMLStreamReader inputReader) { - try { - while (inputReader.hasNext()) { - inputReader.next(); - if (inputReader.hasName() && inputReader.getEventType() == XMLStreamConstants.START_ELEMENT) { - enterStatement(inputReader); - } - - if (inputReader.hasName() && inputReader.getEventType() == XMLStreamConstants.END_ELEMENT) { - exitStatement(inputReader); - } - } - } catch (XMLStreamException e) { - LOG.warn("Fatal error detecting the next state of XMLStreamReader", e); - } catch (URISyntaxException e) { - LOG.warn("Given string {} violates RFC2396", uriStr, e); - } - } - - private void startStatement(final QName identifier, final StatementSourceReference ref) { - writer.startStatement(identifier, ref); - } - - private void argumentValue(final XMLStreamReader inputReader, final StatementSourceReference ref, final QName identifier, final boolean - yinElement) { - if (yinElement) { - writeTextOnlyElement(inputReader, ref); - } else { - writeNormalizedAttributeValue(inputReader, identifier, ref); - } - } - - private void endStatement(final StatementSourceReference ref) { - writer.endStatement(ref); - } - - private void enterStatement(final XMLStreamReader inputReader) throws URISyntaxException { - final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, inputReader - .getLocation().getLineNumber(), inputReader.getLocation().getColumnNumber()); - uriStr = inputReader.getNamespaceURI(); - final QName identifier = new QName(new URI(uriStr), getElementFullName(inputReader)); - if (yinElement && toBeSkipped.isEmpty()) { - //at yin element, it has be read as argument - argumentValue(inputReader, ref, identifier, true); - } else { - if (isStatementWithYinElement(identifier, stmtDef)) { - //at statement with yin element, so next statement will be read as argument - yinElement = true; - } - - final QName validStatementDefinition = Utils.getValidStatementDefinition(prefixes, stmtDef, identifier); - - //main part -> valid statement for actual phase - if (stmtDef != null && validStatementDefinition != null && toBeSkipped.isEmpty()) { - if (identifier.equals(Rfc6020Mapping.TYPE.getStatementName())) { - isType = true; - } else { - startStatement(validStatementDefinition, ref); - if (isStatementWithYinElement(identifier, stmtDef)) { - action = false; - } - } - } else { - //if statement not found through all phases, throw exception - SourceException.throwIf(writer.getPhase().equals(ModelProcessingPhase.FULL_DECLARATION), ref, - "%s is not a YIN statement or use of extension.", identifier.getLocalName()); - - //otherwise skip it (statement not to be read yet) - action = false; - toBeSkipped.add(getElementFullName(inputReader)); - } - - if (isType) { - writeTypeStmtAndArg(inputReader, identifier, ref); - } else if (action & isStatementWithArgument(identifier, stmtDef)) { - argumentValue(inputReader, ref, identifier, false); - } else { - action = true; - } - } - } - - private void exitStatement(final XMLStreamReader inputReader) throws URISyntaxException { - final String statementName = getElementFullName(inputReader); - final QName identifier = new QName(new URI(inputReader.getNamespaceURI()), statementName); - final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, inputReader - .getLocation().getLineNumber(), inputReader.getLocation().getColumnNumber()); - final QName validStatementDefinition = Utils.getValidStatementDefinition(prefixes, stmtDef, identifier); - - if ((stmtDef != null && validStatementDefinition != null && toBeSkipped.isEmpty()) && !yinElement) { - endStatement(ref); - } - - //back to normal mode - if (yinElement) { - yinElement = false; - } - - if (toBeSkipped.contains(statementName)) { - toBeSkipped.remove(statementName); - } - } - - private void writeTextOnlyElement(final XMLStreamReader inputReader, final StatementSourceReference ref) { - try { - writer.argumentValue(inputReader.getElementText(), ref); - } catch (XMLStreamException e) { - LOG.warn("Current event is not a START_ELEMENT or a non text element is encountered ", ref, e); - } - } - - private void writeNormalizedAttributeValue(final XMLStreamReader inputReader, final QName - identifier, final StatementSourceReference ref) { - final String attributeValue = getAttributeValue(inputReader, identifier, stmtDef); - if (attributeValue != null) { - writer.argumentValue(attributeValue, ref); - } - } - - private void writeTypeStmtAndArg(final XMLStreamReader inputReader, final QName identifier, final StatementSourceReference ref) { - String argument = getAttributeValue(inputReader, identifier, stmtDef); - if (TypeUtils.isYangTypeBodyStmtString(argument)) { - startStatement(new QName(YangConstants.RFC6020_YIN_NAMESPACE, argument), ref); - } else { - startStatement(new QName(YangConstants.RFC6020_YIN_NAMESPACE, Rfc6020Mapping - .TYPE.getStatementName().getLocalName()), ref); - } - argumentValue(inputReader, ref, identifier, false); - isType = false; - } - - private static String getElementFullName(final XMLStreamReader inputReader) { - if (!inputReader.getPrefix().isEmpty()) { - return inputReader.getPrefix() + ":" + inputReader.getLocalName(); - } else { - return inputReader.getLocalName(); - } - } - - private boolean isStatementWithArgument(final QName identifier, final QNameToStatementDefinition stmtDef) { - StatementDefinition statementDefinition = getStatementDefinition(identifier, stmtDef); - if (statementDefinition == null) { - return false; - } else if (((StatementSupport) statementDefinition).getPublicView().getArgumentName() == null) { - return false; - } - return true; - } - - private boolean isStatementWithYinElement(final QName identifier, final QNameToStatementDefinition stmtDef) { - StatementDefinition statementDefinition = getStatementDefinition(identifier, stmtDef); - if (statementDefinition == null) { - return false; - } - return statementDefinition.isArgumentYinElement(); - } - - private String getAttributeValue(final XMLStreamReader inputReader, final QName identifier, final QNameToStatementDefinition - stmtDef) { - String namespace = null; - return inputReader.getAttributeValue(namespace, (((StatementSupport) getStatementDefinition(identifier, stmtDef)) - .getPublicView()).getArgumentName().getLocalName()); - } - - private StatementDefinition getStatementDefinition(final QName identifier, final QNameToStatementDefinition stmtDef) { - final QName trimPrefixIdentifier = Utils.trimPrefix(identifier); - return stmtDef.getByNamespaceAndLocalName(trimPrefixIdentifier.getNamespace(), - trimPrefixIdentifier.getLocalName()); - } -} \ No newline at end of file diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinStatementStreamSource.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinStatementStreamSource.java new file mode 100644 index 0000000000..3a6d46eadd --- /dev/null +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinStatementStreamSource.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.yangtools.yang.parser.rfc6020.repo; + +import static org.opendaylight.yangtools.yang.parser.rfc6020.repo.StatementSourceReferenceHandler.extractRef; + +import com.google.common.annotations.Beta; +import com.google.common.base.Preconditions; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import java.net.URI; +import java.net.URISyntaxException; +import javax.xml.transform.TransformerException; +import org.opendaylight.yangtools.concepts.Identifiable; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.YangConstants; +import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.api.YinDomSchemaSource; +import org.opendaylight.yangtools.yang.model.repo.api.YinXmlSchemaSource; +import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; +import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; +import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; +import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource; +import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Attr; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * A {@link StatementStreamSource} based on a {@link YinXmlSchemaSource}. Internal implementation works on top + * of {@link YinDomSchemaSource} and its DOM document. + * + * @author Robert Varga + */ +@Beta +public final class YinStatementStreamSource implements Identifiable, StatementStreamSource { + private static final Logger LOG = LoggerFactory.getLogger(YinStatementStreamSource.class); + private static final LoadingCache URI_CACHE = CacheBuilder.newBuilder().weakValues().build( + new CacheLoader() { + @Override + public URI load(final String key) throws URISyntaxException { + return new URI(key); + } + }); + private final SourceIdentifier identifier; + private final Node root; + + private YinStatementStreamSource(final SourceIdentifier identifier, final Node root) { + this.identifier = Preconditions.checkNotNull(identifier); + this.root = Preconditions.checkNotNull(root); + } + + public static StatementStreamSource create(final YinXmlSchemaSource source) throws TransformerException { + return create(YinDomSchemaSource.transform(source)); + } + + public static StatementStreamSource create(final YinDomSchemaSource source) { + return new YinStatementStreamSource(source.getIdentifier(), source.getSource().getNode()); + } + + @Override + public SourceIdentifier getIdentifier() { + return identifier; + } + + private static StatementDefinition getValidDefinition(final Node node, final StatementWriter writer, + final QNameToStatementDefinition stmtDef, final StatementSourceReference ref) { + final URI uri = URI_CACHE.getUnchecked(node.getNamespaceURI()); + final StatementDefinition def = stmtDef.getByNamespaceAndLocalName(uri, node.getLocalName()); + + if (def == null) { + SourceException.throwIf(writer.getPhase().equals(ModelProcessingPhase.FULL_DECLARATION), ref, + "%s is not a YIN statement or use of extension.", node.getLocalName()); + } + return def; + } + + private static void processAttribute(final Attr attr, final StatementWriter writer, + final QNameToStatementDefinition stmtDef, final StatementSourceReference ref) { + final StatementDefinition def = getValidDefinition(attr, writer, stmtDef, ref); + if (def == null) { + return; + } + + writer.startStatement(def.getStatementName(), ref); + final String value = attr.getValue(); + if (!value.isEmpty()) { + writer.argumentValue(value, ref); + } + writer.endStatement(ref); + } + + private static String getArgValue(final Element element, final QName argName, final boolean yinElement) { + if (yinElement) { + final NodeList children = element.getElementsByTagNameNS(argName.getNamespace().toString(), + argName.getLocalName()); + if (children.getLength() == 0) { + return null; + } + return children.item(0).getTextContent(); + } + + final Attr attr = element.getAttributeNode(argName.getLocalName()); + if (attr == null) { + return null; + } + + return attr.getValue(); + } + + private static void processElement(final Element element, final StatementWriter writer, + final QNameToStatementDefinition stmtDef) { + final StatementSourceReference ref = extractRef(element); + final StatementDefinition def = getValidDefinition(element, writer, stmtDef, ref); + if (def == null) { + LOG.debug("Skipping element {}", element); + return; + } + + final QName argName = def.getArgumentName(); + final String argValue; + final boolean allAttrs; + final boolean allElements; + if (argName != null) { + allAttrs = def.isArgumentYinElement(); + allElements = !allAttrs; + + argValue = getArgValue(element, argName, allAttrs); + SourceException.throwIfNull(argValue, ref, "Statement {} is missing mandatory argument %s", + def.getStatementName(), argName); + } else { + argValue = null; + allAttrs = false; + allElements = false; + } + + // FIXME: this is a hack + if (element.getLocalName().equals(Rfc6020Mapping.TYPE.getStatementName().getLocalName())) { + LOG.debug("Type statement encountered, arg {}", argValue); + Preconditions.checkArgument(argValue != null); + if (TypeUtils.isYangTypeBodyStmtString(argValue)) { + writer.startStatement(QName.create(YangConstants.RFC6020_YIN_MODULE, argValue), ref); + } else { + writer.startStatement(QName.create(YangConstants.RFC6020_YIN_MODULE, Rfc6020Mapping + .TYPE.getStatementName().getLocalName()), ref); + } + writer.argumentValue(argValue, ref); + } else { + writer.startStatement(def.getStatementName(), ref); + if (argValue != null) { + writer.argumentValue(argValue, ref); + } + } + + // First process any statements defined as attributes. We need to skip argument, if present + final NamedNodeMap attributes = element.getAttributes(); + if (attributes != null) { + for (int i = 0, len = attributes.getLength(); i < len; ++i) { + final Attr attr = (Attr) attributes.item(i); + if (allAttrs || !isArgument(argName, attr)) { + processAttribute(attr, writer, stmtDef, ref); + } + } + } + + // Now process child elements, if present + final NodeList children = element.getChildNodes(); + for (int i = 0, len = children.getLength(); i < len; ++i) { + final Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (allElements || !isArgument(argName, child)) { + processElement((Element) child, writer, stmtDef); + } + } + } + + writer.endStatement(ref); + } + + private static boolean isArgument(final QName argName, final Node node) { + return argName != null && argName.getLocalName().equals(node.getLocalName()) && node.getPrefix() == null; + } + + private void walkTree(final StatementWriter writer, final QNameToStatementDefinition stmtDef) { + final NodeList children = root.getChildNodes(); + for (int i = 0, len = children.getLength(); i < len; ++i) { + final Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + processElement((Element) child, writer, stmtDef); + } + } + } + + @Override + public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) { + walkTree(writer, stmtDef); + } + + @Override + public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef, + final PrefixToModule preLinkagePrefixes) { + walkTree(writer, stmtDef); + } + + @Override + public void writeLinkageAndStatementDefinitions(final StatementWriter writer, + final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) { + walkTree(writer, stmtDef); + } + + @Override + public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef, + final PrefixToModule prefixes) { + walkTree(writer, stmtDef); + } +} diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinTextToDomTransformer.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinTextToDomTransformer.java index e600f52399..95937d22f3 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinTextToDomTransformer.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/rfc6020/repo/YinTextToDomTransformer.java @@ -9,7 +9,6 @@ package org.opendaylight.yangtools.yang.parser.rfc6020.repo; import com.google.common.annotations.Beta; import com.google.common.util.concurrent.Futures; -import java.io.IOException; import javax.xml.parsers.SAXParser; import javax.xml.transform.dom.DOMSource; import org.opendaylight.yangtools.util.xml.UntrustedXML; @@ -19,7 +18,6 @@ import org.opendaylight.yangtools.yang.model.repo.api.YinTextSchemaSource; import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry; import org.opendaylight.yangtools.yang.model.repo.util.SchemaSourceTransformer; import org.w3c.dom.Document; -import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** @@ -30,21 +28,23 @@ import org.xml.sax.helpers.DefaultHandler; */ @Beta public final class YinTextToDomTransformer extends SchemaSourceTransformer { + + @Deprecated + public static final Transformation TRANSFORMATION = input -> { + final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); + final SAXParser parser = UntrustedXML.newSAXParser(); + final DefaultHandler handler = new StatementSourceReferenceHandler(doc, null); + parser.parse(input.openStream(), handler); + + return Futures.immediateCheckedFuture(YinDomSchemaSource.create(input.getIdentifier(), new DOMSource(doc))); + }; + private YinTextToDomTransformer(final SchemaRepository provider, final SchemaSourceRegistry consumer) { - super(provider, YinTextSchemaSource.class, consumer, YinDomSchemaSource.class, - input -> Futures.immediateCheckedFuture(parseDocument(input))); + super(provider, YinTextSchemaSource.class, consumer, YinDomSchemaSource.class, TRANSFORMATION); } public static YinTextToDomTransformer create(final SchemaRepository provider, final SchemaSourceRegistry consumer) { return new YinTextToDomTransformer(provider, consumer); } - private static YinDomSchemaSource parseDocument(final YinTextSchemaSource source) throws IOException, SAXException { - final Document doc = UntrustedXML.newDocumentBuilder().newDocument(); - final SAXParser parser = UntrustedXML.newSAXParser(); - final DefaultHandler handler = new StatementSourceReferenceHandler(doc, null); - parser.parse(source.openStream(), handler); - - return YinDomSchemaSource.create(source.getIdentifier(), new DOMSource(doc)); - } } diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YinStatementSourceImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YinStatementSourceImpl.java index 7a4fcdc60a..193dda5674 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YinStatementSourceImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/rfc6020/YinStatementSourceImpl.java @@ -8,124 +8,104 @@ package org.opendaylight.yangtools.yang.parser.stmt.rfc6020; -import com.google.common.base.Preconditions; +import com.google.common.base.Throwables; +import com.google.common.collect.ForwardingObject; +import com.google.common.io.ByteSource; import com.google.common.io.ByteStreams; -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; +import com.google.common.io.Files; import java.io.File; -import java.io.IOException; import java.io.InputStream; -import java.net.URISyntaxException; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import org.opendaylight.yangtools.yang.parser.impl.YinStatementParserImpl; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.api.YinDomSchemaSource; +import org.opendaylight.yangtools.yang.model.repo.api.YinTextSchemaSource; +import org.opendaylight.yangtools.yang.parser.rfc6020.repo.YinStatementStreamSource; +import org.opendaylight.yangtools.yang.parser.rfc6020.repo.YinTextToDomTransformer; import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource; import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter; -import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * * This class represents implementation of StatementStreamSource * in order to emit YIN statements using supplied StatementWriter * + * @deprecated Scheduled for removal. Use {@link YinStatementStreamSource} instead. */ -public class YinStatementSourceImpl implements StatementStreamSource { +@Deprecated +public final class YinStatementSourceImpl extends ForwardingObject implements StatementStreamSource { + private final StatementStreamSource delegate; - private static final Logger LOG = LoggerFactory.getLogger(YinStatementSourceImpl.class); - private static XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory(); + private YinStatementSourceImpl(final YinDomSchemaSource source) { + this.delegate = YinStatementStreamSource.create(source); + } - private YinStatementParserImpl yinStatementModelParser; - private XMLStreamReader streamReader; - private InputStream inputStream; - private String fileName; - private boolean isAbsolute; + @Override + public StatementStreamSource delegate() { + return delegate; + } - // FIXME IO exception: input stream closed when called from StmtTestUtils parserseYinSources method public YinStatementSourceImpl(final InputStream inputStream) { - yinStatementModelParser = new YinStatementParserImpl(inputStream.toString()); - this.inputStream = new BufferedInputStream(inputStream); - this.inputStream.mark(Integer.MAX_VALUE); + this(newStreamSource(inputStream)); } - public YinStatementSourceImpl(final String fileName, final boolean isAbsolute) { - yinStatementModelParser = new YinStatementParserImpl(fileName); - this.fileName = Preconditions.checkNotNull(fileName); - this.isAbsolute = isAbsolute; + private static YinDomSchemaSource newStreamSource(final InputStream inputStream) { + final SourceIdentifier id = YinTextSchemaSource.identifierFromFilename(inputStream.toString()); + + try { + final YinTextSchemaSource text = YinTextSchemaSource.delegateForByteSource(id, + ByteSource.wrap(ByteStreams.toByteArray(inputStream))); + return YinTextToDomTransformer.TRANSFORMATION.apply(text).get(); + } catch (Exception e) { + throw Throwables.propagate(e); + } } - @Override - public void writePreLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef) { - initializeReader(); - yinStatementModelParser.setAttributes(writer, stmtDef); - yinStatementModelParser.walk(streamReader); + private static YinDomSchemaSource newStreamSource(final String fileName, final boolean isAbsolute) { + try { + final File file; + if (isAbsolute) { + file = new File(fileName); + } else { + file = new File(YinStatementSourceImpl.class.getResource(fileName).toURI()); + } + + final YinTextSchemaSource text = YinTextSchemaSource.delegateForByteSource( + YinTextSchemaSource.identifierFromFilename(file.getName()), Files.asByteSource(file)); + + return YinTextToDomTransformer.TRANSFORMATION.apply(text).get(); + } catch (Exception e) { + throw Throwables.propagate(e); + } } - @Override - public void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef, final PrefixToModule preLinkagePrefixes) { - initializeReader(); - yinStatementModelParser.setAttributes(writer, stmtDef, preLinkagePrefixes); - yinStatementModelParser.walk(streamReader); + public YinStatementSourceImpl(final String fileName, final boolean isAbsolute) { + this(newStreamSource(fileName, isAbsolute)); } @Override - public void writeLinkageAndStatementDefinitions(StatementWriter writer, QNameToStatementDefinition stmtDef, - PrefixToModule prefixes) { - initializeReader(); - yinStatementModelParser.setAttributes(writer, stmtDef, prefixes); - yinStatementModelParser.walk(streamReader); + public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) { + delegate.writePreLinkage(writer, stmtDef); } @Override - public void writeFull(StatementWriter writer, QNameToStatementDefinition stmtDef, PrefixToModule prefixes) { - initializeReader(); - yinStatementModelParser.setAttributes(writer, stmtDef, prefixes); - yinStatementModelParser.walk(streamReader); - closeReader(); + public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef, + final PrefixToModule preLinkagePrefixes) { + delegate.writeLinkage(writer, stmtDef, preLinkagePrefixes); + } - private void initializeReader() { - try { - if (fileName != null) { - inputStream = loadFile(fileName, isAbsolute); - streamReader = xmlInputFactory.createXMLStreamReader(inputStream); - } else { - inputStream.reset(); - streamReader = xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(ByteStreams.toByteArray - (inputStream))); - } - } catch (XMLStreamException e) { - LOG.warn("Error while creating XMLStreamReader from input stream", e); - } catch (URISyntaxException e) { - LOG.warn("File name {} cannot be parsed as URI reference", fileName, e); - } catch (IOException e) { - LOG.warn("File {} cannot be found or read into string ", fileName, e); - } + @Override + public void writeLinkageAndStatementDefinitions(final StatementWriter writer, final QNameToStatementDefinition stmtDef, + final PrefixToModule prefixes) { + delegate.writeLinkageAndStatementDefinitions(writer, stmtDef, prefixes); } - private void closeReader() { - try { - inputStream.close(); - streamReader.close(); - } catch (XMLStreamException e) { - LOG.warn("Error occured while freeing associated resources", e); - } catch (IOException e) { - LOG.warn("I/O error occured during closing the input stream", e); - } + @Override + public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef, + final PrefixToModule prefixes) { + delegate().writeFull(writer, stmtDef, prefixes); } - private InputStream loadFile(final String fileName, boolean isAbsolute) throws URISyntaxException, IOException { - final File file; - if (isAbsolute) { - file = new File(fileName); - } else { - file = new File(getClass().getResource(fileName).toURI()); - } - return new NamedFileInputStream(file, fileName); - } } \ No newline at end of file -- 2.36.6