import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.ServiceLoader;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.parser.impl.DefaultReactors;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
-import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
final class SystemTestUtils {
private static final Pattern MODULE_PATTERN = Pattern.compile("module(.*?)\\{");
private static final Pattern WHITESPACES = Pattern.compile("\\s+");
+ private static final @NonNull YangParserFactory PARSER_FACTORY;
+
+ static {
+ final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
+ if (!it.hasNext()) {
+ throw new IllegalStateException("No YangParserFactory found");
+ }
+ PARSER_FACTORY = it.next();
+ }
private SystemTestUtils() {
throw new UnsupportedOperationException();
};
static SchemaContext parseYangSources(final List<String> yangLibDirs, final List<String> yangTestFiles,
- final Set<QName> supportedFeatures, final boolean recursiveSearch)
- throws ReactorException, IOException, YangSyntaxErrorException {
+ final Set<QName> supportedFeatures, final boolean recursiveSearch) throws IOException, YangParserException {
/*
* Current dir "." should be always present implicitly in the list of
* directories where dependencies are searched for
}
static SchemaContext parseYangSources(final Set<QName> supportedFeatures, final List<File> testFiles,
- final List<File> libFiles) throws ReactorException, IOException, YangSyntaxErrorException {
- final List<StatementStreamSource> testSources = getYangStatementSources(testFiles);
- final List<StatementStreamSource> libSources = getYangStatementSources(libFiles);
- return parseYangSources(testSources, libSources, supportedFeatures);
- }
-
- static SchemaContext parseYangSources(final List<StatementStreamSource> testSources,
- final List<StatementStreamSource> libSources, final Set<QName> supportedFeatures) throws ReactorException {
- Preconditions.checkArgument(testSources != null && !testSources.isEmpty(), "No yang sources");
-
- final BuildAction reactor = DefaultReactors.defaultReactor().newBuild()
- .addLibSources(libSources).addSources(testSources);
+ final List<File> libFiles) throws IOException, YangParserException {
+ Preconditions.checkArgument(!testFiles.isEmpty(), "No yang sources");
+ final YangParser parser = PARSER_FACTORY.createParser();
if (supportedFeatures != null) {
- reactor.setSupportedFeatures(supportedFeatures);
+ parser.setSupportedFeatures(supportedFeatures);
}
- return reactor.buildEffective();
+ for (File file : testFiles) {
+ parser.addSource(YangTextSchemaSource.forFile(file));
+ }
+ for (File file : libFiles) {
+ parser.addLibSource(YangTextSchemaSource.forFile(file));
+ }
+
+ return parser.buildSchemaContext();
}
private static File findInFiles(final List<File> libFiles, final String yangTestFile) throws IOException {
private static String getModelNameFromFile(final File file) throws IOException {
final String fileAsString = readFile(file.getAbsolutePath());
final Matcher matcher = MODULE_PATTERN.matcher(fileAsString);
- if (matcher.find()) {
- return matcher.group(1);
- } else {
- return "";
- }
+ return matcher.find() ? matcher.group(1) : "";
}
private static String readFile(final String path) throws IOException {
return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
}
- private static List<StatementStreamSource> getYangStatementSources(final List<File> yangFiles)
- throws IOException, YangSyntaxErrorException {
- final List<StatementStreamSource> yangSources = new ArrayList<>(yangFiles.size());
- for (final File file : yangFiles) {
- yangSources.add(YangStatementStreamSource.create(YangTextSchemaSource.forFile(file)));
- }
- return yangSources;
- }
-
private static Collection<File> getYangFiles(final String yangSourcesDirectoryPath, final boolean recursiveSearch)
throws FileNotFoundException {
final File testSourcesDir = new File(yangSourcesDirectoryPath);
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.model.parser.api;
+
+import com.google.common.annotations.Beta;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.NotThreadSafe;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+
+/**
+ * Configurable single-use YANG parser. Each instance can be configured to use a different set of models after
+ * which it is built. Models once added cannot be removed.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NotThreadSafe
+public interface YangParser {
+ /**
+ * Return enumeration of concrete types of {@link SchemaSourceRepresentation} parsers created from this factory
+ * support. Users can use this
+ *
+ * @return Enumeration of supported schema source representations.
+ */
+ Collection<Class<? extends SchemaSourceRepresentation>> supportedSourceRepresentations();
+
+ /**
+ * Return the set of all YANG statements semantically supported by this parser instance.
+ *
+ * @return Set of all YANG statements semantically supported by this parser instance.
+ */
+ Set<QName> supportedStatements();
+
+ /**
+ * Add main source. All main sources are present in resulting SchemaContext.
+ *
+ * @param source
+ * which should be added into main sources
+ * @throws YangSyntaxErrorException when one of the sources fails syntactic analysis
+ * @throws IOException when an IO error occurs
+ * @throws IllegalArgumentException if the representation is not supported
+ */
+ YangParser addSource(final SchemaSourceRepresentation source) throws IOException, YangSyntaxErrorException;
+
+ /**
+ * Add main sources. All main sources are present in resulting SchemaContext.
+ *
+ * @param sources
+ * which should be added into main sources
+ * @throws YangSyntaxErrorException when one of the sources fails syntactic analysis
+ * @throws IOException when an IO error occurs
+ * @throws IllegalArgumentException if the representation is not supported
+ */
+ default YangParser addSources(final SchemaSourceRepresentation... sources) throws IOException,
+ YangSyntaxErrorException {
+ for (SchemaSourceRepresentation source : sources) {
+ addSource(source);
+ }
+ return this;
+ }
+
+ default YangParser addSources(final Collection<? extends SchemaSourceRepresentation> sources) throws IOException,
+ YangSyntaxErrorException {
+ for (SchemaSourceRepresentation source : sources) {
+ addSource(source);
+ }
+ return this;
+ }
+
+ YangParser addLibSource(SchemaSourceRepresentation source) throws IOException, YangSyntaxErrorException;
+
+ /**
+ * Add library sources. Only library sources required by main sources are present in resulting SchemaContext.
+ * Any other library sources are ignored and this also applies to error reporting.
+ *
+ * <p>
+ * Note: Library sources are not supported in semantic version mode currently.
+ *
+ * @param sources
+ * YANG sources which should be added into library sources
+ * @throws YangSyntaxErrorException when one of the sources fails syntactic analysis
+ * @throws IOException when an IO error occurs
+ * @throws IllegalArgumentException if the representation is not supported
+ */
+ default YangParser addLibSources(final SchemaSourceRepresentation... sources) throws IOException,
+ YangSyntaxErrorException {
+ for (SchemaSourceRepresentation source : sources) {
+ addLibSource(source);
+ }
+ return this;
+ }
+
+ default YangParser addLibSources(final Collection<SchemaSourceRepresentation> sources) throws IOException,
+ YangSyntaxErrorException {
+ for (SchemaSourceRepresentation source : sources) {
+ addLibSource(source);
+ }
+ return this;
+ }
+
+ /**
+ * Set supported features based on which all if-feature statements in the
+ * parsed YANG modules will be resolved. If this method is not invoked, all features will be supported.
+ *
+ * @param supportedFeatures
+ * Set of supported features in the final SchemaContext.
+ * If the set is empty, no features encountered will be supported.
+ */
+ YangParser setSupportedFeatures(@Nonnull final Set<QName> supportedFeatures);
+
+ /**
+ * Set YANG modules which can be deviated by specified modules during the parsing process.
+ * Map key (QNameModule) denotes a module which can be deviated by the modules in the Map value.
+ *
+ * @param modulesDeviatedByModules
+ * Map of YANG modules (Map key) which can be deviated by specified modules (Map value) in the final
+ * SchemaContext. If the map is empty, no deviations encountered will be supported.
+ */
+ YangParser setModulesWithSupportedDeviations(
+ @Nonnull Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules);
+
+ /**
+ * Build the declared view of a combined view of declared statements.
+ *
+ * @return Ordered collection of declared statements from requested sources.
+ */
+ List<DeclaredStatement<?>> buildDeclaredModel() throws YangParserException;
+
+ /**
+ * Build effective {@link SchemaContext}
+ *
+ * @return An effective schema context comprised of configured models.
+ * @throws YangSyntaxErrorException When a syntactic error is encountered.
+ */
+ SchemaContext buildSchemaContext() throws YangParserException;
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.model.parser.api;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Base exception reported by {@link YangParser}. This is used as an exception of last resort, semantic reporting
+ * of individual errors is performed via subclasses, like {@link YangSyntaxErrorException}.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public class YangParserException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public YangParserException(final String message) {
+ super(requireNonNull(message));
+ }
+
+ public YangParserException(final String message, final Throwable cause) {
+ super(requireNonNull(message), cause);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.model.parser.api;
+
+import com.google.common.annotations.Beta;
+import java.util.Collection;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
+
+/**
+ * Basic entry point into a YANG parser implementation.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public interface YangParserFactory {
+ /**
+ * Return enumeration of {@link StatementParserMode}s supported by this factory.
+ *
+ * @return Enumeration of supported schema source representations.
+ */
+ Collection<StatementParserMode> supportedParserModes();
+
+ /**
+ * Create a {@link YangParser} instance operating in default import resolution mode.
+ *
+ * @return A new {@link YangParser} instance
+ */
+ default YangParser createParser() {
+ return createParser(StatementParserMode.DEFAULT_MODE);
+ }
+
+ /**
+ * Create a {@link YangParser} instance operating in specified import resolution mode.
+ *
+ * @param parserMode Requested parser mode, may not be null.
+ * @return A new {@link YangParser} instance
+ * @throws NullPointerException if parser mode is null
+ * @throws IllegalArgumentException if specified parser mode is not supported
+ */
+ YangParser createParser(StatementParserMode parserMode);
+}
*/
package org.opendaylight.yangtools.yang.model.parser.api;
-import static java.util.Objects.requireNonNull;
-
import java.util.Optional;
import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-public class YangSyntaxErrorException extends Exception {
+public class YangSyntaxErrorException extends YangParserException {
private static final long serialVersionUID = 2L;
private final SourceIdentifier source;
public YangSyntaxErrorException(@Nullable final SourceIdentifier source, final int line,
final int charPositionInLine, final String message, @Nullable final Throwable cause) {
- super(requireNonNull(message), cause);
+ super(message, cause);
this.source = source;
this.line = line;
this.charPositionInLine = charPositionInLine;
</dependencyManagement>
<dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>concepts</artifactId>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-common</artifactId>
<artifactId>rfc8040-parser-support</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.kohsuke.metainf-services</groupId>
+ <artifactId>metainf-services</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<artifactId>logback-classic</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>${project.groupId}</groupId>
- <artifactId>concepts</artifactId>
- </dependency>
</dependencies>
<build>
<extensions>true</extensions>
<configuration>
<instructions>
- <Export-Package>
- {local-packages},
- org.opendaylight.yangtools.yang.parser.impl.*,
- ;-split-package:=error
- </Export-Package>
+ <Include-Resource>{META-INF/services=${project.build.directory}/classes/META-INF/services}</Include-Resource>
+ <Bundle-Activator>org.opendaylight.yangtools.yang.parser.impl.osgi.Activator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
package org.opendaylight.yangtools.yang.parser.impl;
import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.odlext.parser.AnyxmlSchemaLocationNamespace;
import org.opendaylight.yangtools.odlext.parser.AnyxmlSchemaLocationStatementSupport;
import org.opendaylight.yangtools.odlext.parser.AnyxmlStatementSupportOverride;
*/
@Beta
public final class DefaultReactors {
- private static final CrossSourceStatementReactor DEFAULT_REACTOR = defaultReactorBuilder().build();
+ private static final @NonNull CrossSourceStatementReactor DEFAULT_REACTOR = defaultReactorBuilder().build();
private DefaultReactors() {
throw new UnsupportedOperationException();
/**
* Get a shared default-configured reactor instance. This instance is configured to handle both RFC6020 and RFC7950,
- * as well as RFC8040's yang-data extension.
+ * as well as
+ * <ul>
+ * <li>RFC6536's default-deny-{all,write} extensions</li>
+ * <li>RFC7952's annotation extension</li>
+ * <li>RFC8040's yang-data extension</li>
+ * <li>OpenConfig extensions</li>
+ * <li>OpenDaylight extensions</li>
+ * </ul>
*
* @return a shared default-configured reactor instance.
*/
- public static CrossSourceStatementReactor defaultReactor() {
+ public static @NonNull CrossSourceStatementReactor defaultReactor() {
return DEFAULT_REACTOR;
}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.impl;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import javax.annotation.concurrent.ThreadSafe;
+import org.eclipse.jdt.annotation.NonNull;
+import org.kohsuke.MetaInfServices;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
+import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+
+/**
+ * Reference {@link YangParserFactory} implementation.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@ThreadSafe
+@MetaInfServices
+public final class YangParserFactoryImpl implements YangParserFactory {
+ private static final Collection<StatementParserMode> SUPPORTED_MODES = ImmutableList.of(
+ StatementParserMode.DEFAULT_MODE, StatementParserMode.SEMVER_MODE);
+
+ private final CrossSourceStatementReactor reactor;
+
+ /**
+ * Construct a new {@link YangParserFactory} backed by {@link DefaultReactors#defaultReactor()}.
+ */
+ public YangParserFactoryImpl() {
+ this(DefaultReactors.defaultReactor());
+ }
+
+ /**
+ * Construct a new {@link YangParserFactory} backed by specified reactor.
+ *
+ * @param reactor Backing reactor
+ */
+ public YangParserFactoryImpl(@NonNull final CrossSourceStatementReactor reactor) {
+ this.reactor = requireNonNull(reactor);
+ }
+
+ @Override
+ public Collection<StatementParserMode> supportedParserModes() {
+ return SUPPORTED_MODES;
+ }
+
+ @Override
+ public YangParser createParser(final StatementParserMode parserMode) {
+ return new YangParserImpl(reactor.newBuild(parserMode));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.impl;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.transform.TransformerException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.api.YinDomSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.api.YinTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.api.YinXmlSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinStatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinTextToDomTransformer;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
+import org.xml.sax.SAXException;
+
+final class YangParserImpl implements YangParser {
+ private static final Collection<Class<? extends SchemaSourceRepresentation>> REPRESENTATIONS = ImmutableList.of(
+ YangTextSchemaSource.class, YinDomSchemaSource.class, YinXmlSchemaSource.class, YinTextSchemaSource.class);
+
+ private final BuildAction buildAction;
+
+ YangParserImpl(final BuildAction buildAction) {
+ this.buildAction = requireNonNull(buildAction);
+ }
+
+ @Override
+ public Collection<Class<? extends SchemaSourceRepresentation>> supportedSourceRepresentations() {
+ return REPRESENTATIONS;
+ }
+
+ @Override
+ public Set<QName> supportedStatements() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public YangParser addSource(final SchemaSourceRepresentation source) throws IOException, YangSyntaxErrorException {
+ buildAction.addSources(sourceToStatementStream(source));
+ return null;
+ }
+
+ @Override
+ public YangParser addLibSource(final SchemaSourceRepresentation source) throws IOException,
+ YangSyntaxErrorException {
+ buildAction.addLibSources(sourceToStatementStream(source));
+ return null;
+ }
+
+ @Override
+ public YangParser setSupportedFeatures(final Set<QName> supportedFeatures) {
+ buildAction.setSupportedFeatures(supportedFeatures);
+ return this;
+ }
+
+ @Override
+ public YangParser setModulesWithSupportedDeviations(
+ final Map<QNameModule, Set<QNameModule>> modulesDeviatedByModules) {
+ buildAction.setModulesWithSupportedDeviations(modulesDeviatedByModules);
+ return this;
+ }
+
+ @Override
+ public List<DeclaredStatement<?>> buildDeclaredModel() throws YangParserException {
+ try {
+ return buildAction.build().getRootStatements();
+ } catch (ReactorException e) {
+ throw decodeReactorException(e);
+ }
+ }
+
+ @Override
+ public SchemaContext buildSchemaContext() throws YangParserException {
+ try {
+ return buildAction.buildEffective();
+ } catch (ReactorException e) {
+ throw decodeReactorException(e);
+ }
+ }
+
+ private static YangParserException decodeReactorException(final ReactorException reported) {
+ // FIXME: map exception in some reasonable manner
+ return new YangParserException("Failed to assemble sources", reported);
+ }
+
+ private static StatementStreamSource sourceToStatementStream(final SchemaSourceRepresentation source)
+ throws IOException, YangSyntaxErrorException {
+ requireNonNull(source);
+ if (source instanceof YangTextSchemaSource) {
+ return YangStatementStreamSource.create((YangTextSchemaSource) source);
+ } else if (source instanceof YinDomSchemaSource) {
+ return YinStatementStreamSource.create((YinDomSchemaSource) source);
+ } else if (source instanceof YinTextSchemaSource) {
+ try {
+ return YinStatementStreamSource.create(YinTextToDomTransformer.transformSource(
+ (YinTextSchemaSource) source));
+ } catch (SAXException e) {
+ throw new YangSyntaxErrorException(source.getIdentifier(), 0, 0, "Failed to parse XML text", e);
+ }
+ } else if (source instanceof YinXmlSchemaSource) {
+ try {
+ return YinStatementStreamSource.create((YinXmlSchemaSource) source);
+ } catch (TransformerException e) {
+ throw new YangSyntaxErrorException(source.getIdentifier(), 0, 0,
+ "Failed to assemble in-memory representation", e);
+ }
+ } else {
+ throw new IllegalArgumentException("Unsupported source " + source);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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.impl.osgi;
+
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserFactoryImpl;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * YANG parser implementation activator. Publishes a {@link YangParserFactory} implementation on bundle start.
+ *
+ * @author Robert Varga
+ */
+public final class Activator implements BundleActivator {
+ private ServiceRegistration<@NonNull YangParserFactory> registration;
+
+ @Override
+ public void start(final BundleContext context) throws Exception {
+ registration = context.registerService(YangParserFactory.class, new YangParserFactoryImpl(), null);
+ }
+
+ @Override
+ public void stop(final BundleContext context) throws Exception {
+ if (registration != null) {
+ registration.unregister();
+ registration = null;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2017 Pantheon Technologies, 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
+ */
+/**
+ * OSGi-specific YANG parser code. Contains activators and similar.
+ */
+package org.opendaylight.yangtools.yang.parser.impl.osgi;
\ No newline at end of file
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import javax.annotation.Nonnull;
+import org.kohsuke.MetaInfServices;
import org.opendaylight.yangtools.concepts.Identifiable;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
* Note: for current implementation, "same" means the same filter and the same set of {@link SourceIdentifier}s.
*/
@Beta
+@MetaInfServices(value = SchemaRepository.class)
public final class SharedSchemaRepository extends AbstractSchemaRepository implements Identifiable<String> {
private final LoadingCache<SchemaSourceFilter, SchemaContextFactory> cache =
CacheBuilder.newBuilder().softValues().build(new CacheLoader<SchemaSourceFilter, SchemaContextFactory>() {
+++ /dev/null
-org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.concepts.Builder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.YangVersion;
}
@Override
- public CrossSourceStatementReactor build() {
+ public @NonNull CrossSourceStatementReactor build() {
final StatementSupportBundle initBundle = reactorSupportBundles.get(ModelProcessingPhase.INIT).build();
final StatementSupportBundle preLinkageBundle = reactorSupportBundles
.get(ModelProcessingPhase.SOURCE_PRE_LINKAGE).setParent(initBundle).build();
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.ServiceLoader;
import java.util.Set;
import java.util.stream.Collectors;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
+import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.parser.impl.DefaultReactors;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinStatementStreamSource;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
-import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
-import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.BuildAction;
/**
* Utility class which provides convenience methods for producing effective schema context based on the supplied
return name.endsWith(YangConstants.RFC6020_YANG_FILE_EXTENSION) && file.isFile();
};
+ private static final @NonNull YangParserFactory PARSER_FACTORY;
+
+ static {
+ final Iterator<@NonNull YangParserFactory> it = ServiceLoader.load(YangParserFactory.class).iterator();
+ if (!it.hasNext()) {
+ throw new IllegalStateException("No YangParserFactory found");
+ }
+ PARSER_FACTORY = it.next();
+ }
+
private YangParserTestUtils() {
throw new UnsupportedOperationException("Utility class should not be instantiated.");
}
*/
public static SchemaContext parseYangFiles(final Set<QName> supportedFeatures,
final StatementParserMode parserMode, final Collection<File> files) {
- return parseYangSources(supportedFeatures, parserMode,
+ return parseSources(parserMode, supportedFeatures,
files.stream().map(YangTextSchemaSource::forFile).collect(Collectors.toList()));
}
for (final String r : resources) {
sources.add(YangTextSchemaSource.forResource(clazz, r));
}
- return parseYangSources(null, StatementParserMode.DEFAULT_MODE, sources);
+ return parseSources(StatementParserMode.DEFAULT_MODE, null, sources);
}
/**
public static SchemaContext parseYangSources(final StatementParserMode parserMode,
final Set<QName> supportedFeatures, final YangTextSchemaSource... sources) {
- return parseYangSources(supportedFeatures, parserMode, Arrays.asList(sources));
+ return parseSources(parserMode, supportedFeatures, Arrays.asList(sources));
}
- public static SchemaContext parseYangSources(final Set<QName> supportedFeatures,
- final StatementParserMode parserMode, final Collection<? extends YangTextSchemaSource> sources) {
- final Collection<YangStatementStreamSource> streams = new ArrayList<>(sources.size());
- for (YangTextSchemaSource source : sources) {
- try {
- streams.add(YangStatementStreamSource.create(source));
- } catch (IOException e) {
- throw new IllegalArgumentException("Failed to read source " + source, e);
- } catch (YangSyntaxErrorException e) {
- throw new IllegalArgumentException("Malformed source " + source, e);
- }
+ public static SchemaContext parseSources(final StatementParserMode parserMode, final Set<QName> supportedFeatures,
+ final Collection<? extends SchemaSourceRepresentation> sources) {
+ final YangParser parser = PARSER_FACTORY.createParser(parserMode);
+ if (supportedFeatures != null) {
+ parser.setSupportedFeatures(supportedFeatures);
}
- return parseSources(supportedFeatures, parserMode, streams);
- }
-
- /**
- * Creates a new effective schema context containing the specified YIN sources. Statement parser mode is set to
- * default mode and all YANG features are supported.
- *
- * @param sources YIN sources to be parsed
- * @return effective schema context
- */
- public static SchemaContext parseYinSources(final YinStatementStreamSource... sources) {
- return parseYinSources(StatementParserMode.DEFAULT_MODE, sources);
- }
-
- /**
- * Creates a new effective schema context containing the specified YIN sources. Statement parser mode is set to
- * default mode.
- *
- * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YIN
- * models are resolved
- * @param sources YIN sources to be parsed
- *
- * @return effective schema context
- * @throws ReactorException if there is an error in one of the parsed YIN sources
- */
- public static SchemaContext parseYinSources(final Set<QName> supportedFeatures,
- final YinStatementStreamSource... sources) throws ReactorException {
- return parseSources(supportedFeatures, StatementParserMode.DEFAULT_MODE, sources);
- }
-
- /**
- * Creates a new effective schema context containing the specified YIN sources. All YANG features are supported.
- *
- * @param statementParserMode mode of statement parser
- * @param sources YIN sources to be parsed
- * @return effective schema context
- */
- public static SchemaContext parseYinSources(final StatementParserMode statementParserMode,
- final YinStatementStreamSource... sources) {
- return parseSources(null, statementParserMode, sources);
- }
-
- /**
- * Creates a new effective schema context containing the specified YANG sources.
- *
- * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
- * models are resolved
- * @param parserMode mode of statement parser
- * @param sources sources to be parsed
- *
- * @return effective schema context
- */
- public static SchemaContext parseSources(final Set<QName> supportedFeatures,
- final StatementParserMode parserMode, final StatementStreamSource... sources) {
- return parseSources(supportedFeatures, parserMode, Arrays.asList(sources));
- }
-
- /**
- * Creates a new effective schema context containing the specified YANG sources.
- *
- * @param supportedFeatures set of supported features based on which all if-feature statements in the parsed YANG
- * models are resolved
- * @param statementParserMode mode of statement parser
- * @param sources sources to be parsed
- *
- * @return effective schema context
- */
- public static SchemaContext parseSources(final Set<QName> supportedFeatures,
- final StatementParserMode statementParserMode, final Collection<? extends StatementStreamSource> sources) {
- final BuildAction reactor = DefaultReactors.defaultReactor().newBuild(statementParserMode);
- if (supportedFeatures != null) {
- reactor.setSupportedFeatures(supportedFeatures);
+ try {
+ parser.addSources(sources);
+ } catch (YangSyntaxErrorException e) {
+ throw new IllegalArgumentException("Malformed source", e);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Failed to read a source", e);
}
- reactor.addSources(sources);
try {
- return reactor.buildEffective();
- } catch (ReactorException e) {
- throw new IllegalStateException(e);
+ return parser.buildSchemaContext();
+ } catch (YangParserException e) {
+ throw new IllegalStateException("Failed to assemble SchemaContext", e);
}
}