Deprecate binding.runtime.spi constructs
[mdsal.git] / binding / mdsal-binding-runtime-spi / src / main / java / org / opendaylight / binding / runtime / spi / ModuleInfoBackedContext.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.binding.runtime.spi;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.annotations.Beta;
14 import com.google.common.cache.CacheBuilder;
15 import com.google.common.cache.CacheLoader;
16 import com.google.common.cache.LoadingCache;
17 import com.google.common.collect.ImmutableSet;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import java.util.Optional;
20 import java.util.Set;
21 import org.checkerframework.checker.lock.qual.Holding;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.opendaylight.binding.runtime.api.BindingRuntimeContext;
24 import org.opendaylight.binding.runtime.api.BindingRuntimeGenerator;
25 import org.opendaylight.binding.runtime.api.ClassLoadingStrategy;
26 import org.opendaylight.binding.runtime.api.DefaultBindingRuntimeContext;
27 import org.opendaylight.yangtools.util.ClassLoaderUtils;
28 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
29 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
30 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
31 import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
32 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
33 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
34 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
35 import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver;
36
37 @Beta
38 @Deprecated(forRemoval = true)
39 public class ModuleInfoBackedContext extends AbstractModuleInfoTracker implements ClassLoadingStrategy,
40         EffectiveModelContextProvider, SchemaSourceProvider<YangTextSchemaSource> {
41     private static final class WithFallback extends ModuleInfoBackedContext {
42         private final @NonNull ClassLoadingStrategy fallback;
43
44         WithFallback(final YangTextSchemaContextResolver resolver, final ClassLoadingStrategy fallback) {
45             super(resolver);
46             this.fallback = requireNonNull(fallback);
47         }
48
49         @Override
50         Class<?> loadUnknownClass(final String fullyQualifiedName) throws ClassNotFoundException {
51             // We have not found a matching registration, consult the backing strategy
52             final Class<?> cls = fallback.loadClass(fullyQualifiedName);
53             registerImplicitBindingClass(cls);
54             return cls;
55         }
56     }
57
58     private static final LoadingCache<ClassLoadingStrategy,
59         LoadingCache<ImmutableSet<YangModuleInfo>, ModuleInfoBackedContext>> CONTEXT_CACHES = CacheBuilder.newBuilder()
60             .weakKeys().build(new CacheLoader<ClassLoadingStrategy,
61                 LoadingCache<ImmutableSet<YangModuleInfo>, ModuleInfoBackedContext>>() {
62                     @Override
63                     public LoadingCache<ImmutableSet<YangModuleInfo>, ModuleInfoBackedContext> load(
64                             final ClassLoadingStrategy strategy) {
65                         return CacheBuilder.newBuilder().weakValues().build(
66                             new CacheLoader<Set<YangModuleInfo>, ModuleInfoBackedContext>() {
67                                 @Override
68                                 public ModuleInfoBackedContext load(final Set<YangModuleInfo> key) {
69                                     final ModuleInfoBackedContext context = ModuleInfoBackedContext.create(strategy);
70                                     context.registerModuleInfos(key);
71                                     return context;
72                                 }
73                             });
74                     }
75             });
76
77     ModuleInfoBackedContext(final YangTextSchemaContextResolver resolver) {
78         super(resolver);
79     }
80
81     @Beta
82     public static ModuleInfoBackedContext cacheContext(final ClassLoadingStrategy loadingStrategy,
83             final ImmutableSet<YangModuleInfo> infos) {
84         return CONTEXT_CACHES.getUnchecked(loadingStrategy).getUnchecked(infos);
85     }
86
87     public static ModuleInfoBackedContext create() {
88         return create("unnamed");
89     }
90
91     public static ModuleInfoBackedContext create(final String id) {
92         return new ModuleInfoBackedContext(YangTextSchemaContextResolver.create(id));
93     }
94
95     public static ModuleInfoBackedContext create(final ClassLoadingStrategy loadingStrategy) {
96         return create("unnamed", loadingStrategy);
97     }
98
99     public static ModuleInfoBackedContext create(final String id, final ClassLoadingStrategy loadingStrategy) {
100         return new WithFallback(YangTextSchemaContextResolver.create(id), loadingStrategy);
101     }
102
103     public static ModuleInfoBackedContext create(final String id, final YangParserFactory factory) {
104         return new ModuleInfoBackedContext(YangTextSchemaContextResolver.create(id, factory));
105     }
106
107     public static ModuleInfoBackedContext create(final String id, final YangParserFactory factory,
108             final ClassLoadingStrategy loadingStrategy) {
109         return new WithFallback(YangTextSchemaContextResolver.create(id, factory), loadingStrategy);
110     }
111
112     @Override
113     public final EffectiveModelContext getEffectiveModelContext() {
114         final Optional<? extends EffectiveModelContext> contextOptional = tryToCreateModelContext();
115         checkState(contextOptional.isPresent(), "Unable to recreate SchemaContext, error while parsing");
116         return contextOptional.get();
117     }
118
119     @Override
120     public final synchronized Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
121         final ClassLoader loader = findClassLoader(fullyQualifiedName);
122         return loader != null ? ClassLoaderUtils.loadClass(loader, fullyQualifiedName)
123                 : loadUnknownClass(fullyQualifiedName);
124     }
125
126     @Override
127     public final ListenableFuture<? extends YangTextSchemaSource> getSource(final SourceIdentifier sourceIdentifier) {
128         return getResolverSource(sourceIdentifier);
129     }
130
131     @Beta
132     public final @NonNull BindingRuntimeContext createRuntimeContext(final BindingRuntimeGenerator generator) {
133         return DefaultBindingRuntimeContext.create(
134             generator.generateTypeMapping(tryToCreateModelContext().orElseThrow()), this);
135     }
136
137     // TODO finish schema parsing and expose as SchemaService
138     // Unite with current SchemaService
139
140     public final Optional<? extends EffectiveModelContext> tryToCreateModelContext() {
141         return getResolverEffectiveModel();
142     }
143
144     @Holding("this")
145     Class<?> loadUnknownClass(final String fullyQualifiedName) throws ClassNotFoundException {
146         throw new ClassNotFoundException(fullyQualifiedName);
147     }
148 }