Bump upstream versions
[netconf.git] / netconf / tools / netconf-testtool / src / main / java / org / opendaylight / netconf / test / tool / schemacache / SchemaSourceCache.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.test.tool.schemacache;
9
10 import com.google.common.util.concurrent.Futures;
11 import com.google.common.util.concurrent.ListenableFuture;
12 import java.util.AbstractMap;
13 import java.util.HashSet;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.stream.Collectors;
17 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.common.Revision;
20 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
21 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
22 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
23 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
24 import org.opendaylight.yangtools.yang.model.repo.spi.AbstractSchemaSourceCache;
25 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
26 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Cache implementation that stores schemas in form of files under provided folder.
32  */
33 public final class SchemaSourceCache<T extends SchemaSourceRepresentation> extends AbstractSchemaSourceCache<T> {
34
35     private static final Logger LOG = LoggerFactory.getLogger(SchemaSourceCache.class);
36
37     private final Class<T> representation;
38     private Map<SourceIdentifier, YangModuleInfo> cachedSchemas;
39
40     public SchemaSourceCache(final SchemaSourceRegistry consumer,
41                              final Class<T> representation,
42                              final Set<YangModuleInfo> moduleList) {
43         super(consumer, representation, Costs.LOCAL_IO);
44         this.representation = representation;
45         initializeCachedSchemas(moduleList);
46     }
47
48     /**
49      * Restore cache state using input set of modules. Cached schemas are filled with dependencies of input modules too.
50      *
51      * @param moduleList Set of modules information.
52      */
53     private void initializeCachedSchemas(final Set<YangModuleInfo> moduleList) {
54         // searching for all dependencies
55         final Set<YangModuleInfo> allModulesInfo = new HashSet<>(moduleList);
56         allModulesInfo.addAll(moduleList.stream()
57                 .flatMap(yangModuleInfo -> collectYangModuleInfoDependencies(yangModuleInfo, moduleList).stream())
58                 .collect(Collectors.toSet()));
59
60         // creation of source identifiers for all yang module info
61         cachedSchemas = allModulesInfo.stream()
62                 .map(yangModuleInfo -> {
63                     final QName name = yangModuleInfo.getName();
64                     final SourceIdentifier revisionSourceIdentifier = new SourceIdentifier(
65                             name.getLocalName(), name.getRevision().map(Revision::toString).orElse(null));
66                     return new AbstractMap.SimpleEntry<>(revisionSourceIdentifier, yangModuleInfo);
67                 })
68                 .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
69         cachedSchemas.keySet().forEach(this::register);
70     }
71
72     /**
73      * Collection of all direct and indirect dependencies of input YANG module info.
74      *
75      * @param yangModuleInfo       Input YANG module info for which this method collects dependencies.
76      * @param collectedModulesInfo Already collected module information.
77      * @return Already collected module information union found direct and indirect dependencies.
78      */
79     private static Set<YangModuleInfo> collectYangModuleInfoDependencies(
80             final YangModuleInfo yangModuleInfo, final Set<YangModuleInfo> collectedModulesInfo) {
81         // resolution of direct dependencies that haven't already been collected
82         final Set<YangModuleInfo> allDependencies = new HashSet<>(collectedModulesInfo);
83         final Set<YangModuleInfo> directDependencies = yangModuleInfo.getImportedModules().stream()
84                 .filter(importedYangModuleInfo -> !collectedModulesInfo.contains(importedYangModuleInfo))
85                 .collect(Collectors.toSet());
86         allDependencies.addAll(directDependencies);
87
88         // resolution of indirect dependencies through recursion
89         final Set<YangModuleInfo> indirectDependencies = directDependencies.stream()
90                 .flatMap(importedYangModuleInfo ->
91                         collectYangModuleInfoDependencies(importedYangModuleInfo, allDependencies).stream())
92                 .collect(Collectors.toSet());
93         allDependencies.addAll(indirectDependencies);
94         return allDependencies;
95     }
96
97     @Override
98     public synchronized ListenableFuture<? extends T> getSource(final SourceIdentifier sourceIdentifier) {
99         final YangModuleInfo yangModuleInfo = cachedSchemas.get(sourceIdentifier);
100         if (yangModuleInfo != null) {
101             final YangTextSchemaSource yangTextSchemaSource = YangTextSchemaSource.delegateForByteSource(
102                     sourceIdentifier, yangModuleInfo.getYangTextByteSource());
103             return Futures.immediateFuture(representation.cast(yangTextSchemaSource));
104         }
105
106         LOG.debug("Source {} not found in cache", sourceIdentifier);
107         return Futures.immediateFailedFuture(new MissingSchemaSourceException("Source not found", sourceIdentifier));
108     }
109
110     @Override
111     protected synchronized void offer(final T source) {
112         LOG.trace("Source {} offered to cache", source.getIdentifier());
113     }
114 }