847e0eb6ce0edfde03c488372200719cb80c7d4a
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / LazySerializedDOMNotification.java
1 /*
2  * Copyright (c) 2015 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.mdsal.binding.dom.adapter;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.cache.CacheBuilder;
13 import com.google.common.cache.CacheLoader;
14 import com.google.common.cache.LoadingCache;
15 import java.time.Instant;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
18 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
19 import org.opendaylight.mdsal.dom.api.DOMEvent;
20 import org.opendaylight.mdsal.dom.api.DOMNotification;
21 import org.opendaylight.yangtools.yang.binding.Notification;
22 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
23 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
24
25 /**
26  * Lazy serialized implementation of DOM Notification.
27  *
28  * <p>
29  * This implementation performs serialization of data, only if receiver of notification actually accessed data from
30  * notification.
31  */
32 public final class LazySerializedDOMNotification implements DOMNotification, DOMEvent {
33     private static final LoadingCache<Class<?>, Absolute> PATHS = CacheBuilder.newBuilder().weakKeys()
34             .build(new CacheLoader<Class<?>, Absolute>() {
35                 @Override
36                 public Absolute load(final Class<?> key) {
37                     // TODO: for nested (YANG 1.1) notifications we will need the SchemaNodeIdentifier where the
38                     //       notification is being invoked and use that instead of ROOT. How Binding users will refer to
39                     //       it is TBD (but probably InstanceIdentifier, which means we will need to do some lifting to
40                     //       find the SchemaNodeIdentifier)
41                     return Absolute.of(BindingReflections.findQName(key)).intern();
42                 }
43             });
44
45     private final @NonNull BindingNormalizedNodeSerializer codec;
46     private final @NonNull Notification data;
47     private final @NonNull Absolute type;
48     private final @NonNull Instant eventInstant;
49
50     private volatile ContainerNode domBody;
51
52     LazySerializedDOMNotification(final BindingNormalizedNodeSerializer codec, final Notification data,
53             final Absolute type, final Instant eventInstant) {
54         this.codec = requireNonNull(codec);
55         this.data = requireNonNull(data);
56         this.type = requireNonNull(type);
57         this.eventInstant = requireNonNull(eventInstant);
58     }
59
60     static @NonNull DOMNotification create(final BindingNormalizedNodeSerializer codec, final Notification data,
61             final Instant eventInstant) {
62         final Absolute type = PATHS.getUnchecked(data.implementedInterface());
63         return new LazySerializedDOMNotification(codec, data, type, eventInstant);
64     }
65
66     @Override
67     public Absolute getType() {
68         return type;
69     }
70
71     @Override
72     public ContainerNode getBody() {
73         ContainerNode local = domBody;
74         if (local == null) {
75             domBody = local = codec.toNormalizedNodeNotification(data);
76         }
77         return local;
78     }
79
80     @Override
81     public Instant getEventInstant() {
82         return eventInstant;
83     }
84
85     public @NonNull Notification getBindingData() {
86         return data;
87     }
88 }