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