Do not fail if invoking of listener fails
[mdsal.git] / dom / mdsal-dom-broker / src / main / java / org / opendaylight / mdsal / dom / broker / DOMMountPointServiceImpl.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
9 package org.opendaylight.mdsal.dom.broker;
10
11 import static com.google.common.base.Preconditions.checkState;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.annotations.VisibleForTesting;
15 import com.google.common.base.Preconditions;
16 import com.google.common.collect.MutableClassToInstanceMap;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.Optional;
20 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
21 import org.opendaylight.mdsal.dom.api.DOMMountPointListener;
22 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
23 import org.opendaylight.mdsal.dom.api.DOMService;
24 import org.opendaylight.mdsal.dom.spi.SimpleDOMMountPoint;
25 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.concepts.ObjectRegistration;
28 import org.opendaylight.yangtools.util.ListenerRegistry;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 public class DOMMountPointServiceImpl implements DOMMountPointService {
35     private static final Logger LOG = LoggerFactory.getLogger(DOMMountPointServiceImpl.class);
36
37     private final Map<YangInstanceIdentifier, DOMMountPoint> mountPoints = new HashMap<>();
38
39     private final ListenerRegistry<DOMMountPointListener> listeners = ListenerRegistry.create();
40
41     @Override
42     public Optional<DOMMountPoint> getMountPoint(final YangInstanceIdentifier path) {
43         return Optional.ofNullable(mountPoints.get(path));
44     }
45
46     @Override
47     public DOMMountPointBuilder createMountPoint(final YangInstanceIdentifier path) {
48         checkState(!mountPoints.containsKey(path), "Mount point already exists");
49         return new DOMMountPointBuilderImpl(path);
50     }
51
52     @Override
53     public ListenerRegistration<DOMMountPointListener> registerProvisionListener(final DOMMountPointListener listener) {
54         return listeners.register(listener);
55     }
56
57     /**
58      * Deprecated.
59      *
60      * @deprecated this method should never have been exposed publicly - registration should be done via the public
61      *             {@link #createMountPoint} interface. As such, this method expects the {@code mountPoint} part to be
62      *             of type {@link SimpleDOMMountPoint}.
63      */
64     @Deprecated
65     public ObjectRegistration<DOMMountPoint> registerMountPoint(final DOMMountPoint mountPoint) {
66         Preconditions.checkArgument(mountPoint instanceof SimpleDOMMountPoint,
67                 "Expected mountpoint argument to be of type SimpleDOMMountPoint");
68         return doRegisterMountPoint((SimpleDOMMountPoint) mountPoint);
69     }
70
71     @SuppressWarnings("checkstyle:IllegalCatch")
72     private ObjectRegistration<DOMMountPoint> doRegisterMountPoint(final SimpleDOMMountPoint mountPoint) {
73         final YangInstanceIdentifier mountPointId = mountPoint.getIdentifier();
74         synchronized (mountPoints) {
75             final DOMMountPoint prev = mountPoints.putIfAbsent(mountPointId, mountPoint);
76             checkState(prev == null, "Mount point %s already exists as %s", mountPointId, prev);
77         }
78         listeners.forEach(listener -> {
79             try {
80                 listener.getInstance().onMountPointCreated(mountPointId);
81             } catch (final Exception ex) {
82                 LOG.error("Listener {} failed on mount point {} created event", listener, mountPoint, ex);
83             }
84         });
85
86         return new AbstractObjectRegistration<DOMMountPoint>(mountPoint) {
87             @Override
88             protected void removeRegistration() {
89                 doUnregisterMountPoint(getInstance().getIdentifier());
90             }
91         };
92     }
93
94     /**
95      * Unregisters mountpoint.
96      *
97      * @param mountPointId Mountpoint identifier.
98      *
99      * @deprecated this method should never have been exposed publicly - mountpoint should be unregistered by simply
100      *             closing its registration.
101      *
102      */
103     @Deprecated
104     public void unregisterMountPoint(final YangInstanceIdentifier mountPointId) {
105         doUnregisterMountPoint(mountPointId);
106     }
107
108     @SuppressWarnings("checkstyle:IllegalCatch")
109     private void doUnregisterMountPoint(final YangInstanceIdentifier mountPointId) {
110         synchronized (mountPoints) {
111             if (mountPoints.remove(mountPointId) == null) {
112                 LOG.warn("Removing non-existent mount point {} at", mountPointId, new Throwable());
113                 return;
114             }
115         }
116
117         listeners.forEach(listener -> {
118             try {
119                 listener.getInstance().onMountPointRemoved(mountPointId);
120             } catch (final Exception ex) {
121                 LOG.error("Listener {} failed on mount point {} removed event", listener, mountPointId, ex);
122             }
123         });
124     }
125
126     final class DOMMountPointBuilderImpl implements DOMMountPointBuilder {
127
128         private final MutableClassToInstanceMap<DOMService> services = MutableClassToInstanceMap.create();
129         private final YangInstanceIdentifier path;
130         private SchemaContext schemaContext;
131
132         private SimpleDOMMountPoint mountPoint;
133
134         DOMMountPointBuilderImpl(final YangInstanceIdentifier path) {
135             this.path = requireNonNull(path);
136         }
137
138         @VisibleForTesting
139         SchemaContext getSchemaContext() {
140             return schemaContext;
141         }
142
143         @VisibleForTesting
144         Map<Class<? extends DOMService>, DOMService> getServices() {
145             return services;
146         }
147
148         @Override
149         public <T extends DOMService> DOMMountPointBuilder addService(final Class<T> type, final T impl) {
150             services.putInstance(requireNonNull(type), requireNonNull(impl));
151             return this;
152         }
153
154         @Override
155         public DOMMountPointBuilder addInitialSchemaContext(final SchemaContext ctx) {
156             schemaContext = requireNonNull(ctx);
157             return this;
158         }
159
160         @Override
161         public ObjectRegistration<DOMMountPoint> register() {
162             checkState(mountPoint == null, "Mount point is already built.");
163             mountPoint = SimpleDOMMountPoint.create(path, services, schemaContext);
164             return doRegisterMountPoint(mountPoint);
165         }
166     }
167 }