d9bfd8ce5151901c3a59648a916d4ef67acf8231
[mdsal.git] / binding / mdsal-binding-dom-adapter / src / main / java / org / opendaylight / mdsal / binding / dom / adapter / query / DefaultQueryResultItem.java
1 /*
2  * Copyright (c) 2020 PANTHEON.tech, 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.binding.dom.adapter.query;
9
10 import static java.util.Objects.requireNonNull;
11
12 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
13 import java.lang.invoke.MethodHandles;
14 import java.lang.invoke.MethodHandles.Lookup;
15 import java.lang.invoke.VarHandle;
16 import java.util.Map.Entry;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.mdsal.binding.api.query.QueryResult;
20 import org.opendaylight.yangtools.yang.binding.DataObject;
21 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
23 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
24
25 @NonNullByDefault
26 final class DefaultQueryResultItem<T extends DataObject> implements QueryResult.Item<T> {
27     private static final VarHandle OBJECT;
28     private static final VarHandle PATH;
29
30     static {
31         final Lookup lookup = MethodHandles.lookup();
32         try {
33             OBJECT = lookup.findVarHandle(DefaultQueryResultItem.class, "object", DataObject.class);
34             PATH = lookup.findVarHandle(DefaultQueryResultItem.class, "path", InstanceIdentifier.class);
35         } catch (NoSuchFieldException | IllegalAccessException e) {
36             throw new ExceptionInInitializerError(e);
37         }
38     }
39
40     private final Entry<YangInstanceIdentifier, NormalizedNode> domItem;
41     private final DefaultQueryResult<T> result;
42
43     @SuppressWarnings("unused")
44     @SuppressFBWarnings(value = "NP_STORE_INTO_NONNULL_FIELD", justification = "Ungrokked type annotation")
45     private volatile @Nullable InstanceIdentifier<T> path = null;
46     @SuppressWarnings("unused")
47     @SuppressFBWarnings(value = "NP_STORE_INTO_NONNULL_FIELD", justification = "Ungrokked type annotation")
48     private volatile @Nullable T object = null;
49
50     DefaultQueryResultItem(final DefaultQueryResult<T> result,
51             final Entry<YangInstanceIdentifier, NormalizedNode> domItem) {
52         this.result = requireNonNull(result);
53         this.domItem = requireNonNull(domItem);
54     }
55
56     @Override
57     public T object() {
58         final @Nullable T local = (T) OBJECT.getAcquire(this);
59         return local != null ? local : loadObject();
60     }
61
62     @Override
63     public InstanceIdentifier<T> path() {
64         final @Nullable InstanceIdentifier<T> local = (InstanceIdentifier<T>) PATH.getAcquire(this);
65         return local != null ? local : loadPath();
66     }
67
68     private T loadObject() {
69         final T ret = result.createObject(domItem);
70         final Object witness = OBJECT.compareAndExchangeRelease(this, null, ret);
71         return witness == null ? ret : (T) witness;
72     }
73
74     @SuppressWarnings("unchecked")
75     private InstanceIdentifier<T> loadPath() {
76         final InstanceIdentifier<T> ret = result.createPath(domItem.getKey());
77         final Object witness = PATH.compareAndExchangeRelease(this, null, ret);
78         return witness == null ? ret : (InstanceIdentifier<T>) witness;
79     }
80 }