2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.impl.util;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import com.google.common.base.Optional;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.ImmutableMap.Builder;
15 import com.google.common.io.ByteSource;
17 import java.io.IOException;
18 import java.io.InputStream;
20 import java.util.Collection;
21 import java.util.Map.Entry;
22 import java.util.concurrent.ConcurrentHashMap;
23 import java.util.concurrent.ConcurrentMap;
25 import javax.annotation.concurrent.GuardedBy;
26 import javax.annotation.concurrent.ThreadSafe;
28 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
29 import org.opendaylight.yangtools.concepts.Identifiable;
30 import org.opendaylight.yangtools.concepts.ObjectRegistration;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 import org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider;
33 import org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier;
34 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * @deprecated Use {@link org.opendaylight.yangtools.yang.parser.repo.URLSchemaContextResolver}
44 public class URLSchemaContextResolver implements AdvancedSchemaSourceProvider<InputStream> {
46 private static final Logger LOG = LoggerFactory.getLogger(URLSchemaContextResolver.class);
49 private final ConcurrentMap<SourceIdentifier, SourceContext> availableSources = new ConcurrentHashMap<>();
51 private YangSourceContext currentSourceContext;
53 private Optional<SchemaContext> currentSchemaContext = Optional.absent();
56 * Register new yang schema when it appears.
58 public synchronized ObjectRegistration<URL> registerSource(final URL source) {
59 checkArgument(source != null, "Supplied source must not be null");
60 InputStream yangStream = getInputStream(source);
61 YangModelDependencyInfo modelInfo = YangModelDependencyInfo.fromInputStream(yangStream);
62 SourceIdentifier identifier = SourceIdentifier.create(modelInfo.getName(),
63 Optional.of(modelInfo.getFormattedRevision()));
64 SourceContext sourceContext = new SourceContext(source, identifier, modelInfo);
65 availableSources.putIfAbsent(identifier, sourceContext);
69 public synchronized Optional<SchemaContext> getSchemaContext() {
70 return currentSchemaContext;
74 public synchronized Optional<InputStream> getSchemaSource(final SourceIdentifier key) {
75 SourceContext ctx = availableSources.get(key);
77 InputStream stream = getInputStream(ctx.getInstance());
78 return Optional.fromNullable(stream);
80 return Optional.absent();
84 public Optional<InputStream> getSchemaSource(final String name, final Optional<String> version) {
85 return getSchemaSource(SourceIdentifier.create(name, version));
88 private static InputStream getInputStream(final URL source) {
91 stream = source.openStream();
92 } catch (IOException e) {
93 throw new IllegalArgumentException("Supplied stream: " + source + " is not available", e);
98 private final class SourceContext extends AbstractObjectRegistration<URL> //
99 implements Identifiable<SourceIdentifier> {
101 final SourceIdentifier identifier;
102 final YangModelDependencyInfo dependencyInfo;
104 public SourceContext(final URL instance, final SourceIdentifier identifier, final YangModelDependencyInfo modelInfo) {
106 this.identifier = identifier;
107 this.dependencyInfo = modelInfo;
111 public SourceIdentifier getIdentifier() {
116 protected void removeRegistration() {
120 public YangModelDependencyInfo getDependencyInfo() {
121 return dependencyInfo;
125 private synchronized void removeSource(final SourceContext sourceContext) {
126 boolean removed = availableSources.remove(sourceContext.getIdentifier(), sourceContext);
128 tryToUpdateSchemaContext();
133 * Try to parse all currently available yang files and build new schema context.
134 * @return new schema context iif there is at least 1 yang file registered and new schema context was successfully built.
136 public synchronized Optional<SchemaContext> tryToUpdateSchemaContext() {
137 if (availableSources.isEmpty()) {
138 return Optional.absent();
140 ImmutableMap<SourceIdentifier, SourceContext> actualSources = ImmutableMap.copyOf(availableSources);
141 Builder<SourceIdentifier, YangModelDependencyInfo> builder = ImmutableMap.<SourceIdentifier, YangModelDependencyInfo>builder();
142 for (Entry<SourceIdentifier, SourceContext> entry : actualSources.entrySet()) {
143 builder.put(entry.getKey(), entry.getValue().getDependencyInfo());
145 ImmutableMap<SourceIdentifier, YangModelDependencyInfo> sourcesMap = builder.build();
146 YangSourceContext yangSourceContext = YangSourceContext.createFrom(sourcesMap, this);
147 LOG.debug("Trying to create schema context from {}", sourcesMap.keySet());
149 if (yangSourceContext.getMissingDependencies().size() != 0) {
150 LOG.debug("Omitting {} because of unresolved dependencies", yangSourceContext.getMissingDependencies().keySet());
151 LOG.debug("Missing model sources for {}", yangSourceContext.getMissingSources());
153 if (currentSourceContext == null || !yangSourceContext.getValidSources().equals(currentSourceContext.getValidSources())) {
155 Collection<ByteSource> byteSources = yangSourceContext.getValidByteSources();
156 YangParserImpl parser = YangParserImpl.getInstance();
157 SchemaContext schemaContext = parser.parseSources(byteSources);
158 currentSchemaContext = Optional.of(schemaContext);
159 currentSourceContext = yangSourceContext;
160 return Optional.of(schemaContext);
161 } catch (Exception e) {
162 LOG.error("Could not create schema context for {} ", yangSourceContext.getValidSources(), e);
163 return Optional.absent();
166 currentSourceContext = yangSourceContext;
167 return Optional.absent();