7a9f07df184f0135682c3cee9a8eb10e9fae444b
[mdsal.git] / dom / mdsal-dom-broker / src / main / java / org / opendaylight / mdsal / dom / broker / schema / ScanningSchemaServiceProvider.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.mdsal.dom.broker.schema;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.collect.ClassToInstanceMap;
12 import com.google.common.collect.ImmutableClassToInstanceMap;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.Iterables;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import java.io.IOException;
17 import java.net.URL;
18 import java.util.ArrayList;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Optional;
22 import javax.annotation.concurrent.GuardedBy;
23 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
24 import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
25 import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.concepts.Registration;
28 import org.opendaylight.yangtools.util.ListenerRegistry;
29 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
32 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
33 import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
34 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
35 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
36 import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class ScanningSchemaServiceProvider
41         implements DOMSchemaService, SchemaContextProvider, DOMYangTextSourceProvider, AutoCloseable {
42     private static final Logger LOG = LoggerFactory.getLogger(ScanningSchemaServiceProvider.class);
43
44     @GuardedBy("lock")
45     private final ListenerRegistry<SchemaContextListener> listeners = new ListenerRegistry<>();
46     private final Object lock = new Object();
47     private final YangTextSchemaContextResolver contextResolver = YangTextSchemaContextResolver.create("global-bundle");
48
49     public void tryToUpdateSchemaContext() {
50         synchronized (lock) {
51             final Optional<SchemaContext> schema = contextResolver.getSchemaContext();
52             if (schema.isPresent()) {
53                 if (LOG.isDebugEnabled()) {
54                     LOG.debug("Got new SchemaContext: # of modules {}", schema.get().getModules().size());
55                 }
56                 notifyListeners(schema.get());
57             }
58         }
59     }
60
61     @VisibleForTesting
62     @SuppressWarnings("checkstyle:IllegalCatch")
63     public void notifyListeners(final SchemaContext schemaContext) {
64         synchronized (lock) {
65             for (final ListenerRegistration<SchemaContextListener> registration : listeners) {
66                 try {
67                     registration.getInstance().onGlobalContextUpdated(schemaContext);
68                 } catch (final Exception e) {
69                     LOG.error("Exception occured during invoking listener", e);
70                 }
71             }
72         }
73     }
74
75     public List<Registration> registerAvailableYangs(final List<URL> yangs) {
76         final List<Registration> sourceRegistrator = new ArrayList<>();
77         for (final URL url : yangs) {
78             try {
79                 sourceRegistrator.add(contextResolver.registerSource(url));
80             } catch (SchemaSourceException | IOException | YangSyntaxErrorException e) {
81                 LOG.warn("Failed to register {}, ignoring it", url, e);
82             }
83         }
84         return sourceRegistrator;
85     }
86
87     public void removeListener(final SchemaContextListener schemaContextListener) {
88         synchronized (lock) {
89             for (final ListenerRegistration<SchemaContextListener> listenerRegistration : listeners.getListeners()) {
90                 if (listenerRegistration.getInstance().equals(schemaContextListener)) {
91                     listenerRegistration.close();
92                     break;
93                 }
94             }
95         }
96     }
97
98     public boolean hasListeners() {
99         boolean hasListeners;
100         synchronized (lock) {
101             if (Iterables.size(listeners.getListeners()) > 0) {
102                 hasListeners = true;
103             } else {
104                 hasListeners = false;
105             }
106         }
107         return hasListeners;
108     }
109
110     @Override
111     public SchemaContext getSessionContext() {
112         throw new UnsupportedOperationException();
113     }
114
115     @Override
116     public SchemaContext getGlobalContext() {
117         return contextResolver.getSchemaContext().orElse(null);
118     }
119
120     @Override
121     public ListenerRegistration<SchemaContextListener>
122             registerSchemaContextListener(final SchemaContextListener listener) {
123         synchronized (lock) {
124             final Optional<SchemaContext> potentialCtx = contextResolver.getSchemaContext();
125             if (potentialCtx.isPresent()) {
126                 listener.onGlobalContextUpdated(potentialCtx.get());
127             }
128             return listeners.register(listener);
129         }
130     }
131
132     @Override
133     public SchemaContext getSchemaContext() {
134         return getGlobalContext();
135     }
136
137     @Override
138     public ListenableFuture<? extends YangTextSchemaSource> getSource(final SourceIdentifier sourceIdentifier) {
139         return contextResolver.getSource(sourceIdentifier);
140     }
141
142     @Override
143     public ClassToInstanceMap<DOMSchemaServiceExtension> getExtensions() {
144         return ImmutableClassToInstanceMap.of(DOMYangTextSourceProvider.class, this);
145     }
146
147     @Override
148     @Deprecated
149     public Map<Class<? extends DOMSchemaServiceExtension>, DOMSchemaServiceExtension> getSupportedExtensions() {
150         return ImmutableMap.of(DOMYangTextSourceProvider.class, this);
151     }
152
153     @Override
154     public void close() {
155         synchronized (lock) {
156             for (final ListenerRegistration<SchemaContextListener> registration : listeners) {
157                 registration.close();
158             }
159         }
160     }
161 }