1 package org.opendaylight.yangtools.yang.parser.impl.util;
3 import java.io.IOException;
4 import java.io.InputStream;
7 import java.util.Map.Entry;
9 import java.util.concurrent.ConcurrentHashMap;
10 import java.util.concurrent.ConcurrentMap;
12 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
13 import org.opendaylight.yangtools.concepts.Identifiable;
14 import org.opendaylight.yangtools.concepts.Registration;
15 import org.opendaylight.yangtools.yang.model.api.Module;
16 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
17 import org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider;
18 import org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier;
19 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
23 import com.google.common.base.Optional;
24 import com.google.common.collect.ImmutableMap;
25 import com.google.common.collect.ImmutableMap.Builder;
26 import com.google.common.collect.ImmutableSet;
28 import static com.google.common.base.Preconditions.checkArgument;
30 public class URLSchemaContextResolver implements AdvancedSchemaSourceProvider<InputStream> {
32 private static final Logger LOG = LoggerFactory.getLogger(URLSchemaContextResolver.class);
33 private final ConcurrentMap<SourceIdentifier, SourceContext> availableSources = new ConcurrentHashMap<>();
35 private YangSourceContext currentSourceContext;
36 private Optional<SchemaContext> currentSchemaContext = Optional.absent();
38 public Registration<URL> registerSource(URL source) {
39 checkArgument(source != null, "Supplied source must not be null");
40 InputStream yangStream = getInputStream(source);
41 YangModelDependencyInfo modelInfo = YangModelDependencyInfo.fromInputStream(yangStream);
42 SourceIdentifier identifier = SourceIdentifier.create(modelInfo.getName(),
43 Optional.of(modelInfo.getFormattedRevision()));
44 SourceContext sourceContext = new SourceContext(source, identifier, modelInfo);
45 availableSources.putIfAbsent(identifier, sourceContext);
49 public Optional<SchemaContext> getSchemaContext() {
50 return currentSchemaContext;
54 public Optional<InputStream> getSchemaSource(SourceIdentifier key) {
55 SourceContext ctx = availableSources.get(key);
57 InputStream stream = getInputStream(ctx.getInstance());
58 return Optional.fromNullable(stream);
60 return Optional.absent();
64 public Optional<InputStream> getSchemaSource(String name, Optional<String> version) {
65 return getSchemaSource(SourceIdentifier.create(name, version));
68 private InputStream getInputStream(URL source) {
71 stream = source.openStream();
72 } catch (IOException e) {
73 throw new IllegalArgumentException("Supplied stream: " + source + " is not available", e);
78 private final class SourceContext extends AbstractObjectRegistration<URL> //
79 implements Identifiable<SourceIdentifier> {
81 final SourceIdentifier identifier;
82 final YangModelDependencyInfo dependencyInfo;
84 public SourceContext(URL instance, SourceIdentifier identifier, YangModelDependencyInfo modelInfo) {
86 this.identifier = identifier;
87 this.dependencyInfo = modelInfo;
90 public SourceIdentifier getIdentifier() {
95 protected void removeRegistration() {
99 public YangModelDependencyInfo getDependencyInfo() {
100 return dependencyInfo;
104 private void removeSource(SourceContext sourceContext) {
105 boolean removed = availableSources.remove(sourceContext.getIdentifier(), sourceContext);
107 tryToUpdateSchemaContext();
111 public synchronized Optional<SchemaContext> tryToUpdateSchemaContext() {
112 if(availableSources.isEmpty()) {
113 return Optional.absent();
115 ImmutableMap<SourceIdentifier, SourceContext> actualSources = ImmutableMap.copyOf(availableSources);
116 Builder<SourceIdentifier, YangModelDependencyInfo> builder = ImmutableMap.<SourceIdentifier, YangModelDependencyInfo> builder();
117 for(Entry<SourceIdentifier, SourceContext> entry : actualSources.entrySet()) {
118 builder.put(entry.getKey(), entry.getValue().getDependencyInfo());
120 ImmutableMap<SourceIdentifier, YangModelDependencyInfo> sourcesMap = builder.build();
121 YangSourceContext context = YangSourceContext.createFrom(sourcesMap);
122 LOG.debug("Trying to create schema context from {}",sourcesMap.keySet());
123 LOG.debug("Ommiting {} because of unresolved dependencies",context.getMissingDependencies().keySet());
126 if(currentSourceContext == null || !context.getValidSources().equals(currentSourceContext.getValidSources())) {
127 List<InputStream> streams = YangSourceContext.getValidInputStreams(context, this);
128 YangParserImpl parser = new YangParserImpl();
129 Set<Module> modules = parser.parseYangModelsFromStreams(streams);
130 SchemaContext schemaContext = parser.resolveSchemaContext(modules);
131 currentSchemaContext = Optional.of(schemaContext);
132 currentSourceContext = context;
133 return currentSchemaContext;
135 currentSourceContext = context;
136 } catch (Exception e) {
137 LOG.error("Could not create schema context for {} ",context.getValidSources());
139 return Optional.absent();