--- /dev/null
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. 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.yangtools.yang.model.api;
+
+import static java.util.Objects.requireNonNull;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.AbstractList;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.Spliterator;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+
+final class PathFromRoot extends AbstractList<QName> implements Immutable {
+ private static final QName[] EMPTY_QNAMES = new QName[0];
+ private static final VarHandle QNAMES;
+
+ static {
+ try {
+ QNAMES = MethodHandles.lookup().findVarHandle(PathFromRoot.class, "qnames", QName[].class);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ private final SchemaPath path;
+
+ @SuppressWarnings("unused")
+ private QName @Nullable [] qnames;
+
+ PathFromRoot(final SchemaPath path) {
+ this.path = requireNonNull(path);
+ }
+
+ @Override
+ public Iterator<QName> iterator() {
+ return Arrays.asList(qnames()).iterator();
+ }
+
+ @Override
+ public Spliterator<QName> spliterator() {
+ return Arrays.spliterator(qnames());
+ }
+
+ @Override
+ public QName get(final int index) {
+ return qnames()[index];
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public int size() {
+ return qnames().length;
+ }
+
+ private QName @NonNull [] qnames() {
+ final QName[] local = (QName[]) QNAMES.getAcquire(this);
+ return local != null ? local : loadQNames();
+ }
+
+ private QName @NonNull [] loadQNames() {
+ final Deque<QName> tmp = new ArrayDeque<>();
+ for (QName qname : path.getPathTowardsRoot()) {
+ tmp.addFirst(qname);
+ }
+
+ final QName[] result = tmp.toArray(EMPTY_QNAMES);
+ // We do not care about atomicity here
+ QNAMES.setRelease(this, result);
+ return result;
+ }
+}
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
import com.google.common.collect.UnmodifiableIterator;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import org.eclipse.jdt.annotation.NonNull;
}
}
- private static final VarHandle LEGACY_PATH;
-
- static {
- try {
- LEGACY_PATH = MethodHandles.lookup().findVarHandle(SchemaPath.class, "legacyPath", ImmutableList.class);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
/**
* Shared instance of the conceptual root schema node.
*/
*/
private final int hash;
- /**
- * Cached legacy path, filled-in when {@link #getPath()} or {@link #getPathTowardsRoot()} is invoked.
- */
- @SuppressWarnings("unused")
- private volatile ImmutableList<QName> legacyPath;
-
SchemaPath(final SchemaPath parent, final QName qname) {
this.parent = parent;
this.qname = qname;
hash = tmp;
}
- private ImmutableList<QName> getLegacyPath() {
- final ImmutableList<QName> local = (ImmutableList<QName>) LEGACY_PATH.getAcquire(this);
- return local != null ? local : loadLegacyPath();
- }
-
- @SuppressWarnings("unchecked")
- private ImmutableList<QName> loadLegacyPath() {
- final List<QName> tmp = new ArrayList<>();
- for (QName item : getPathTowardsRoot()) {
- tmp.add(item);
- }
- final ImmutableList<QName> ret = ImmutableList.copyOf(Lists.reverse(tmp));
- final Object witness = LEGACY_PATH.compareAndExchangeRelease(this, null, ret);
- return witness == null ? ret : (ImmutableList<QName>) witness;
- }
-
/**
* Constructs new instance of this class with the concrete path.
*
* path from the root to the schema node.
*/
public Iterable<QName> getPathFromRoot() {
- return getLegacyPath();
+ if (qname == null) {
+ return ImmutableList.of();
+ }
+ return parent == null ? ImmutableList.of(qname) : new PathFromRoot(this);
}
/**