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.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
import org.opendaylight.yangtools.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator.ImportResolutionMode;
final YangParser parser = parserFactory.createParser(parserMode);
final List<YangTextSchemaSource> sourcesInProject = new ArrayList<>(yangFilesInProject.size());
- final List<Entry<YangTextSchemaSource, ASTSchemaSource>> parsed = yangFilesInProject.parallelStream()
+ final List<Entry<YangTextSchemaSource, IRSchemaSource>> parsed = yangFilesInProject.parallelStream()
.map(file -> {
final YangTextSchemaSource textSource = YangTextSchemaSource.forFile(file);
try {
return new SimpleImmutableEntry<>(textSource,
- TextToASTTransformer.transformText(textSource));
- } catch (YangSyntaxErrorException | SchemaSourceException | IOException e) {
+ TextToIRTransformer.transformText(textSource));
+ } catch (YangSyntaxErrorException | IOException e) {
throw new IllegalArgumentException("Failed to parse " + file, e);
}
})
.collect(Collectors.toList());
- for (final Entry<YangTextSchemaSource, ASTSchemaSource> entry : parsed) {
+ for (final Entry<YangTextSchemaSource, IRSchemaSource> entry : parsed) {
final YangTextSchemaSource textSource = entry.getKey();
- final ASTSchemaSource astSource = entry.getValue();
+ final IRSchemaSource astSource = entry.getValue();
parser.addSource(astSource);
if (!astSource.getIdentifier().equals(textSource.getIdentifier())) {
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.ir.IRSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YinStatementStreamSource;
final class YangParserImpl implements YangParser {
private static final @NonNull Collection<Class<? extends SchemaSourceRepresentation>> REPRESENTATIONS =
- ImmutableList.of(ASTSchemaSource.class, YangTextSchemaSource.class,
+ ImmutableList.of(IRSchemaSource.class, ASTSchemaSource.class, YangTextSchemaSource.class,
YinDomSchemaSource.class, YinXmlSchemaSource.class, YinTextSchemaSource.class);
private final BuildAction buildAction;
private static StatementStreamSource sourceToStatementStream(final SchemaSourceRepresentation source)
throws IOException, YangSyntaxErrorException {
requireNonNull(source);
- if (source instanceof ASTSchemaSource) {
+ if (source instanceof IRSchemaSource) {
+ return YangStatementStreamSource.create((IRSchemaSource) source);
+ } else if (source instanceof ASTSchemaSource) {
return YangStatementStreamSource.create((ASTSchemaSource) source);
} else if (source instanceof YangTextSchemaSource) {
return YangStatementStreamSource.create((YangTextSchemaSource) source);
import java.util.concurrent.ExecutionException;
import org.eclipse.jdt.annotation.NonNull;
import org.gaul.modernizer_maven_annotations.SuppressModernizer;
+import org.opendaylight.yangtools.concepts.SemVer;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.parser.api.YangParser;
import org.opendaylight.yangtools.yang.model.parser.api.YangParserException;
import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
+import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangModelDependencyInfo;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
import org.slf4j.Logger;
private @NonNull ListenableFuture<EffectiveModelContext> createSchemaContext(
final Collection<SourceIdentifier> requiredSources,
final Cache<Collection<SourceIdentifier>, EffectiveModelContext> cache,
- final AsyncFunction<List<ASTSchemaSource>, EffectiveModelContext> assembleSources) {
+ final AsyncFunction<List<IRSchemaSource>, EffectiveModelContext> assembleSources) {
// Make sources unique
final List<SourceIdentifier> uniqueSourceIdentifiers = deDuplicateSources(requiredSources);
}
// Request all sources be loaded
- ListenableFuture<List<ASTSchemaSource>> sf = Futures.allAsList(Collections2.transform(uniqueSourceIdentifiers,
+ ListenableFuture<List<IRSchemaSource>> sf = Futures.allAsList(Collections2.transform(uniqueSourceIdentifiers,
this::requestSource));
// Detect mismatch between requested Source IDs and IDs that are extracted from parsed source
return rf;
}
- private ListenableFuture<ASTSchemaSource> requestSource(final @NonNull SourceIdentifier identifier) {
- return repository.getSchemaSource(identifier, ASTSchemaSource.class);
+ private ListenableFuture<IRSchemaSource> requestSource(final @NonNull SourceIdentifier identifier) {
+ return repository.getSchemaSource(identifier, IRSchemaSource.class);
}
/**
}
@SuppressModernizer
- private static final class SourceIdMismatchDetector implements Function<List<ASTSchemaSource>,
- List<ASTSchemaSource>> {
+ private static final class SourceIdMismatchDetector implements Function<List<IRSchemaSource>,
+ List<IRSchemaSource>> {
private final List<SourceIdentifier> sourceIdentifiers;
SourceIdMismatchDetector(final List<SourceIdentifier> sourceIdentifiers) {
}
@Override
- public List<ASTSchemaSource> apply(final List<ASTSchemaSource> input) {
- final Map<SourceIdentifier, ASTSchemaSource> filtered = new LinkedHashMap<>();
+ public List<IRSchemaSource> apply(final List<IRSchemaSource> input) {
+ final Map<SourceIdentifier, IRSchemaSource> filtered = new LinkedHashMap<>();
for (int i = 0; i < input.size(); i++) {
final SourceIdentifier expectedSId = sourceIdentifiers.get(i);
- final ASTSchemaSource astSchemaSource = input.get(i);
- final SourceIdentifier realSId = astSchemaSource.getIdentifier();
+ final IRSchemaSource irSchemaSource = input.get(i);
+ final SourceIdentifier realSId = irSchemaSource.getIdentifier();
if (!expectedSId.equals(realSId)) {
LOG.warn("Source identifier mismatch for module \"{}\", requested as {} but actually is {}. "
LOG.warn("Duplicate source for module {} detected in reactor", realSId);
}
- filtered.put(realSId, astSchemaSource);
+ filtered.put(realSId, irSchemaSource);
}
return ImmutableList.copyOf(filtered.values());
}
}
- private static final class AssembleSources implements AsyncFunction<List<ASTSchemaSource>, EffectiveModelContext> {
+ private static final class AssembleSources implements AsyncFunction<List<IRSchemaSource>, EffectiveModelContext> {
private final @NonNull YangParserFactory parserFactory;
private final @NonNull SchemaContextFactoryConfiguration config;
- private final @NonNull Function<ASTSchemaSource, SourceIdentifier> getIdentifier;
+ private final @NonNull Function<IRSchemaSource, SourceIdentifier> getIdentifier;
private AssembleSources(final @NonNull YangParserFactory parserFactory,
final @NonNull SchemaContextFactoryConfiguration config) {
this.config = config;
switch (config.getStatementParserMode()) {
case SEMVER_MODE:
- this.getIdentifier = ASTSchemaSource::getSemVerIdentifier;
+ this.getIdentifier = AssembleSources::getSemVerIdentifier;
break;
default:
- this.getIdentifier = ASTSchemaSource::getIdentifier;
+ this.getIdentifier = IRSchemaSource::getIdentifier;
}
}
@Override
- public FluentFuture<EffectiveModelContext> apply(final List<ASTSchemaSource> sources)
+ public FluentFuture<EffectiveModelContext> apply(final List<IRSchemaSource> sources)
throws SchemaResolutionException, ReactorException {
- final Map<SourceIdentifier, ASTSchemaSource> srcs = Maps.uniqueIndex(sources, getIdentifier);
+ final Map<SourceIdentifier, IRSchemaSource> srcs = Maps.uniqueIndex(sources, getIdentifier);
final Map<SourceIdentifier, YangModelDependencyInfo> deps =
- Maps.transformValues(srcs, ASTSchemaSource::getDependencyInformation);
+ Maps.transformValues(srcs, YangModelDependencyInfo::forIR);
LOG.debug("Resolving dependency reactor {}", deps);
config.getSupportedFeatures().ifPresent(parser::setSupportedFeatures);
config.getModulesDeviatedByModules().ifPresent(parser::setModulesWithSupportedDeviations);
- for (final Entry<SourceIdentifier, ASTSchemaSource> entry : srcs.entrySet()) {
- final ASTSchemaSource ast = entry.getValue();
+ for (final Entry<SourceIdentifier, IRSchemaSource> entry : srcs.entrySet()) {
try {
- parser.addSource(ast);
+ parser.addSource(entry.getValue());
} catch (YangSyntaxErrorException | IOException e) {
throw new SchemaResolutionException("Failed to add source " + entry.getKey(), e);
}
return immediateFluentFuture(schemaContext);
}
+
+ private static SemVerSourceIdentifier getSemVerIdentifier(final IRSchemaSource source) {
+ final SourceIdentifier identifier = source.getIdentifier();
+ final SemVer semver = YangModelDependencyInfo.findSemanticVersion(source.getRootStatement(), identifier);
+ if (identifier instanceof SemVerSourceIdentifier && semver == null) {
+ return (SemVerSourceIdentifier) identifier;
+ }
+
+ return SemVerSourceIdentifier.create(identifier.getName(), identifier.getRevision(), semver);
+ }
}
}
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
import org.opendaylight.yangtools.yang.model.repo.util.InMemorySchemaSourceCache;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final Multimap<SourceIdentifier, YangTextSchemaSource> texts = ArrayListMultimap.create();
private final AtomicReference<Optional<EffectiveModelContext>> currentSchemaContext =
new AtomicReference<>(Optional.empty());
- private final InMemorySchemaSourceCache<ASTSchemaSource> cache;
+ private final InMemorySchemaSourceCache<IRSchemaSource> cache;
private final SchemaListenerRegistration transReg;
private final SchemaSourceRegistry registry;
private final SchemaRepository repository;
this.repository = requireNonNull(repository);
this.registry = requireNonNull(registry);
- final TextToASTTransformer t = TextToASTTransformer.create(repository, registry);
+ final TextToIRTransformer t = TextToIRTransformer.create(repository, registry);
transReg = registry.registerSchemaSourceListener(t);
- cache = InMemorySchemaSourceCache.createSoftCache(registry, ASTSchemaSource.class, SOURCE_LIFETIME_SECONDS,
+ cache = InMemorySchemaSourceCache.createSoftCache(registry, IRSchemaSource.class, SOURCE_LIFETIME_SECONDS,
TimeUnit.SECONDS);
}
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
public class MultipleRevImportBug6875Test {
private static final String BAR_NS = "bar";
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
"shared-schema-repo-multiple-rev-import-test");
- final SettableSchemaProvider<ASTSchemaSource> foo = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> foo = getSourceProvider(
"/rfc7950/bug6875/yang1-1/foo.yang");
- final SettableSchemaProvider<ASTSchemaSource> bar1 = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> bar1 = getSourceProvider(
"/rfc7950/bug6875/yang1-1/bar@1999-01-01.yang");
- final SettableSchemaProvider<ASTSchemaSource> bar2 = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> bar2 = getSourceProvider(
"/rfc7950/bug6875/yang1-1/bar@2017-02-06.yang");
- final SettableSchemaProvider<ASTSchemaSource> bar3 = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> bar3 = getSourceProvider(
"/rfc7950/bug6875/yang1-1/bar@1970-01-01.yang");
setAndRegister(sharedSchemaRepository, foo);
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
"shared-schema-repo-multiple-rev-import-test");
- final SettableSchemaProvider<ASTSchemaSource> foo = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> foo = getSourceProvider(
"/rfc7950/bug6875/yang1-0/foo.yang");
- final SettableSchemaProvider<ASTSchemaSource> bar1 = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> bar1 = getSourceProvider(
"/rfc7950/bug6875/yang1-0/bar@1999-01-01.yang");
- final SettableSchemaProvider<ASTSchemaSource> bar2 = getSourceProvider(
+ final SettableSchemaProvider<IRSchemaSource> bar2 = getSourceProvider(
"/rfc7950/bug6875/yang1-0/bar@2017-02-06.yang");
setAndRegister(sharedSchemaRepository, foo);
}
private static void setAndRegister(final SharedSchemaRepository sharedSchemaRepository,
- final SettableSchemaProvider<ASTSchemaSource> source) {
+ final SettableSchemaProvider<IRSchemaSource> source) {
source.register(sharedSchemaRepository);
source.setResult();
}
- private static SettableSchemaProvider<ASTSchemaSource> getSourceProvider(final String resourceName)
+ private static SettableSchemaProvider<IRSchemaSource> getSourceProvider(final String resourceName)
throws Exception {
final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
- return SettableSchemaProvider.createImmediate(TextToASTTransformer.transformText(yangSource),
- ASTSchemaSource.class);
+ return SettableSchemaProvider.createImmediate(TextToIRTransformer.transformText(yangSource),
+ IRSchemaSource.class);
}
private static SchemaNode findNode(final SchemaContext context, final Iterable<QName> qnames) {
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
public class OpenconfigVerSharedSchemaRepositoryTest {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
"openconfig-ver-shared-schema-repo-test");
- final SettableSchemaProvider<ASTSchemaSource> bar = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> bar = getImmediateYangSourceProviderFromResource(
"/openconfig-version/openconfigver-shared-schema-repository/bar@2016-01-01.yang");
bar.register(sharedSchemaRepository);
bar.setResult();
- final SettableSchemaProvider<ASTSchemaSource> foo = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> foo = getImmediateYangSourceProviderFromResource(
"/openconfig-version/openconfigver-shared-schema-repository/foo.yang");
foo.register(sharedSchemaRepository);
foo.setResult();
- final SettableSchemaProvider<ASTSchemaSource> semVer = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> semVer = getImmediateYangSourceProviderFromResource(
"/openconfig-version/openconfigver-shared-schema-repository/openconfig-extensions.yang");
semVer.register(sharedSchemaRepository);
semVer.setResult();
public void testSharedSchemaRepository() throws Exception {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository("shared-schema-repo-test");
- final SettableSchemaProvider<ASTSchemaSource> bar = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> bar = getImmediateYangSourceProviderFromResource(
"/openconfig-version/shared-schema-repository/bar@2016-01-01.yang");
bar.register(sharedSchemaRepository);
bar.setResult();
- final SettableSchemaProvider<ASTSchemaSource> foo = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> foo = getImmediateYangSourceProviderFromResource(
"/openconfig-version/shared-schema-repository/foo.yang");
foo.register(sharedSchemaRepository);
foo.setResult();
- final SettableSchemaProvider<ASTSchemaSource> semVer = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> semVer = getImmediateYangSourceProviderFromResource(
"/openconfig-version/shared-schema-repository/openconfig-extensions.yang");
semVer.register(sharedSchemaRepository);
semVer.setResult();
assertEquals(moduleSize, schemaContext.getModules().size());
}
- static SettableSchemaProvider<ASTSchemaSource> getImmediateYangSourceProviderFromResource(final String resourceName)
+ static SettableSchemaProvider<IRSchemaSource> getImmediateYangSourceProviderFromResource(final String resourceName)
throws Exception {
final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
- return SettableSchemaProvider.createImmediate(TextToASTTransformer.transformText(yangSource),
- ASTSchemaSource.class);
+ return SettableSchemaProvider.createImmediate(TextToIRTransformer.transformText(yangSource),
+ IRSchemaSource.class);
}
}
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
public class SchemaContextFactoryDeviationsTest {
startsWith("Deviation must not target the same module as the one it is defined in"));
}
- private static SettableSchemaProvider<ASTSchemaSource> getImmediateYangSourceProviderFromResource(
+ private static SettableSchemaProvider<IRSchemaSource> getImmediateYangSourceProviderFromResource(
final String resourceName) throws Exception {
final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
- return SettableSchemaProvider.createImmediate(TextToASTTransformer.transformText(yangSource),
- ASTSchemaSource.class);
+ return SettableSchemaProvider.createImmediate(TextToIRTransformer.transformText(yangSource),
+ IRSchemaSource.class);
}
private static ListenableFuture<EffectiveModelContext> createSchemaContext(
final Collection<SourceIdentifier> requiredSources = new ArrayList<>();
for (final String resource : resources) {
- final SettableSchemaProvider<ASTSchemaSource> yangSource = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> yangSource = getImmediateYangSourceProviderFromResource(
resource);
yangSource.register(sharedSchemaRepository);
yangSource.setResult();
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class SharedSchemaContextFactoryTest {
s1 = RevisionSourceIdentifier.create("ietf-inet-types", Revision.of("2010-09-24"));
s2 = RevisionSourceIdentifier.create("iana-timezones", Revision.of("2012-07-09"));
- final TextToASTTransformer transformer = TextToASTTransformer.create(repository, repository);
+ final TextToIRTransformer transformer = TextToIRTransformer.create(repository, repository);
repository.registerSchemaSourceListener(transformer);
repository.registerSchemaSource(sourceIdentifier -> immediateFluentFuture(source1),
s1 = source1.getIdentifier();
s2 = source2.getIdentifier();
- final SettableSchemaProvider<ASTSchemaSource> provider =
+ final SettableSchemaProvider<IRSchemaSource> provider =
SharedSchemaRepositoryTest.getImmediateYangSourceProviderFromResource(
"/no-revision/imported@2012-12-12.yang");
provider.setResult();
// Register the same provider under source id without revision
final SourceIdentifier sIdWithoutRevision = RevisionSourceIdentifier.create(provider.getId().getName());
repository.registerSchemaSource(provider, PotentialSchemaSource.create(
- sIdWithoutRevision, ASTSchemaSource.class, PotentialSchemaSource.Costs.IMMEDIATE.getValue()));
+ sIdWithoutRevision, IRSchemaSource.class, PotentialSchemaSource.Costs.IMMEDIATE.getValue()));
final SharedSchemaContextFactory sharedSchemaContextFactory = new SharedSchemaContextFactory(repository,
config);
import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceListener;
import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
public class SharedSchemaRepositoryTest {
final SourceIdentifier id2 = loadAndRegisterSource(sharedSchemaRepository,
"/no-revision/imported@2012-12-12.yang");
- ListenableFuture<ASTSchemaSource> source = sharedSchemaRepository.getSchemaSource(idNoRevision,
- ASTSchemaSource.class);
+ ListenableFuture<IRSchemaSource> source = sharedSchemaRepository.getSchemaSource(idNoRevision,
+ IRSchemaSource.class);
assertEquals(idNoRevision, source.get().getIdentifier());
- source = sharedSchemaRepository.getSchemaSource(id2, ASTSchemaSource.class);
+ source = sharedSchemaRepository.getSchemaSource(id2, IRSchemaSource.class);
assertEquals(id2, source.get().getIdentifier());
}
private static SourceIdentifier loadAndRegisterSource(final SharedSchemaRepository sharedSchemaRepository,
final String resourceName) throws Exception {
- final SettableSchemaProvider<ASTSchemaSource> sourceProvider = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> sourceProvider = getImmediateYangSourceProviderFromResource(
resourceName);
sourceProvider.setResult();
final SourceIdentifier idNoRevision = sourceProvider.getId();
public void testSimpleSchemaContext() throws Exception {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
- final SettableSchemaProvider<ASTSchemaSource> remoteInetTypesYang = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> remoteInetTypesYang = getImmediateYangSourceProviderFromResource(
"/ietf/ietf-inet-types@2010-09-24.yang");
remoteInetTypesYang.register(sharedSchemaRepository);
- final ListenableFuture<ASTSchemaSource> registeredSourceFuture = sharedSchemaRepository.getSchemaSource(
- remoteInetTypesYang.getId(), ASTSchemaSource.class);
+ final ListenableFuture<IRSchemaSource> registeredSourceFuture = sharedSchemaRepository.getSchemaSource(
+ remoteInetTypesYang.getId(), IRSchemaSource.class);
assertFalse(registeredSourceFuture.isDone());
final EffectiveModelContextFactory fact = sharedSchemaRepository.createEffectiveModelContextFactory();
public void testTwoSchemaContextsSharingSource() throws Exception {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
- final SettableSchemaProvider<ASTSchemaSource> remoteInetTypesYang = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> remoteInetTypesYang = getImmediateYangSourceProviderFromResource(
"/ietf/ietf-inet-types@2010-09-24.yang");
remoteInetTypesYang.register(sharedSchemaRepository);
remoteInetTypesYang.setResult();
- final SettableSchemaProvider<ASTSchemaSource> remoteTopologyYang = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> remoteTopologyYang = getImmediateYangSourceProviderFromResource(
"/ietf/network-topology@2013-10-21.yang");
remoteTopologyYang.register(sharedSchemaRepository);
remoteTopologyYang.setResult();
- final SettableSchemaProvider<ASTSchemaSource> remoteModuleNoRevYang =
+ final SettableSchemaProvider<IRSchemaSource> remoteModuleNoRevYang =
getImmediateYangSourceProviderFromResource("/no-revision/module-without-revision.yang");
remoteModuleNoRevYang.register(sharedSchemaRepository);
public void testFailedSchemaContext() throws Exception {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
- final SettableSchemaProvider<ASTSchemaSource> remoteInetTypesYang = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> remoteInetTypesYang = getImmediateYangSourceProviderFromResource(
"/ietf/ietf-inet-types@2010-09-24.yang");
remoteInetTypesYang.register(sharedSchemaRepository);
public void testDifferentCosts() throws Exception {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository("netconf-mounts");
- final SettableSchemaProvider<ASTSchemaSource> immediateInetTypesYang = spy(
+ final SettableSchemaProvider<IRSchemaSource> immediateInetTypesYang = spy(
getImmediateYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang"));
immediateInetTypesYang.register(sharedSchemaRepository);
immediateInetTypesYang.setResult();
- final SettableSchemaProvider<ASTSchemaSource> remoteInetTypesYang = spy(
+ final SettableSchemaProvider<IRSchemaSource> remoteInetTypesYang = spy(
getRemoteYangSourceProviderFromResource("/ietf/ietf-inet-types@2010-09-24.yang"));
remoteInetTypesYang.register(sharedSchemaRepository);
remoteInetTypesYang.setResult();
}), PotentialSchemaSource.create(runningId, YangTextSchemaSource.class,
PotentialSchemaSource.Costs.REMOTE_IO.getValue()));
- final TextToASTTransformer transformer = TextToASTTransformer.create(sharedSchemaRepository,
+ final TextToIRTransformer transformer = TextToIRTransformer.create(sharedSchemaRepository,
sharedSchemaRepository);
sharedSchemaRepository.registerSchemaSourceListener(transformer);
assertEquals(moduleSize, schemaContext.getModules().size());
}
- static SettableSchemaProvider<ASTSchemaSource> getRemoteYangSourceProviderFromResource(final String resourceName)
+ static SettableSchemaProvider<IRSchemaSource> getRemoteYangSourceProviderFromResource(final String resourceName)
throws Exception {
final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
- return SettableSchemaProvider.createRemote(TextToASTTransformer.transformText(yangSource),
- ASTSchemaSource.class);
+ return SettableSchemaProvider.createRemote(TextToIRTransformer.transformText(yangSource),
+ IRSchemaSource.class);
}
- static SettableSchemaProvider<ASTSchemaSource> getImmediateYangSourceProviderFromResource(final String resourceName)
+ static SettableSchemaProvider<IRSchemaSource> getImmediateYangSourceProviderFromResource(final String resourceName)
throws Exception {
final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
- return SettableSchemaProvider.createImmediate(TextToASTTransformer.transformText(yangSource),
- ASTSchemaSource.class);
+ return SettableSchemaProvider.createImmediate(TextToIRTransformer.transformText(yangSource),
+ IRSchemaSource.class);
}
}
import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToIRTransformer;
public class SharedSchemaRepositoryWithFeaturesTest {
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
"shared-schema-repo-with-features-test");
- final SettableSchemaProvider<ASTSchemaSource> foobar = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> foobar = getImmediateYangSourceProviderFromResource(
"/if-feature-resolution-test/shared-schema-repository/foobar.yang");
foobar.register(sharedSchemaRepository);
foobar.setResult();
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
"shared-schema-repo-with-features-test");
- final SettableSchemaProvider<ASTSchemaSource> foobar = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> foobar = getImmediateYangSourceProviderFromResource(
"/if-feature-resolution-test/shared-schema-repository/foobar.yang");
foobar.register(sharedSchemaRepository);
foobar.setResult();
final SharedSchemaRepository sharedSchemaRepository = new SharedSchemaRepository(
"shared-schema-repo-with-features-test");
- final SettableSchemaProvider<ASTSchemaSource> foobar = getImmediateYangSourceProviderFromResource(
+ final SettableSchemaProvider<IRSchemaSource> foobar = getImmediateYangSourceProviderFromResource(
"/if-feature-resolution-test/shared-schema-repository/foobar.yang");
foobar.register(sharedSchemaRepository);
foobar.setResult();
assertNotNull(testLeafC);
}
- private static SettableSchemaProvider<ASTSchemaSource> getImmediateYangSourceProviderFromResource(
+ private static SettableSchemaProvider<IRSchemaSource> getImmediateYangSourceProviderFromResource(
final String resourceName) throws Exception {
final YangTextSchemaSource yangSource = YangTextSchemaSource.forResource(resourceName);
- return SettableSchemaProvider.createImmediate(TextToASTTransformer.transformText(yangSource),
- ASTSchemaSource.class);
+ return SettableSchemaProvider.createImmediate(TextToIRTransformer.transformText(yangSource),
+ IRSchemaSource.class);
}
private static void assertSchemaContext(final SchemaContext schemaContext, final int moduleSize) {
}
/**
- * Create an {@link IRStatement} from a parsed {@link StatementContext}.
+ * Create an {@link IRStatement} from a parsed {@link FileContext}.
*
* @param file ANTLR file context
* @return A new IRStatement
* @throws NullPointerException if {@code file} is null or it does not contain a root statement
*/
public static @NonNull IRStatement createStatement(final FileContext file) {
- return new AntlrSupport().createStatement(file.statement());
+ return createStatement(file.statement());
+ }
+
+ /**
+ * Create an {@link IRStatement} from a parsed {@link StatementContext}.
+ *
+ * @param stmt ANTLR statement context
+ * @return A new IRStatement
+ * @throws NullPointerException if {@code stmt} is null
+ */
+ public static @NonNull IRStatement createStatement(final StatementContext stmt) {
+ return new AntlrSupport().statementOf(stmt);
}
- private @NonNull IRStatement createStatement(final StatementContext stmt) {
+ private @NonNull IRStatement statementOf(final StatementContext stmt) {
final ParseTree firstChild = stmt.getChild(0);
verify(firstChild instanceof KeywordContext, "Unexpected shape of %s", stmt);
switch (statements.size()) {
case 0:
- return createStatement(keyword, argument, line, column);
+ return statementOf(keyword, argument, line, column);
case 1:
return new IRStatement144(keyword, argument, statements.get(0), line, column);
default:
}
}
- private static @NonNull IRStatement createStatement(final IRKeyword keyword, final IRArgument argument,
+ private static @NonNull IRStatement statementOf(final IRKeyword keyword, final IRArgument argument,
final int line, final int column) {
if (line >= 0 && column >= 0) {
if (line <= 65535 && column <= 65535) {
private ImmutableList<IRStatement> createStatements(final StatementContext stmt) {
final List<StatementContext> statements = stmt.statement();
return statements.isEmpty() ? ImmutableList.of()
- : statements.stream().map(this::createStatement).collect(ImmutableList.toImmutableList());
+ : statements.stream().map(this::statementOf).collect(ImmutableList.toImmutableList());
}
private String strOf(final ParseTree tree) {
}
@VisibleForTesting
- static String trimWhitespace(final String str, final int dquot) {
+ @Deprecated
+ public static String trimWhitespace(final String str, final int dquot) {
final int firstBrk = str.indexOf('\n');
if (firstBrk == -1) {
return str;
--- /dev/null
+/*
+ * Copyright (c) 2020 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.ir;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword.Unqualified;
+
+@Beta
+public final class IRSchemaSource extends AbstractIdentifiable<SourceIdentifier> implements SchemaSourceRepresentation {
+ private final @NonNull IRStatement rootStatement;
+ private final @Nullable String symbolicName;
+
+ public IRSchemaSource(final @NonNull SourceIdentifier identifier, final @NonNull IRStatement rootStatement,
+ @Nullable final String symbolicName) {
+ super(identifier);
+ this.rootStatement = requireNonNull(rootStatement);
+ this.symbolicName = symbolicName;
+
+ final IRKeyword rootKeyword = rootStatement.keyword();
+ checkArgument(rootKeyword instanceof Unqualified, "Root statement has invalid keyword %s", rootKeyword);
+ final String rootName = rootKeyword.identifier();
+ switch (rootName) {
+ case "module":
+ case "submodule":
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid root statement keyword " + rootName);
+ }
+
+ checkArgument(rootStatement.argument() != null, "Root statement does not have an argument");
+ }
+
+ public IRSchemaSource(final @NonNull SourceIdentifier identifier, final @NonNull IRStatement rootStatement) {
+ this(identifier, rootStatement, null);
+ }
+
+ @Override
+ public Optional<String> getSymbolicName() {
+ return Optional.ofNullable(symbolicName);
+ }
+
+ @Override
+ public Class<@NonNull IRSchemaSource> getType() {
+ return IRSchemaSource.class;
+ }
+
+ /**
+ * Return the root statement of this source.
+ *
+ * @return Root statement.
+ */
+ public @NonNull IRStatement getRootStatement() {
+ return rootStatement;
+ }
+}
import com.google.common.annotations.Beta;
import java.util.Optional;
+import org.antlr.v4.runtime.ParserRuleContext;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
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.ir.IRStatement;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.StatementContext;
/**
* Abstract Syntax Tree representation of a schema source. This representation is internal to the YANG parser
* basic semantic validation and we were able to extract dependency information.
*/
@Beta
+@Deprecated(forRemoval = true)
public final class ASTSchemaSource extends AbstractIdentifiable<SourceIdentifier>
implements SchemaSourceRepresentation {
+ private final @NonNull StatementContext tree;
+ private final @Nullable String symbolicName;
+
+ // FIXME: compute lazily
private final @NonNull YangModelDependencyInfo depInfo;
private final @NonNull SemVerSourceIdentifier semVerId;
- private final @NonNull IRStatement rootStatement;
- private final @Nullable String symbolicName;
private ASTSchemaSource(final @NonNull SourceIdentifier identifier, final @NonNull SemVerSourceIdentifier semVerId,
- final @NonNull IRStatement tree, final @NonNull YangModelDependencyInfo depInfo,
+ final @NonNull StatementContext tree, final @NonNull YangModelDependencyInfo depInfo,
@Nullable final String symbolicName) {
super(identifier);
this.depInfo = requireNonNull(depInfo);
- this.rootStatement = requireNonNull(tree);
+ this.tree = requireNonNull(tree);
this.semVerId = requireNonNull(semVerId);
this.symbolicName = symbolicName;
}
* if we fail to extract dependency information.
*/
static @NonNull ASTSchemaSource create(final @NonNull SourceIdentifier identifier,
- final @Nullable String symbolicName, final @NonNull IRStatement rootStatement)
+ final @Nullable String symbolicName, final @NonNull StatementContext tree)
throws YangSyntaxErrorException {
- final YangModelDependencyInfo depInfo = YangModelDependencyInfo.parseAST(rootStatement, identifier);
+ final YangModelDependencyInfo depInfo = YangModelDependencyInfo.parseAST(tree, identifier);
final SourceIdentifier id = getSourceId(depInfo);
final SemVerSourceIdentifier semVerId;
semVerId = getSemVerSourceId(depInfo);
}
- return new ASTSchemaSource(id, semVerId, rootStatement, depInfo, symbolicName);
+ return new ASTSchemaSource(id, semVerId, tree, depInfo, symbolicName);
}
@Override
}
/**
- * Return the root statement of this source.
+ * Return the underlying abstract syntax tree.
*
- * @return Root statement.
+ * @return Underlying AST.
*/
- public @NonNull IRStatement getRootStatement() {
- return rootStatement;
+ public @NonNull ParserRuleContext getAST() {
+ return tree;
+ }
+
+ @NonNull StatementContext tree() {
+ return tree;
}
/**
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
+import com.google.common.base.VerifyException;
import java.util.List;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.TerminalNode;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.ArgumentContext;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.UnquotedStringContext;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.AntlrSupport;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRArgument;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRArgument.Concatenation;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRArgument.Single;
return concatStrings(((Concatenation) argument).parts(), ref);
}
+ /*
+ * NOTE: this method we do not use convenience methods provided by generated parser code, but instead are making
+ * based on the grammar assumptions. While this is more verbose, it cuts out a number of unnecessary code,
+ * such as intermediate List allocation et al.
+ */
+ @Deprecated(forRemoval = true)
+ final @NonNull String stringFromStringContext(final ArgumentContext context, final StatementSourceReference ref) {
+ // Get first child, which we fully expect to exist and be a lexer token
+ final ParseTree firstChild = context.getChild(0);
+ if (firstChild instanceof TerminalNode) {
+ final Token token = ((TerminalNode) firstChild).getSymbol();
+ switch (token.getType()) {
+ case YangStatementParser.IDENTIFIER:
+ // Simplest of cases -- it is an IDENTIFIER, hence we do not need to validate anything else and can
+ // just grab the string and run with it.
+ return firstChild.getText();
+ case YangStatementParser.DQUOT_STRING:
+ case YangStatementParser.DQUOT_END:
+ case YangStatementParser.SQUOT_STRING:
+ case YangStatementParser.SQUOT_END:
+ // Quoted strings are potentially a pain, deal with them separately
+ return decodeQuoted(context, ref);
+ default:
+ throw new VerifyException("Unexpected token " + token);
+ }
+ }
+
+ verify(firstChild instanceof UnquotedStringContext, "Unexpected shape of %s", context);
+ // Simple case, just grab the text, as ANTLR has done all the heavy lifting
+ final String str = firstChild.getText();
+ checkUnquoted(str, ref);
+ return str;
+ }
+
+ @Deprecated
+ private @NonNull String decodeQuoted(final ArgumentContext context, final StatementSourceReference ref) {
+ if (context.getChildCount() > 2) {
+ // Potentially-complex case of string quoting, escaping and concatenation.
+ return concatStrings(context, ref);
+ }
+
+ // No concatenation needed, special-case
+ final ParseTree child = context.getChild(0);
+ verify(child instanceof TerminalNode, "Unexpected shape of %s", context);
+ final Token token = ((TerminalNode) child).getSymbol();
+ switch (token.getType()) {
+ case YangStatementParser.DQUOT_END:
+ case YangStatementParser.SQUOT_END:
+ // We are missing actual body, hence this is an empty string
+ return "";
+ case YangStatementParser.SQUOT_STRING:
+ return token.getText();
+ case YangStatementParser.DQUOT_STRING:
+ return normalizeDoubleQuoted(token, ref);
+ default:
+ throw new VerifyException("Unhandled token " + token);
+ }
+ }
+
private @NonNull String concatStrings(final List<? extends Single> parts, final StatementSourceReference ref) {
final StringBuilder sb = new StringBuilder();
for (Single part : parts) {
return sb.toString();
}
+ @Deprecated
+ private String concatStrings(final ArgumentContext context, final StatementSourceReference ref) {
+ final StringBuilder sb = new StringBuilder();
+ for (ParseTree child : context.children) {
+ verify(child instanceof TerminalNode, "Unexpected argument component %s", child);
+ final Token token = ((TerminalNode) child).getSymbol();
+ switch (token.getType()) {
+ case YangStatementParser.SEP:
+ // Separator, just skip it over
+ case YangStatementParser.PLUS:
+ // Operator, which we are handling by concat, skip it over
+ case YangStatementParser.DQUOT_END:
+ case YangStatementParser.SQUOT_END:
+ // Quote stops, skip them over because we either already added the content, or would be appending
+ // an empty string
+ break;
+ case YangStatementParser.SQUOT_STRING:
+ // Single-quoted string, append it as a literal
+ sb.append(token.getText());
+ break;
+ case YangStatementParser.DQUOT_STRING:
+ sb.append(normalizeDoubleQuoted(token, ref));
+ break;
+ default:
+ throw new VerifyException("Unexpected token " + token);
+ }
+ }
+ return sb.toString();
+ }
+
+ @Deprecated
+ private String normalizeDoubleQuoted(final Token token, final StatementSourceReference ref) {
+ // Whitespace normalization happens irrespective of further handling and has no effect on the result. Strictly
+ // speaking we should also have the previous token, which would be a DQUOT_START and get the position from it.
+ // Seeing as it is a single-character token let's just subtract one from this token to achieve the same result.
+ final String stripped = AntlrSupport.trimWhitespace(token.getText(), token.getCharPositionInLine() - 1);
+
+ // Now we need to perform some amount of unescaping. This serves as a pre-check before we dispatch
+ // validation and processing (which will reuse the work we have done)
+ final int backslash = stripped.indexOf('\\');
+ return backslash == -1 ? stripped : unescape(ref, stripped, backslash);
+ }
+
/*
* NOTE: Enforcement and transformation logic done by these methods should logically reside in the lexer and ANTLR
* account the for it with lexer modes. We do not want to force a re-lexing phase in the parser just because
package org.opendaylight.yangtools.yang.parser.rfc7950.repo;
import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import java.io.IOException;
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ErrorNode;
+import org.antlr.v4.runtime.tree.ParseTreeListener;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.antlr.v4.runtime.tree.TerminalNode;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
import org.opendaylight.yangtools.yang.model.repo.util.SchemaSourceTransformer;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.StatementContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A {@link SchemaSourceTransformer} which handles translation of models from
* {@link YangTextSchemaSource} representation into {@link ASTSchemaSource}.
+ *
+ * @deprecated Use {@link TextToIRTransformer} instead.
*/
@Beta
+@Deprecated(forRemoval = true)
public final class TextToASTTransformer extends SchemaSourceTransformer<YangTextSchemaSource, ASTSchemaSource> {
private static final Logger LOG = LoggerFactory.getLogger(TextToASTTransformer.class);
+ private static final ParseTreeListener MAKE_IMMUTABLE_LISTENER = new ParseTreeListener() {
+ @Override
+ public void enterEveryRule(final ParserRuleContext ctx) {
+ // No-op
+ }
+
+ @Override
+ public void exitEveryRule(final ParserRuleContext ctx) {
+ ctx.children = ctx.children == null ? ImmutableList.of() : ImmutableList.copyOf(ctx.children);
+ }
+
+ @Override
+ public void visitTerminal(final TerminalNode node) {
+ // No-op
+ }
+
+ @Override
+ public void visitErrorNode(final ErrorNode node) {
+ // No-op
+ }
+ };
+
private TextToASTTransformer(final SchemaRepository provider, final SchemaSourceRegistry consumer) {
super(provider, YangTextSchemaSource.class, consumer, ASTSchemaSource.class,
input -> Futures.immediateFuture(transformText(input)));
public static ASTSchemaSource transformText(final YangTextSchemaSource text) throws SchemaSourceException,
IOException, YangSyntaxErrorException {
- final YangStatementStreamSource src = YangStatementStreamSource.create(text);
+ final StatementContext stmt = YangStatementStreamSource.parseYangSource(text);
LOG.debug("Model {} parsed successfully", text);
+ // Walk the resulting tree and replace each children with an immutable list, lowering memory requirements
+ // and making sure the resulting tree will not get accidentally modified. An alternative would be to use
+ // org.antlr.v4.runtime.Parser.TrimToSizeListener, but that does not make the tree immutable.
+ ParseTreeWalker.DEFAULT.walk(MAKE_IMMUTABLE_LISTENER, stmt);
+
// TODO: missing validation (YangModelBasicValidationListener should be re-implemented to new parser)
- return ASTSchemaSource.create(text.getIdentifier(), text.getSymbolicName().orElse(null), src.rootStatement());
+ return ASTSchemaSource.create(text.getIdentifier(), text.getSymbolicName().orElse(null), stmt);
}
}
--- /dev/null
+/*
+ * Copyright (c) 2020 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.repo;
+
+import com.google.common.annotations.Beta;
+import com.google.common.util.concurrent.Futures;
+import java.io.IOException;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
+import org.opendaylight.yangtools.yang.model.repo.util.SchemaSourceTransformer;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.AntlrSupport;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
+
+@Beta
+public final class TextToIRTransformer extends SchemaSourceTransformer<YangTextSchemaSource, IRSchemaSource> {
+ private TextToIRTransformer(final SchemaRepository provider, final SchemaSourceRegistry consumer) {
+ super(provider, YangTextSchemaSource.class, consumer, IRSchemaSource.class,
+ input -> Futures.immediateFuture(transformText(input)));
+ }
+
+ public static @NonNull TextToIRTransformer create(final SchemaRepository provider,
+ final SchemaSourceRegistry consumer) {
+ return new TextToIRTransformer(provider, consumer);
+ }
+
+ public static @NonNull IRSchemaSource transformText(final YangTextSchemaSource text)
+ throws YangSyntaxErrorException, IOException {
+ final IRStatement rootStatement = AntlrSupport.createStatement(YangStatementStreamSource.parseYangSource(text));
+ final String name = YangModelDependencyInfo.safeStringArgument(text.getIdentifier(), rootStatement, "name");
+ final String latestRevision = YangModelDependencyInfo.getLatestRevision(rootStatement, text.getIdentifier());
+ final RevisionSourceIdentifier sourceId = latestRevision == null ? RevisionSourceIdentifier.create(name)
+ : RevisionSourceIdentifier.create(name, Revision.of(latestRevision));
+
+ return new IRSchemaSource(sourceId, rootStatement);
+ }
+}
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
+import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.ArgumentContext;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.StatementContext;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRArgument;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword.Unqualified;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
private static final String OPENCONFIG_VERSION = OpenConfigStatements.OPENCONFIG_VERSION.getStatementName()
.getLocalName();
+ @Deprecated
+ private static final Splitter COLON_SPLITTER = Splitter.on(":").omitEmptyStrings().trimResults();
private final String name;
private final Revision revision;
}
/**
- * Extracts {@link YangModelDependencyInfo} from an abstract syntax tree of a YANG model.
+ * Extracts {@link YangModelDependencyInfo} from an intermediate representation root statement of a YANG model.
+ *
+ * @param source Schema source
+ * @return {@link YangModelDependencyInfo}
+ * @throws IllegalArgumentException If the root statement is not a valid YANG module/submodule
+ */
+ public static @NonNull YangModelDependencyInfo forIR(final IRSchemaSource source) {
+ return forIR(source.getRootStatement(), source.getIdentifier());
+ }
+
+ /**
+ * Extracts {@link YangModelDependencyInfo} from an intermediate representation root statement of a YANG model.
*
* @param source Source identifier
* @param rootStatement root statement
* @return {@link YangModelDependencyInfo}
- * @throws IllegalArgumentException If the AST is not a valid YANG module/submodule
+ * @throws IllegalArgumentException If the root statement is not a valid YANG module/submodule
*/
- static @NonNull YangModelDependencyInfo parseAST(final IRStatement rootStatement,
+ static @NonNull YangModelDependencyInfo forIR(final IRStatement rootStatement,
final SourceIdentifier source) {
final IRKeyword keyword = rootStatement.keyword();
checkArgument(keyword instanceof Unqualified, "Invalid root statement %s", keyword);
throw new IllegalArgumentException("Root of parsed AST must be either module or submodule");
}
+ /**
+ * Extracts {@link YangModelDependencyInfo} from an abstract syntax tree of a YANG model.
+ *
+ * @param source Source identifier
+ * @param tree Abstract syntax tree
+ * @return {@link YangModelDependencyInfo}
+ * @throws IllegalArgumentException If the AST is not a valid YANG module/submodule
+ */
+ @Deprecated(forRemoval = true)
+ static @NonNull YangModelDependencyInfo parseAST(final StatementContext rootStatement,
+ final SourceIdentifier source) {
+ final String keyWordText = rootStatement.keyword().getText();
+ if (MODULE.equals(keyWordText)) {
+ return parseModuleContext(rootStatement, source);
+ }
+ if (SUBMODULE.equals(keyWordText)) {
+ return parseSubmoduleContext(rootStatement, source);
+ }
+ throw new IllegalArgumentException("Root of parsed AST must be either module or submodule");
+ }
+
/**
* Extracts {@link YangModelDependencyInfo} from input stream containing a YANG model. This parsing does not
* validate full YANG module, only parses header up to the revisions and imports.
throws IOException, YangSyntaxErrorException {
final YangStatementStreamSource source = YangStatementStreamSource.create(
YangTextSchemaSource.forResource(refClass, resourceName));
- return parseAST(source.rootStatement(), source.getIdentifier());
+ return forIR(source.rootStatement(), source.getIdentifier());
}
private static @NonNull YangModelDependencyInfo parseModuleContext(final IRStatement module,
return new ModuleDependencyInfo(name, latestRevision, imports, includes, semVer);
}
+ @Deprecated
+ private static @NonNull YangModelDependencyInfo parseModuleContext(final StatementContext module,
+ final SourceIdentifier source) {
+ final String name = safeStringArgument(source, module, "module name");
+ final String latestRevision = getLatestRevision(module, source);
+ final Optional<SemVer> semVer = Optional.ofNullable(findSemanticVersion(module, source));
+ final ImmutableSet<ModuleImport> imports = parseImports(module, source);
+ final ImmutableSet<ModuleImport> includes = parseIncludes(module, source);
+
+ return new ModuleDependencyInfo(name, latestRevision, imports, includes, semVer);
+ }
+
private static ImmutableSet<ModuleImport> parseImports(final IRStatement module,
final SourceIdentifier source) {
final Set<ModuleImport> result = new HashSet<>();
return ImmutableSet.copyOf(result);
}
- private static SemVer findSemanticVersion(final IRStatement statement, final SourceIdentifier source) {
+ @Deprecated
+ private static ImmutableSet<ModuleImport> parseImports(final StatementContext module,
+ final SourceIdentifier source) {
+ final Set<ModuleImport> result = new HashSet<>();
+ for (final StatementContext subStatementContext : module.statement()) {
+ if (IMPORT.equals(subStatementContext.keyword().getText())) {
+ final String importedModuleName = safeStringArgument(source, subStatementContext,
+ "imported module name");
+ final String revisionDateStr = getRevisionDateString(subStatementContext, source);
+ final Revision revisionDate = Revision.ofNullable(revisionDateStr).orElse(null);
+ final SemVer importSemVer = findSemanticVersion(subStatementContext, source);
+ result.add(new ModuleImportImpl(importedModuleName, revisionDate, importSemVer));
+ }
+ }
+ return ImmutableSet.copyOf(result);
+ }
+
+ @Beta
+ public static SemVer findSemanticVersion(final IRStatement statement, final SourceIdentifier source) {
String semVerString = null;
for (final IRStatement substatement : statement.statements()) {
// FIXME: this should also check we are using a prefix
return Strings.isNullOrEmpty(semVerString) ? null : SemVer.valueOf(semVerString);
}
+ @Deprecated
+ private static SemVer findSemanticVersion(final StatementContext statement, final SourceIdentifier source) {
+ String semVerString = null;
+ for (final StatementContext subStatement : statement.statement()) {
+ final String subStatementName = trimPrefix(subStatement.keyword().getText());
+ if (OPENCONFIG_VERSION.equals(subStatementName)) {
+ semVerString = safeStringArgument(source, subStatement, "version string");
+ break;
+ }
+ }
+
+ return Strings.isNullOrEmpty(semVerString) ? null : SemVer.valueOf(semVerString);
+ }
+
+ @Deprecated
+ private static String trimPrefix(final String identifier) {
+ final List<String> namesParts = COLON_SPLITTER.splitToList(identifier);
+ if (namesParts.size() == 2) {
+ return namesParts.get(1);
+ }
+ return identifier;
+ }
+
private static boolean isBuiltin(final IRStatement stmt, final String localName) {
final IRKeyword keyword = stmt.keyword();
return keyword instanceof Unqualified && localName.equals(keyword.identifier());
return ImmutableSet.copyOf(result);
}
+ @Deprecated
+ private static ImmutableSet<ModuleImport> parseIncludes(final StatementContext module,
+ final SourceIdentifier source) {
+ final Set<ModuleImport> result = new HashSet<>();
+ for (final StatementContext subStatementContext : module.statement()) {
+ if (INCLUDE.equals(subStatementContext.keyword().getText())) {
+ final String revisionDateStr = getRevisionDateString(subStatementContext, source);
+ final String IncludeModuleName = safeStringArgument(source, subStatementContext,
+ "included submodule name");
+ final Revision revisionDate = Revision.ofNullable(revisionDateStr).orElse(null);
+ result.add(new ModuleImportImpl(IncludeModuleName, revisionDate));
+ }
+ }
+ return ImmutableSet.copyOf(result);
+ }
+
private static String getRevisionDateString(final IRStatement importStatement, final SourceIdentifier source) {
String revisionDateStr = null;
for (final IRStatement substatement : importStatement.statements()) {
return revisionDateStr;
}
+ @Deprecated
+ private static String getRevisionDateString(final StatementContext importStatement, final SourceIdentifier source) {
+ String revisionDateStr = null;
+ for (final StatementContext importSubStatement : importStatement.statement()) {
+ if (REVISION_DATE.equals(importSubStatement.keyword().getText())) {
+ revisionDateStr = safeStringArgument(source, importSubStatement, "imported module revision-date");
+ }
+ }
+ return revisionDateStr;
+ }
+
public static String getLatestRevision(final IRStatement module, final SourceIdentifier source) {
String latestRevision = null;
for (final IRStatement substatement : module.statements()) {
return latestRevision;
}
+ @Deprecated
+ public static String getLatestRevision(final StatementContext module, final SourceIdentifier source) {
+ String latestRevision = null;
+ for (final StatementContext subStatementContext : module.statement()) {
+ if (REVISION.equals(subStatementContext.keyword().getText())) {
+ final String currentRevision = safeStringArgument(source, subStatementContext, "revision date");
+ if (latestRevision == null || latestRevision.compareTo(currentRevision) < 0) {
+ latestRevision = currentRevision;
+ }
+ }
+ }
+ return latestRevision;
+ }
+
private static @NonNull YangModelDependencyInfo parseSubmoduleContext(final IRStatement submodule,
final SourceIdentifier source) {
final String name = safeStringArgument(source, submodule, "submodule name");
return new SubmoduleDependencyInfo(name, latestRevision, belongsTo, imports, includes);
}
+ @Deprecated
+ private static @NonNull YangModelDependencyInfo parseSubmoduleContext(final StatementContext submodule,
+ final SourceIdentifier source) {
+ final String name = safeStringArgument(source, submodule, "submodule name");
+ final String belongsTo = parseBelongsTo(submodule, source);
+
+ final String latestRevision = getLatestRevision(submodule, source);
+ final ImmutableSet<ModuleImport> imports = parseImports(submodule, source);
+ final ImmutableSet<ModuleImport> includes = parseIncludes(submodule, source);
+
+ return new SubmoduleDependencyInfo(name, latestRevision, belongsTo, imports, includes);
+ }
+
private static String parseBelongsTo(final IRStatement submodule, final SourceIdentifier source) {
for (final IRStatement substatement : submodule.statements()) {
if (isBuiltin(substatement, BELONGS_TO)) {
return null;
}
- private static String safeStringArgument(final SourceIdentifier source, final IRStatement stmt, final String desc) {
+ @Deprecated
+ private static String parseBelongsTo(final StatementContext submodule, final SourceIdentifier source) {
+ for (final StatementContext subStatementContext : submodule.statement()) {
+ if (BELONGS_TO.equals(subStatementContext.keyword().getText())) {
+ return safeStringArgument(source, subStatementContext, "belongs-to module name");
+ }
+ }
+ return null;
+ }
+
+ static String safeStringArgument(final SourceIdentifier source, final IRStatement stmt, final String desc) {
final StatementSourceReference ref = getReference(source, stmt);
final IRArgument arg = stmt.argument();
checkArgument(arg != null, "Missing %s at %s", desc, ref);
return ArgumentContextUtils.rfc6020().stringFromStringContext(arg, ref);
}
+ @Deprecated
+ private static String safeStringArgument(final SourceIdentifier source, final StatementContext stmt,
+ final String desc) {
+ final StatementSourceReference ref = getReference(source, stmt);
+ final ArgumentContext arg = stmt.argument();
+ checkArgument(arg != null, "Missing %s at %s", desc, ref);
+ // TODO: we probably need to understand yang version first....
+ return ArgumentContextUtils.rfc6020().stringFromStringContext(arg, ref);
+ }
+
private static StatementSourceReference getReference(final SourceIdentifier source, final IRStatement stmt) {
return DeclarationInTextSource.atPosition(source.getName(), stmt.startLine(), stmt.startColumn());
}
+ @Deprecated
+ private static StatementSourceReference getReference(final SourceIdentifier source,
+ final StatementContext context) {
+ return DeclarationInTextSource.atPosition(source.getName(), context.getStart().getLine(),
+ context.getStart().getCharPositionInLine());
+ }
+
/**
* Dependency information for YANG module.
*/
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.repo;
+import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.Beta;
import org.opendaylight.yangtools.yang.parser.antlr.YangStatementLexer;
import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser;
import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.FileContext;
+import org.opendaylight.yangtools.yang.parser.antlr.YangStatementParser.StatementContext;
import org.opendaylight.yangtools.yang.parser.rfc7950.antlr.CompactYangStatementLexer;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.AntlrSupport;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRKeyword;
+import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRSchemaSource;
import org.opendaylight.yangtools.yang.parser.rfc7950.ir.IRStatement;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
*/
public static YangStatementStreamSource create(final YangTextSchemaSource source) throws IOException,
YangSyntaxErrorException {
- final IRStatement rootStatement;
- try (InputStream stream = source.openStream()) {
- rootStatement = parseYangSource(source.getIdentifier(), stream);
- }
-
- return new YangStatementStreamSource(source.getIdentifier(), rootStatement,
- source.getSymbolicName().orElse(null));
+ return new YangStatementStreamSource(source.getIdentifier(),
+ AntlrSupport.createStatement(parseYangSource(source)), source.getSymbolicName().orElse(null));
}
/**
*
* @param source YangTextSchemaSource, must not be null
* @return A new {@link YangStatementStreamSource}
+ * @throws NullPointerException if {@code source} is null
*/
public static YangStatementStreamSource create(final ASTSchemaSource source) {
+ return create(source.getIdentifier(), AntlrSupport.createStatement(source.tree()),
+ source.getSymbolicName().orElse(null));
+ }
+
+ /**
+ * Create a {@link YangStatementStreamSource} for a {@link IRSchemaSource}.
+ *
+ * @param source YangTextSchemaSource, must not be null
+ * @return A new {@link YangStatementStreamSource}
+ * @throws NullPointerException if {@code source} is null
+ */
+ public static YangStatementStreamSource create(final IRSchemaSource source) {
return create(source.getIdentifier(), source.getRootStatement(), source.getSymbolicName().orElse(null));
}
return rootStatement;
}
- private static IRStatement parseYangSource(final SourceIdentifier source, final InputStream stream)
+ static StatementContext parseYangSource(final YangTextSchemaSource source)
+ throws IOException, YangSyntaxErrorException {
+ try (InputStream stream = source.openStream()) {
+ return parseYangSource(source.getIdentifier(), stream);
+ }
+ }
+
+ private static StatementContext parseYangSource(final SourceIdentifier source, final InputStream stream)
throws IOException, YangSyntaxErrorException {
final YangStatementLexer lexer = new CompactYangStatementLexer(CharStreams.fromStream(stream));
final YangStatementParser parser = new YangStatementParser(new CommonTokenStream(lexer));
final FileContext result = parser.file();
errorListener.validate();
- return AntlrSupport.createStatement(result);
+ return verifyNotNull(result.statement());
}
}