/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.mdsal.binding.dom.adapter;
import static java.util.Objects.requireNonNull;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.time.Instant;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.mdsal.dom.api.DOMEvent;
import org.opendaylight.mdsal.dom.api.DOMNotification;
import org.opendaylight.yangtools.yang.binding.Notification;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
/**
* Lazy serialized implementation of DOM Notification.
*
*
* This implementation performs serialization of data, only if receiver of notification actually accessed data from
* notification.
*/
final class LazySerializedDOMNotification implements DOMNotification, DOMEvent {
private static final LoadingCache, Absolute> PATHS = CacheBuilder.newBuilder().weakKeys()
.build(new CacheLoader, Absolute>() {
@Override
public Absolute load(final Class> key) {
// TODO: for nested (YANG 1.1) notifications we will need the SchemaNodeIdentifier where the
// notification is being invoked and use that instead of ROOT. How Binding users will refer to
// it is TBD (but probably InstanceIdentifier, which means we will need to do some lifting to
// find the SchemaNodeIdentifier), as we will need to deal with the same multiplicies we need
// for data due to grouping-based reuse.
return Absolute.of(BindingReflections.findQName(key)).intern();
}
});
private final @NonNull BindingNormalizedNodeSerializer codec;
private final @NonNull Notification data;
private final @NonNull Absolute type;
private final @NonNull Instant eventInstant;
private volatile ContainerNode domBody;
LazySerializedDOMNotification(final BindingNormalizedNodeSerializer codec, final Notification data,
final Absolute type, final Instant eventInstant) {
this.codec = requireNonNull(codec);
this.data = requireNonNull(data);
this.type = requireNonNull(type);
this.eventInstant = requireNonNull(eventInstant);
}
static @NonNull DOMNotification create(final BindingNormalizedNodeSerializer codec, final Notification data,
final Instant eventInstant) {
final Absolute type = PATHS.getUnchecked(data.implementedInterface());
return new LazySerializedDOMNotification(codec, data, type, eventInstant);
}
@Override
public Absolute getType() {
return type;
}
@Override
public ContainerNode getBody() {
ContainerNode local = domBody;
if (local == null) {
domBody = local = codec.toNormalizedNodeNotification(data);
}
return local;
}
@Override
public Instant getEventInstant() {
return eventInstant;
}
@NonNull Notification getBindingData() {
return data;
}
}