<type>xml</type>
<classifier>features</classifier>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>odl-yangtools-xpath</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>odlext-parser-support</artifactId>
<artifactId>rfc8528-parser-support</artifactId>
</dependency>
+ <!-- XPath reference implementation -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-xpath-impl</artifactId>
+ </dependency>
+
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-xpath-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.rfc7950.namespace;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+
+/**
+ * Implementation-internal cache for looking up URI to import prefix. URIs are taken in as Strings to save ourselves
+ * some quality parsing time.
+ */
+@Beta
+public interface ModuleQNameToPrefix extends IdentifierNamespace<QNameModule, String> {
+ NamespaceBehaviour<QNameModule, String, @NonNull ModuleQNameToPrefix> BEHAVIOUR =
+ NamespaceBehaviour.rootStatementLocal(ModuleQNameToPrefix.class);
+}
/**
* Implementation-internal cache for looking up URI to import prefix. URIs are taken in as Strings to save ourselves
* some quality parsing time.
+ *
+ * @deprecated Use {@link ModuleQNameToPrefix} instead.
*/
+@Deprecated
@Beta
public interface URIStringToImportPrefix extends IdentifierNamespace<String, String> {
NamespaceBehaviour<String, String, @NonNull URIStringToImportPrefix> BEHAVIOUR =
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.parser.openconfig.stmt.OpenConfigVersionSupport;
import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ChildSchemaNodeNamespace;
+import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ModuleQNameToPrefix;
import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.URIStringToImportPrefix;
import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.action.ActionStatementSupport;
import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.anydata.AnydataStatementSupport;
.addSupport(IncludedSubmoduleNameToModuleCtx.BEHAVIOUR)
.addSupport(ImportPrefixToModuleCtx.BEHAVIOUR)
.addSupport(BelongsToPrefixToModuleCtx.BEHAVIOUR)
+ .addSupport(ModuleQNameToPrefix.BEHAVIOUR)
.addSupport(URIStringToImportPrefix.BEHAVIOUR)
.addSupport(BelongsToModuleContext.BEHAVIOUR)
.addSupport(QNameToStatementDefinition.BEHAVIOUR)
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
-import static org.opendaylight.yangtools.yang.common.YangConstants.RFC6020_YANG_NAMESPACE_STRING;
-import static org.opendaylight.yangtools.yang.common.YangConstants.YANG_XPATH_FUNCTIONS_PREFIX;
-
import com.google.common.annotations.Beta;
import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableBiMap;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
import org.checkerframework.checker.regex.qual.Regex;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.YangVersion;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.stmt.UnresolvedNumber;
-import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.slf4j.LoggerFactory;
/**
- * Utility class for dealing with arguments encountered by StatementSupport classes. Note that using this class may
- * result in thread-local state getting attached. To clean up this state, please invoke
- * {@link #detachFromCurrentThread()} when appropriate.
+ * Utility class for dealing with arguments encountered by StatementSupport classes.
*/
@Beta
public final class ArgumentUtils {
private static final Logger LOG = LoggerFactory.getLogger(ArgumentUtils.class);
- @Regex
- private static final String YANG_XPATH_FUNCTIONS_STRING =
- "(re-match|deref|derived-from(-or-self)?|enum-value|bit-is-set)([ \t\r\n]*)(\\()";
- private static final Pattern YANG_XPATH_FUNCTIONS_PATTERN = Pattern.compile(YANG_XPATH_FUNCTIONS_STRING);
-
@Regex
private static final String PATH_ABS_STR = "/[^/].*";
private static final Pattern PATH_ABS = Pattern.compile(PATH_ABS_STR);
private static final Splitter SLASH_SPLITTER = Splitter.on('/').omitEmptyStrings().trimResults();
- // XPathFactory is not thread-safe, rather than locking around a shared instance, we use a thread-local one.
- private static final ThreadLocal<XPathFactory> XPATH_FACTORY = new ThreadLocal<>() {
- @Override
- protected XPathFactory initialValue() {
- return XPathFactory.newInstance();
- }
- };
-
// these objects are to compare whether range has MAX or MIN value
// none of these values should appear as Yang number according to spec so they are safe to use
private static final BigDecimal YANG_MIN_NUM = BigDecimal.valueOf(-Double.MAX_VALUE);
}
public static RevisionAwareXPath parseXPath(final StmtContext<?, ?, ?> ctx, final String path) {
- final XPath xPath = XPATH_FACTORY.get().newXPath();
- xPath.setNamespaceContext(StmtNamespaceContext.create(ctx,
- ImmutableBiMap.of(RFC6020_YANG_NAMESPACE_STRING, YANG_XPATH_FUNCTIONS_PREFIX)));
-
- final String trimmed = trimSingleLastSlashFromXPath(path);
- try {
- // XPath extension functions have to be prefixed
- // yang-specific XPath functions are in fact extended functions, therefore we have to add
- // "yang" prefix to them so that they can be properly validated with the XPath.compile() method
- // the "yang" prefix is bound to RFC6020 YANG namespace
- final String prefixedXPath = addPrefixToYangXPathFunctions(trimmed, ctx);
- // TODO: we could capture the result and expose its 'evaluate' method
- xPath.compile(prefixedXPath);
- } catch (final XPathExpressionException e) {
- LOG.warn("Argument \"{}\" is not valid XPath string at \"{}\"", path, ctx.getStatementSourceReference(), e);
- }
-
- return new RevisionAwareXPathImpl(path, isAbsoluteXPath(path));
+ return XPathSupport.parseXPath(ctx, path);
}
public static boolean isAbsoluteXPath(final String path) {
return SchemaNodeIdentifier.create(qNames, PATH_ABS.matcher(path).matches());
}
- /**
- * Cleanup any resources attached to the current thread. Threads interacting with this class can cause thread-local
- * caches to them. Invoke this method if you want to detach those resources.
- */
- public static void detachFromCurrentThread() {
- XPATH_FACTORY.remove();
- }
-
- private static String addPrefixToYangXPathFunctions(final String path, final StmtContext<?, ?, ?> ctx) {
- if (ctx.getRootVersion() == YangVersion.VERSION_1_1) {
- final StringBuilder result = new StringBuilder();
- final String prefix = YANG_XPATH_FUNCTIONS_PREFIX + ":";
- final Matcher matcher = YANG_XPATH_FUNCTIONS_PATTERN.matcher(path);
- while (matcher.find()) {
- matcher.appendReplacement(result, prefix + matcher.group());
- }
-
- matcher.appendTail(result);
- return result.toString();
- }
-
- return path;
- }
-
private static String trimSingleLastSlashFromXPath(final String path) {
return path.endsWith("/") ? path.substring(0, path.length() - 1) : path;
}
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.Iterators;
-import java.util.Iterator;
+import java.util.Optional;
import javax.xml.namespace.NamespaceContext;
import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.URIStringToImportPrefix;
+import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
+import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ModuleQNameToPrefix;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
* A {@link NamespaceContext} implementation based on the set of imports and local module namespace.
*/
// TODO: this is a useful utility, so it may be useful to expose it either in this package, or yang.parser.spi.source.
-final class StmtNamespaceContext implements NamespaceContext {
- private final StmtContext<?, ?, ?> ctx;
- private final ImmutableBiMap<String, String> uriToPrefix;
-
- private String localNamespaceURI;
+final class StmtNamespaceContext implements YangNamespaceContext {
+ // FIXME: add serialization barrier
+ private static final long serialVersionUID = 1L;
- private StmtNamespaceContext(final StmtContext<?, ?, ?> ctx) {
- this(ctx, ImmutableBiMap.of());
- }
+ private final StmtContext<?, ?, ?> ctx;
- private StmtNamespaceContext(final StmtContext<?, ?, ?> ctx, final BiMap<String, String> uriToPrefix) {
+ StmtNamespaceContext(final StmtContext<?, ?, ?> ctx) {
this.ctx = requireNonNull(ctx);
- this.uriToPrefix = ImmutableBiMap.copyOf(uriToPrefix);
- }
-
- public static NamespaceContext create(final StmtContext<?, ?, ?> ctx) {
- return new StmtNamespaceContext(ctx);
- }
-
- public static NamespaceContext create(final StmtContext<?, ?, ?> ctx, final BiMap<String, String> uriToPrefix) {
- return new StmtNamespaceContext(ctx, uriToPrefix);
- }
-
- private String localNamespaceURI() {
- if (localNamespaceURI == null) {
- localNamespaceURI = verifyNotNull(ctx.getPublicDefinition().getStatementName().getNamespace().toString(),
- "Local namespace URI not found in %s", ctx);
- }
- return localNamespaceURI;
}
@Override
- public String getNamespaceURI(final String prefix) {
- // API-mandated by NamespaceContext
- checkArgument(prefix != null);
-
- final String uri = uriToPrefix.inverse().get(prefix);
- if (uri != null) {
- return uri;
- }
-
- if (prefix.isEmpty()) {
- return localNamespaceURI();
- }
-
- final QNameModule module = StmtContextUtils.getModuleQNameByPrefix(ctx, prefix);
- return module == null ? null : module.getNamespace().toString();
- }
-
- @Override
- public String getPrefix(final String namespaceURI) {
- // API-mandated by NamespaceContext
- checkArgument(namespaceURI != null);
-
- final String prefix = uriToPrefix.get(namespaceURI);
- if (prefix != null) {
- return prefix;
- }
-
- if (localNamespaceURI().equals(namespaceURI)) {
- return "";
- }
- return ctx.getFromNamespace(URIStringToImportPrefix.class, namespaceURI);
+ public Optional<String> findPrefixForNamespace(final QNameModule namespace) {
+ return Optional.ofNullable(ctx.getFromNamespace(ModuleQNameToPrefix.class, namespace));
}
@Override
- public Iterator<String> getPrefixes(final String namespaceURI) {
- // Ensures underlying map remains constant
- return Iterators.unmodifiableIterator(Iterators.concat(
- ctx.getAllFromNamespace(URIStringToImportPrefix.class).values().iterator(),
- uriToPrefix.values().iterator()));
+ public Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
+ // TODO: perform caching?
+ return Optional.ofNullable(StmtContextUtils.getModuleQNameByPrefix(ctx, prefix));
}
}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.rfc7950.stmt;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.base.MoreObjects;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath.WithExpression;
+import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression.QualifiedBound;
+
+// TODO: disconnect from RevisionAwareXPathImpl
+// FIXME: absolute should not be needed: since the expression is qualified, we known how to interpret it
+// FIXME: originalString() is an escape hatch: everybody should operate of QualifiedBound
+@NonNullByDefault
+final class WithExpressionImpl extends RevisionAwareXPathImpl implements WithExpression {
+ private final QualifiedBound xpathExpression;
+
+ WithExpressionImpl(final String xpath, final boolean absolute, final QualifiedBound xpathExpression) {
+ super(xpath, absolute);
+ this.xpathExpression = requireNonNull(xpathExpression);
+ }
+
+ @Override
+ public QualifiedBound getXPathExpression() {
+ return xpathExpression;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("xpath", getOriginalString()).toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2019 PANTHEON.tech, s.r.o. 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.rfc7950.stmt;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+import javax.xml.xpath.XPathExpressionException;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathExpression.QualifiedBound;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParser;
+import org.opendaylight.yangtools.yang.xpath.api.YangXPathParserFactory;
+import org.slf4j.Logger;
+
+@NonNullByDefault
+abstract class XPathSupport {
+ private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(XPathSupport.class);
+
+ private static final XPathSupport INSTANCE;
+
+ static {
+ final Iterator<YangXPathParserFactory> it = ServiceLoader.load(YangXPathParserFactory.class).iterator();
+ if (!it.hasNext()) {
+ LOG.warn("Failed to find XPath parser factory, no XPath validation will be performed");
+ INSTANCE = new Noop();
+ } else {
+ INSTANCE = new XPathImpl(it.next());
+ }
+ }
+
+ static RevisionAwareXPath parseXPath(final StmtContext<?, ?, ?> ctx, final String xpath) {
+ return INSTANCE.parseXPath(xpath, ctx);
+ }
+
+ abstract RevisionAwareXPath parseXPath(String xpath, StmtContext<?, ?, ?> ctx);
+
+ private static final class Noop extends XPathSupport {
+ @Override
+ RevisionAwareXPath parseXPath(final String xpath, final StmtContext<?, ?, ?> ctx) {
+ return new RevisionAwareXPathImpl(xpath, ArgumentUtils.isAbsoluteXPath(xpath));
+ }
+ }
+
+ private static final class XPathImpl extends XPathSupport {
+ private final YangXPathParserFactory factory;
+
+ XPathImpl(final YangXPathParserFactory factory) {
+ this.factory = factory;
+ }
+
+ @Override
+ RevisionAwareXPath parseXPath(final String xpath, final StmtContext<?, ?, ?> ctx) {
+ final boolean isAbsolute = ArgumentUtils.isAbsoluteXPath(xpath);
+ final YangXPathParser.QualifiedBound parser = factory.newParser(new StmtNamespaceContext(ctx));
+ final QualifiedBound parsed;
+ try {
+ parsed = parser.parseExpression(xpath);
+ } catch (XPathExpressionException e) {
+ LOG.warn("Argument \"{}\" is not valid XPath string at \"{}\"", xpath,
+ ctx.getStatementSourceReference(), e);
+ return new RevisionAwareXPathImpl(xpath, isAbsolute);
+ }
+
+ if (ctx.getRootVersion().compareTo(parsed.getYangVersion()) < 0) {
+ LOG.warn("{} features required in {} context to parse expression '{}' [at {}]",
+ parsed.getYangVersion().getReference(), ctx.getRootVersion().getReference(), xpath,
+ ctx.getStatementSourceReference());
+ }
+ return new WithExpressionImpl(xpath, isAbsolute, parsed);
+ }
+ }
+}
import java.net.URI;
import java.util.Collection;
import java.util.Optional;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.Revision;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RevisionDateStatement;
import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ModuleQNameToPrefix;
import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.URIStringToImportPrefix;
import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
import org.opendaylight.yangtools.yang.parser.spi.source.ImportedModuleContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToSourceIdentifier;
final class RevisionImport {
public void apply(final InferenceContext ctx) {
final StmtContext<?, ?, ?> importedModule = imported.resolve(ctx);
+ final QNameModule mod = InferenceException.throwIfNull(stmt.getFromNamespace(
+ ModuleCtxToModuleQName.class, importedModule), stmt.getStatementSourceReference(),
+ "Failed to find module of %s", importedModule);
+
linkageTarget.resolve(ctx).addToNs(ImportedModuleContext.class,
stmt.getFromNamespace(ModuleCtxToSourceIdentifier.class, importedModule), importedModule);
final String impPrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
final URI modNs = firstAttributeOf(importedModule.declaredSubstatements(),
NamespaceStatement.class);
stmt.addToNs(ImportPrefixToModuleCtx.class, impPrefix, importedModule);
+ stmt.addToNs(ModuleQNameToPrefix.class, mod, impPrefix);
stmt.addToNs(URIStringToImportPrefix.class, modNs.toString(), impPrefix);
}
import java.util.Collection;
import java.util.Optional;
import org.opendaylight.yangtools.concepts.SemVer;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.NamespaceStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.PrefixStatement;
import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.ModuleQNameToPrefix;
import org.opendaylight.yangtools.yang.parser.rfc7950.namespace.URIStringToImportPrefix;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToSemVerSourceIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.source.ImportedModuleContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToSourceIdentifier;
final class SemanticVersionImport {
stmt.addToNs(ImportPrefixToModuleCtx.class, impPrefix, importedModule);
stmt.addToNs(ImportPrefixToSemVerSourceIdentifier.class, impPrefix, semVerModuleIdentifier);
+ final QNameModule mod = InferenceException.throwIfNull(stmt.getFromNamespace(
+ ModuleCtxToModuleQName.class, importedModule), stmt.getStatementSourceReference(),
+ "Failed to find module of %s", importedModule);
+
final URI modNs = firstAttributeOf(importedModule.declaredSubstatements(),
NamespaceStatement.class);
+ stmt.addToNs(ModuleQNameToPrefix.class, mod, impPrefix);
stmt.addToNs(URIStringToImportPrefix.class, modNs.toString(), impPrefix);
}
* 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.stmt.rfc7950;
+import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThat;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.junit.Test;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
public class Bug6878Test {
@Test
- @SuppressWarnings("checkstyle:regexpSinglelineJava")
public void testParsingXPathWithYang11Functions() throws Exception {
- final PrintStream stdout = System.out;
- final ByteArrayOutputStream output = new ByteArrayOutputStream();
- final String testLog;
-
- System.setOut(new PrintStream(output, true, "UTF-8"));
-
- final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6878/foo.yang");
- assertNotNull(schemaContext);
-
- testLog = output.toString();
+ final String testLog = parseAndcaptureLog("/rfc7950/bug6878/foo.yang");
assertFalse(testLog.contains("Could not find function: "));
- System.setOut(stdout);
}
@Test
- @SuppressWarnings("checkstyle:regexpSinglelineJava")
public void shouldLogInvalidYang10XPath() throws Exception {
- final PrintStream stdout = System.out;
- final ByteArrayOutputStream output = new ByteArrayOutputStream();
- final String testLog;
-
- System.setOut(new PrintStream(output, true, "UTF-8"));
-
- StmtTestUtils.parseYangSource("/rfc7950/bug6878/foo10-invalid.yang");
-
- testLog = output.toString();
- assertTrue(testLog.contains("Could not find function: re-match"));
- System.setOut(stdout);
+ final String testLog = parseAndcaptureLog("/rfc7950/bug6878/foo10-invalid.yang");
+ assertThat(testLog, containsString("RFC7950 features required in RFC6020 context to parse expression "));
}
@Test
- @SuppressWarnings("checkstyle:regexpSinglelineJava")
public void shouldLogInvalidYang10XPath2() throws Exception {
+ final String testLog = parseAndcaptureLog("/rfc7950/bug6878/foo10-invalid-2.yang");
+ assertThat(testLog, containsString("RFC7950 features required in RFC6020 context to parse expression "));
+ }
+
+ @SuppressWarnings("checkstyle:regexpSinglelineJava")
+ private static String parseAndcaptureLog(final String yangFile) throws Exception {
final PrintStream stdout = System.out;
final ByteArrayOutputStream output = new ByteArrayOutputStream();
- final String testLog;
-
- System.setOut(new PrintStream(output, true, "UTF-8"));
- StmtTestUtils.parseYangSource("/rfc7950/bug6878/foo10-invalid-2.yang");
+ try (PrintStream out = new PrintStream(output, true, "UTF-8")) {
+ System.setOut(out);
+ StmtTestUtils.parseYangSource(yangFile);
+ } finally {
+ System.setOut(stdout);
+ }
- testLog = output.toString();
- assertTrue(testLog.contains("Could not find function: deref"));
- System.setOut(stdout);
+ return output.toString();
}
}
package org.opendaylight.yangtools.yang.stmt;
+import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.Optional;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath.WithExpression;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.Status;
-import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
public class Bug5481Test {
@Test
assertTrue(dataChildByName2 instanceof LeafSchemaNode);
LeafSchemaNode extendedLeaf = (LeafSchemaNode) dataChildByName2;
- RevisionAwareXPath whenConditionExtendedLeaf = extendedLeaf.getWhenCondition().get();
-
- assertEquals(new RevisionAwareXPathImpl("module1:top = 'extended'", false), whenConditionExtendedLeaf);
assertEquals(Status.DEPRECATED, extendedLeaf.getStatus());
assertEquals(Optional.of("text"), extendedLeaf.getDescription());
assertEquals(Optional.of("ref"), extendedLeaf.getReference());
+
+ RevisionAwareXPath whenConditionExtendedLeaf = extendedLeaf.getWhenCondition().get();
+ assertFalse(whenConditionExtendedLeaf.isAbsolute());
+ assertThat(whenConditionExtendedLeaf, instanceOf(WithExpression.class));
+ assertEquals("module1:top = 'extended'", whenConditionExtendedLeaf.getOriginalString());
}
}
* 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.stmt;
+import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath.WithExpression;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.Status;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;
-import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
public class Bug5942Test {
@Test
assertEquals(Optional.of("uses description"), usesNode.getDescription());
assertEquals(Optional.of("uses reference"), usesNode.getReference());
assertEquals(Status.DEPRECATED, usesNode.getStatus());
- assertEquals(new RevisionAwareXPathImpl("0!=1", false), usesNode.getWhenCondition().get());
+
+ final RevisionAwareXPath when = usesNode.getWhenCondition().get();
+ assertFalse(when.isAbsolute());
+ assertThat(when, instanceOf(WithExpression.class));
+ assertEquals("0!=1", when.getOriginalString());
final List<UnknownSchemaNode> unknownSchemaNodes = usesNode.getUnknownSchemaNodes();
assertEquals(1, unknownSchemaNodes.size());