exchange with GNPy to check path feasibility
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / DataStoreContextImpl.java
1 /*
2  * Copyright © 2016 AT&T 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.transportpce.common;
9
10 import com.google.common.collect.ClassToInstanceMap;
11 import com.google.common.collect.ImmutableMap;
12 import com.google.common.util.concurrent.ListeningExecutorService;
13 import com.google.common.util.concurrent.MoreExecutors;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.ServiceLoader;
19 import java.util.concurrent.Executors;
20 import javassist.ClassPool;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
24 import org.opendaylight.controller.md.sal.binding.api.NotificationService;
25 import org.opendaylight.controller.md.sal.binding.impl.BindingDOMDataBrokerAdapter;
26 import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationPublishServiceAdapter;
27 import org.opendaylight.controller.md.sal.binding.impl.BindingDOMNotificationServiceAdapter;
28 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
31 import org.opendaylight.controller.md.sal.dom.broker.impl.DOMNotificationRouter;
32 import org.opendaylight.controller.md.sal.dom.broker.impl.SerializedDOMDataBroker;
33 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
34 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
35 import org.opendaylight.mdsal.binding.dom.codec.gen.impl.StreamWriterGenerator;
36 import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
37 import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
38 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
39 import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
40 import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
41 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
42 import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
43 import org.opendaylight.yangtools.concepts.ListenerRegistration;
44 import org.opendaylight.yangtools.util.ListenerRegistry;
45 import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
46 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
47 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
48 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
49 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class DataStoreContextImpl implements DataStoreContext {
54
55     private static final Logger LOG = LoggerFactory.getLogger(DataStoreContextImpl.class);
56
57     private final Map<LogicalDatastoreType, DOMStore> datastores;
58     private final SchemaContextHolder mockedSchemaContext;
59     private final DOMNotificationRouter domNotificationRouter;
60     private final DOMDataBroker domDataBroker;
61     private final DataBroker dataBroker;
62     private final NotificationService notificationService;
63     private final NotificationPublishService notificationPublishService;
64
65     public DataStoreContextImpl() {
66         this(false);
67     }
68
69     public DataStoreContextImpl(boolean fromClasspath) {
70         this.mockedSchemaContext = new SchemaContextHolder(fromClasspath);
71         this.datastores = createDatastores();
72         this.domNotificationRouter = DOMNotificationRouter.create(16);
73         this.domDataBroker = createDOMDataBroker();
74         this.dataBroker = createDataBroker();
75         this.notificationService = createNotificationService();
76         this.notificationPublishService = createNotificationPublishService();
77         for (ListenerRegistration<SchemaContextListener> listener : this.mockedSchemaContext.listeners) {
78             listener.getInstance().onGlobalContextUpdated(this.mockedSchemaContext.schemaContext);
79         }
80     }
81
82     @Override
83     public DataBroker getDataBroker() {
84         return this.dataBroker;
85     }
86
87     @Override
88     public DOMDataBroker getDOMDataBroker() {
89         return this.domDataBroker;
90     }
91
92     @Override
93     public NotificationService createNotificationService() {
94         return new BindingDOMNotificationServiceAdapter(this.mockedSchemaContext.bindingStreamCodecs,
95                 this.domNotificationRouter);
96     }
97
98     @Override
99     public NotificationPublishService createNotificationPublishService() {
100         return new BindingDOMNotificationPublishServiceAdapter(this.mockedSchemaContext.bindingToNormalized,
101                 this.domNotificationRouter);
102     }
103
104     @Override
105     public SchemaContext getSchemaContext() {
106         return this.mockedSchemaContext.schemaContext;
107     }
108
109     @Override
110     public BindingNormalizedNodeCodecRegistry getBindingToNormalizedNodeCodec() {
111         return this.mockedSchemaContext.bindingStreamCodecs;
112     }
113
114     @Override
115     public NotificationService getNotificationService() {
116         return this.notificationService;
117     }
118
119     @Override
120     public NotificationPublishService getNotificationPublishService() {
121         return this.notificationPublishService;
122     }
123
124     private DOMDataBroker createDOMDataBroker() {
125         return new SerializedDOMDataBroker(this.datastores,
126                 MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()));
127     }
128
129     private ListeningExecutorService getDataTreeChangeListenerExecutor() {
130         return MoreExecutors.newDirectExecutorService();
131     }
132
133     private DataBroker createDataBroker() {
134         return new BindingDOMDataBrokerAdapter(getDOMDataBroker(), this.mockedSchemaContext.bindingToNormalized);
135     }
136
137     private Map<LogicalDatastoreType, DOMStore> createDatastores() {
138         return ImmutableMap.<LogicalDatastoreType, DOMStore>builder()
139                 .put(LogicalDatastoreType.OPERATIONAL, createOperationalDatastore())
140                 .put(LogicalDatastoreType.CONFIGURATION, createConfigurationDatastore()).build();
141     }
142
143     private DOMStore createConfigurationDatastore() {
144         final InMemoryDOMDataStore store = new InMemoryDOMDataStore("CFG", getDataTreeChangeListenerExecutor());
145         this.mockedSchemaContext.registerSchemaContextListener(store);
146         return store;
147     }
148
149     private DOMStore createOperationalDatastore() {
150         final InMemoryDOMDataStore store = new InMemoryDOMDataStore("OPER", getDataTreeChangeListenerExecutor());
151         this.mockedSchemaContext.registerSchemaContextListener(store);
152         return store;
153     }
154
155     private final class SchemaContextHolder implements DOMSchemaService, SchemaContextProvider {
156
157         private final SchemaContext schemaContext;
158         private final ListenerRegistry<SchemaContextListener> listeners;
159         private final BindingNormalizedNodeCodecRegistry bindingStreamCodecs;
160         private final BindingToNormalizedNodeCodec bindingToNormalized;
161         private final ModuleInfoBackedContext moduleInfoBackedCntxt;
162
163         private SchemaContextHolder(boolean fromClasspath) {
164             List<YangModuleInfo> moduleInfos = loadModuleInfos();
165             this.moduleInfoBackedCntxt = ModuleInfoBackedContext.create();
166             this.schemaContext = getSchemaContext(moduleInfos);
167             this.listeners = ListenerRegistry.create();
168             this.bindingStreamCodecs = createBindingRegistry();
169             GeneratedClassLoadingStrategy loading = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
170             this.bindingToNormalized = new BindingToNormalizedNodeCodec(loading, this.bindingStreamCodecs);
171             registerSchemaContextListener(this.bindingToNormalized);
172         }
173
174         @Override
175         public SchemaContext getSchemaContext() {
176             return this.schemaContext;
177         }
178
179         /**
180          * Get the schemacontext from loaded modules on classpath.
181          *
182          * @param moduleInfos a list of Yang module Infos
183          * @return SchemaContext a schema context
184          */
185         private SchemaContext getSchemaContext(List<YangModuleInfo> moduleInfos) {
186             this.moduleInfoBackedCntxt.addModuleInfos(moduleInfos);
187             Optional<SchemaContext> tryToCreateSchemaContext =
188                     this.moduleInfoBackedCntxt.tryToCreateSchemaContext();
189             if (!tryToCreateSchemaContext.isPresent()) {
190                 LOG.error("Could not create the initial schema context. Schema context is empty");
191                 throw new IllegalStateException();
192             }
193             return tryToCreateSchemaContext.get();
194         }
195
196         @Override
197         public SchemaContext getGlobalContext() {
198             return this.schemaContext;
199         }
200
201         @Override
202         public SchemaContext getSessionContext() {
203             return this.schemaContext;
204         }
205
206         @Override
207         public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
208                 SchemaContextListener listener) {
209             return this.listeners.register(listener);
210         }
211
212         /**
213          * Loads all {@link YangModelBindingProvider} on the classpath.
214          *
215          * @return list of known {@link YangModuleInfo}
216          */
217         private List<YangModuleInfo> loadModuleInfos() {
218             List<YangModuleInfo> moduleInfos = new LinkedList<>();
219             ServiceLoader<YangModelBindingProvider> yangProviderLoader =
220                     ServiceLoader.load(YangModelBindingProvider.class);
221             for (YangModelBindingProvider yangModelBindingProvider : yangProviderLoader) {
222                 moduleInfos.add(yangModelBindingProvider.getModuleInfo());
223                 LOG.debug("Adding [{}] module into known modules", yangModelBindingProvider.getModuleInfo());
224             }
225             return moduleInfos;
226         }
227
228         /**
229          * Creates binding registry.
230          *
231          * @return BindingNormalizedNodeCodecRegistry the resulting binding registry
232          */
233         private BindingNormalizedNodeCodecRegistry createBindingRegistry() {
234             BindingRuntimeContext bindingContext =
235                 BindingRuntimeContext.create(this.moduleInfoBackedCntxt, this.schemaContext);
236             BindingNormalizedNodeCodecRegistry bindingNormalizedNodeCodecRegistry =
237                     new BindingNormalizedNodeCodecRegistry(
238                             StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())));
239             bindingNormalizedNodeCodecRegistry.onBindingRuntimeContextUpdated(bindingContext);
240             return bindingNormalizedNodeCodecRegistry;
241         }
242
243         /* (non-Javadoc)
244          * @see org.opendaylight.mdsal.dom.api.DOMExtensibleService#getExtensions()
245          */
246         @Override
247         public @NonNull ClassToInstanceMap<DOMSchemaServiceExtension> getExtensions() {
248             // TODO Auto-generated method stub
249             return null;
250         }
251     }
252 }