X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Frepo%2FYangTextSchemaContextResolver.java;h=4f536abcf7f2edec97d31a804a1370cc05293027;hb=3310cd312a6419064b7a2850865e434970ba5a67;hp=00075b935876010d296b1d68194f4dfc387f5629;hpb=3680e198a70129fafa634eeb3fb49e8401fff010;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java index 00075b9358..4f536abcf7 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/YangTextSchemaContextResolver.java @@ -8,61 +8,62 @@ package org.opendaylight.yangtools.yang.parser.repo; import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; +import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture; +import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture; import com.google.common.annotations.Beta; -import com.google.common.base.MoreObjects.ToStringHelper; -import com.google.common.base.Preconditions; import com.google.common.base.Verify; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; -import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.FluentFuture; import com.google.common.util.concurrent.ListenableFuture; import java.io.IOException; -import java.io.InputStream; import java.net.URL; +import java.time.Duration; import java.util.Collection; import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; -import javax.annotation.Nonnull; +import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.yangtools.yang.common.Revision; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +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.EffectiveModelContextFactory; import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException; import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier; -import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory; +import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration; import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository; import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException; import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException; -import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceFilter; import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; import org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode; import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; +import org.opendaylight.yangtools.yang.model.repo.spi.GuavaSchemaSourceCache; import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource; import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs; import org.opendaylight.yangtools.yang.model.repo.spi.SchemaListenerRegistration; import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider; 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.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.slf4j.Logger; import org.slf4j.LoggerFactory; public final class YangTextSchemaContextResolver implements AutoCloseable, SchemaSourceProvider { private static final Logger LOG = LoggerFactory.getLogger(YangTextSchemaContextResolver.class); - private static final long SOURCE_LIFETIME_SECONDS = 60; + private static final Duration SOURCE_LIFETIME = Duration.ofSeconds(60); private final Collection requiredSources = new ConcurrentLinkedDeque<>(); private final Multimap texts = ArrayListMultimap.create(); - private final AtomicReference> currentSchemaContext = + private final AtomicReference> currentSchemaContext = new AtomicReference<>(Optional.empty()); - private final InMemorySchemaSourceCache cache; + private final GuavaSchemaSourceCache cache; private final SchemaListenerRegistration transReg; private final SchemaSourceRegistry registry; private final SchemaRepository repository; @@ -70,21 +71,25 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem private volatile Object contextVersion = version; private YangTextSchemaContextResolver(final SchemaRepository repository, final SchemaSourceRegistry registry) { - this.repository = Preconditions.checkNotNull(repository); - this.registry = Preconditions.checkNotNull(registry); + 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, - TimeUnit.SECONDS); + cache = GuavaSchemaSourceCache.createSoftCache(registry, IRSchemaSource.class, SOURCE_LIFETIME); } - public static YangTextSchemaContextResolver create(final String name) { + public static @NonNull YangTextSchemaContextResolver create(final String name) { final SharedSchemaRepository sharedRepo = new SharedSchemaRepository(name); return new YangTextSchemaContextResolver(sharedRepo, sharedRepo); } + public static @NonNull YangTextSchemaContextResolver create(final String name, final YangParserFactory factory) { + final SharedSchemaRepository sharedRepo = new SharedSchemaRepository(name, factory); + return new YangTextSchemaContextResolver(sharedRepo, sharedRepo); + } + /** * Register a {@link YangTextSchemaSource}. * @@ -94,11 +99,11 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem * @throws IOException when the URL is not readable * @throws SchemaSourceException When parsing encounters general error */ - public YangTextSchemaSourceRegistration registerSource(@Nonnull final YangTextSchemaSource source) + public @NonNull YangTextSchemaSourceRegistration registerSource(final @NonNull YangTextSchemaSource source) throws SchemaSourceException, IOException, YangSyntaxErrorException { checkArgument(source != null); - final ASTSchemaSource ast = TextToASTTransformer.transformText(source); + final IRSchemaSource ast = TextToIRTransformer.transformText(source); LOG.trace("Resolved source {} to source {}", source, ast); // AST carries an accurate identifier, check if it matches the one supplied by the source. If it @@ -163,30 +168,19 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem * @throws IOException when the URL is not readable * @throws SchemaSourceException When parsing encounters general error */ - public YangTextSchemaSourceRegistration registerSource(@Nonnull final URL url) throws SchemaSourceException, - IOException, YangSyntaxErrorException { + public @NonNull YangTextSchemaSourceRegistration registerSource(final @NonNull URL url) + throws SchemaSourceException, IOException, YangSyntaxErrorException { checkArgument(url != null, "Supplied URL must not be null"); final String path = url.getPath(); final String fileName = path.substring(path.lastIndexOf('/') + 1); - final SourceIdentifier guessedId = guessSourceIdentifier(fileName); - return registerSource(new YangTextSchemaSource(guessedId) { - @Override - public InputStream openStream() throws IOException { - return url.openStream(); - } - - @Override - protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) { - return toStringHelper.add("url", url); - } - }); + return registerSource(YangTextSchemaSource.forURL(url, guessSourceIdentifier(fileName))); } - private static SourceIdentifier guessSourceIdentifier(final String fileName) { + private static SourceIdentifier guessSourceIdentifier(final @NonNull String fileName) { try { return YangTextSchemaSource.identifierFromFilename(fileName); - } catch (IllegalArgumentException e) { + } catch (final IllegalArgumentException e) { LOG.warn("Invalid file name format in '{}'", fileName, e); return RevisionSourceIdentifier.create(fileName); } @@ -198,8 +192,8 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem * @return new schema context iif there is at least 1 yang file registered and * new schema context was successfully built. */ - public Optional getSchemaContext() { - return getSchemaContext(StatementParserMode.DEFAULT_MODE); + public Optional getEffectiveModelContext() { + return getEffectiveModelContext(StatementParserMode.DEFAULT_MODE); } /** @@ -209,9 +203,11 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem * @return new schema context iif there is at least 1 yang file registered and * new schema context was successfully built. */ - public Optional getSchemaContext(final StatementParserMode statementParserMode) { - final SchemaContextFactory factory = repository.createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT); - Optional sc; + public Optional getEffectiveModelContext( + final StatementParserMode statementParserMode) { + final EffectiveModelContextFactory factory = repository.createEffectiveModelContextFactory( + config(statementParserMode)); + Optional sc; Object ver; do { // Spin get stable context version @@ -232,13 +228,13 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem } while (ver != version); while (true) { - final ListenableFuture f = factory.createSchemaContext(sources, statementParserMode); + final ListenableFuture f = factory.createEffectiveModelContext(sources); try { sc = Optional.of(f.get()); break; - } catch (InterruptedException e) { - throw new RuntimeException("Interrupted while assembling schema context", e); - } catch (ExecutionException e) { + } catch (final InterruptedException e) { + throw new IllegalStateException("Interrupted while assembling schema context", e); + } catch (final ExecutionException e) { LOG.info("Failed to fully assemble schema context for {}", sources, e); final Throwable cause = e.getCause(); Verify.verify(cause instanceof SchemaResolutionException); @@ -260,17 +256,17 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem } @Override - public synchronized ListenableFuture getSource( + public synchronized @NonNull FluentFuture getSource( final SourceIdentifier sourceIdentifier) { final Collection ret = texts.get(sourceIdentifier); LOG.debug("Lookup {} result {}", sourceIdentifier, ret); if (ret.isEmpty()) { - return Futures.immediateFailedFuture(new MissingSchemaSourceException( - "URL for " + sourceIdentifier + " not registered", sourceIdentifier)); + return immediateFailedFluentFuture(new MissingSchemaSourceException("URL for " + sourceIdentifier + + " not registered", sourceIdentifier)); } - return Futures.immediateFuture(ret.iterator().next()); + return immediateFluentFuture(ret.iterator().next()); } /** @@ -288,23 +284,23 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem } @Beta - public SchemaContext trySchemaContext() throws SchemaResolutionException { + public EffectiveModelContext trySchemaContext() throws SchemaResolutionException { return trySchemaContext(StatementParserMode.DEFAULT_MODE); } @Beta @SuppressWarnings("checkstyle:avoidHidingCauseException") - public SchemaContext trySchemaContext(final StatementParserMode statementParserMode) + public EffectiveModelContext trySchemaContext(final StatementParserMode statementParserMode) throws SchemaResolutionException { - final ListenableFuture future = repository - .createSchemaContextFactory(SchemaSourceFilter.ALWAYS_ACCEPT) - .createSchemaContext(ImmutableSet.copyOf(requiredSources), statementParserMode); + final ListenableFuture future = repository + .createEffectiveModelContextFactory(config(statementParserMode)) + .createEffectiveModelContext(ImmutableSet.copyOf(requiredSources)); try { return future.get(); - } catch (InterruptedException e) { - throw new RuntimeException("Interrupted while waiting for SchemaContext assembly", e); - } catch (ExecutionException e) { + } catch (final InterruptedException e) { + throw new IllegalStateException("Interrupted while waiting for SchemaContext assembly", e); + } catch (final ExecutionException e) { final Throwable cause = e.getCause(); if (cause instanceof SchemaResolutionException) { throw (SchemaResolutionException) cause; @@ -318,4 +314,8 @@ public final class YangTextSchemaContextResolver implements AutoCloseable, Schem public void close() { transReg.close(); } + + private static SchemaContextFactoryConfiguration config(final StatementParserMode statementParserMode) { + return SchemaContextFactoryConfiguration.builder().setStatementParserMode(statementParserMode).build(); + } }