51f80848bd2a86463cf333f7eb0e62f12ef1acfa
[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.base.MoreObjects.ToStringHelper;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.Set;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22 import org.opendaylight.netconf.test.tool.TestToolUtils;
23 import org.opendaylight.yangtools.yang.common.Revision;
24 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
25 import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
26 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
27 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
28 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
29 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource.Costs;
30 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
31 import org.opendaylight.yangtools.yang.model.repo.util.AbstractSchemaSourceCache;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * Cache implementation that stores schemas in form of files under provided folder.
37  */
38 public final class SchemaSourceCache<T extends SchemaSourceRepresentation>
39         extends AbstractSchemaSourceCache<T> {
40
41     private static final Logger LOG = LoggerFactory.getLogger(SchemaSourceCache.class);
42
43     public static final Pattern CACHED_FILE_PATTERN = Pattern.compile(
44                     ".*/(?<moduleName>[^@]+)" + "(@(?<revision>" + Revision.STRING_FORMAT_PATTERN + "))?.yang");
45
46     private final Class<T> representation;
47     private final Set<String> modelList;
48     private Map<String, ModelData> cachedSchemas;
49
50     public SchemaSourceCache(
51             final SchemaSourceRegistry consumer, final Class<T> representation, final Set<String> modelList) {
52         super(consumer, representation, Costs.LOCAL_IO);
53         this.representation = representation;
54         this.modelList = Preconditions.checkNotNull(modelList);
55         init();
56     }
57
58     /**
59      * Restore cache state.
60      */
61     private void init() {
62         cachedSchemas = new HashMap<>();
63         for (String modelPath: modelList) {
64             Optional<SourceIdentifier> sourceIdentifierOptional = getSourceIdentifier(modelPath);
65             if (sourceIdentifierOptional.isPresent()) {
66                 SourceIdentifier sourceIdentifier = sourceIdentifierOptional.get();
67                 cachedSchemas.put(sourceIdentifier.toYangFilename(), new ModelData(sourceIdentifier, modelPath));
68             } else {
69                 LOG.debug("Skipping caching model {}, cannot restore source identifier from model path,"
70                         + " does not match {}", modelPath, CACHED_FILE_PATTERN);
71             }
72         }
73         for (final ModelData cachedSchema : cachedSchemas.values()) {
74             register(cachedSchema.getId());
75         }
76     }
77
78     @Override
79     public synchronized ListenableFuture<? extends T> getSource(final SourceIdentifier sourceIdentifier) {
80         ModelData modelData = cachedSchemas.get(sourceIdentifier.toYangFilename());
81         if (modelData != null) {
82             final SchemaSourceRepresentation restored = restoreAsType(modelData.getId(), modelData.getPath());
83             return Futures.immediateFuture(representation.cast(restored));
84         }
85
86         LOG.debug("Source {} not found in cache as {}", sourceIdentifier);
87         return Futures.immediateFailedFuture(new MissingSchemaSourceException("Source not found", sourceIdentifier));
88     }
89
90     @Override
91     protected synchronized void offer(final T source) {
92         LOG.trace("Source {} offered to cache", source.getIdentifier());
93     }
94
95     private static YangTextSchemaSource restoreAsType(final SourceIdentifier sourceIdentifier,
96             final String cachedSource) {
97         return new YangTextSchemaSource(sourceIdentifier) {
98
99             @Override
100             protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
101                 return toStringHelper;
102             }
103
104             @Override
105             public InputStream openStream() throws IOException {
106                 return TestToolUtils.getDataAsStream(cachedSource);
107             }
108         };
109     }
110
111     private static Optional<SourceIdentifier> getSourceIdentifier(final String fileName) {
112         final Matcher matcher = CACHED_FILE_PATTERN.matcher(fileName);
113         if (matcher.matches()) {
114             final String moduleName = matcher.group("moduleName");
115             final Optional<Revision> revision = Revision.ofNullable(matcher.group("revision"));
116             return Optional.of(RevisionSourceIdentifier.create(moduleName, revision));
117         }
118         return Optional.empty();
119     }
120 }