Merge "Improved sorting of augmentations before code generation."
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / repo / AbstractCachingSchemaSourceProvider.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/eplv10.html
7  */
8 package org.opendaylight.yangtools.yang.model.util.repo;
9
10 import org.opendaylight.yangtools.concepts.Delegator;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.Optional;
14 import com.google.common.base.Preconditions;
15
16
17 /**
18  *
19  * Abstract caching schema provider with support of multiple context
20  * per backing {@link SchemaSourceProvider}.
21  *
22  * @param <I> Input Schema Source Representation
23  * @param <O> Output Schema Source Representation
24  */
25 public abstract class AbstractCachingSchemaSourceProvider<I, O> implements AdvancedSchemaSourceProvider<O>,
26         Delegator<AdvancedSchemaSourceProvider<I>> {
27
28     private final AdvancedSchemaSourceProvider<I> defaultDelegate;
29
30     /**
31      * Construct caching schema source provider with supplied delegate.
32      *
33      * Default delegate is is used to retrieve schema source when cache does not
34      * contain requested sources.
35      *
36      * @param delegate SchemaSourceProvided used to look up and retrieve schema source
37      * when cache does not contain requested sources.
38      */
39     protected AbstractCachingSchemaSourceProvider(final AdvancedSchemaSourceProvider<I> delegate) {
40         this.defaultDelegate = delegate;
41     }
42
43     @Override
44     public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
45         Preconditions.checkNotNull(moduleName, "Module name should not be null.");
46         Preconditions.checkNotNull(revision, "Revision should not be null");
47         return getSchemaSource(SourceIdentifier.create(moduleName, revision));
48     }
49
50     @Override
51     public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
52         return getSchemaSourceImpl(sourceIdentifier, defaultDelegate);
53     }
54
55     /**
56      * Actual implementation of schema source retrieval.
57      *
58      * <ul>
59      * <li>look up cached schema source via {@link #getCachedSchemaSource(SourceIdentifier)}
60      * <li>If source was found in cache, returns source to client code.
61      * <li>If source was not found in cache, Look up schema source in supplied <code>delegate</code>
62      * <li>Updates cache with schema from delegate by {@link #cacheSchemaSource(SourceIdentifier, Optional)}
63      * <li>Result is returned to client code.
64      * </ul>
65      *
66      * @param identifier Source identifier
67      * @param delegate Delegate to lookup if there is a miss.
68      * @return Optional of schema source, present if source was found. Absent otherwise.
69      */
70     protected final Optional<O> getSchemaSourceImpl(final SourceIdentifier identifier,
71             final AdvancedSchemaSourceProvider<I> delegate) {
72         Preconditions.checkNotNull(identifier, "Source identifier name should not be null.");
73
74         Optional<O> cached = getCachedSchemaSource(identifier);
75         if (cached.isPresent()) {
76             return cached;
77         }
78         Optional<I> live = delegate.getSchemaSource(identifier);
79         return cacheSchemaSource(identifier, live);
80     }
81
82     /**
83      * Caches supplied result and returns cached result which should be returned to client.
84      *
85      * <p>
86      * Implementations of cache are required to cache schema source if possible.
87      * They are not required to cache {@link Optional#absent()}.
88      *
89      * Implementations are required to transform source representation if <code>O</code> and <code>I</code>
90      * are different.
91      *
92      * This method SHOULD NOT fail and should recover from Runtime exceptions
93      * by not caching source and only transforming it.
94      *
95      * @param identifier Source Identifier for which schema SHOULD be cached
96      * @param input Optional of schema source, representing one returned from delegate.
97      * @return Optional of schema source, representing result returned from this cache.
98      */
99     abstract protected Optional<O> cacheSchemaSource(SourceIdentifier identifier, Optional<I> input);
100
101     /**
102      * Returns cached schema source of {@link Optional#absent()} if source is not present in cache.
103      *
104      * <p>
105      * Implementations of cache MUST return cached schema source, if it is present in cache,
106      * otherwise source will be requested from deleate and then cache will be updated
107      * via {@link #cacheSchemaSource(SourceIdentifier, Optional)}.
108      *
109      * @param identifier Source Identifier for which schema should be retrieved.
110      * @return Cached schema source.
111      */
112     abstract protected Optional<O> getCachedSchemaSource(SourceIdentifier identifier);
113
114     @Override
115     public AdvancedSchemaSourceProvider<I> getDelegate() {
116         return defaultDelegate;
117     }
118
119     /**
120      * Creates an lightweight instance of source provider, which uses this cache for caching
121      * and supplied additional delegate for lookup of not cached sources.
122      * <p>
123      *
124      * @param delegate Backing {@link SchemaSourceProvider} which should be used for lookup
125      *   for sources not present in schema.
126      * @return new instance of {@link SchemaSourceProvider} which first lookup in cache
127      *   and then in delegate.
128      *
129      */
130     @Beta
131     public SchemaSourceProvider<O> createInstanceFor(final SchemaSourceProvider<I> delegate) {
132         return new SchemaSourceProviderInstance(SchemaSourceProviders.toAdvancedSchemaSourceProvider(delegate));
133
134     }
135
136     /**
137      *
138      * Lightweight instance of source provider, which is associated with parent
139      * {@link AbstractCachingSchemaSourceProvider}, but uses
140      * different delegate for retrieving not cached sources.
141      *
142      */
143     @Beta
144     private class SchemaSourceProviderInstance implements //
145     AdvancedSchemaSourceProvider<O>,
146     Delegator<AdvancedSchemaSourceProvider<I>> {
147
148         private final AdvancedSchemaSourceProvider<I> delegate;
149
150         protected SchemaSourceProviderInstance(final AdvancedSchemaSourceProvider<I> delegate) {
151             super();
152             this.delegate = Preconditions.checkNotNull(delegate, "Delegate should not be null");;
153         }
154
155         @Override
156         public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
157             return getSchemaSource(SourceIdentifier.create(moduleName, revision));
158         }
159
160         @Override
161         public AdvancedSchemaSourceProvider<I> getDelegate() {
162             return delegate;
163         }
164
165         @Override
166         public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
167             return getSchemaSourceImpl(sourceIdentifier, getDelegate());
168         }
169     }
170 }