import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-abstract class AbstractInteriorContextNode<T extends PathArgument> extends
- DataSchemaContextNode<T> {
-
- protected AbstractInteriorContextNode(final T identifier, final DataSchemaNode schema) {
+abstract class AbstractInteriorContextNode<T extends PathArgument> extends DataSchemaContextNode<T> {
+ AbstractInteriorContextNode(final T identifier, final DataSchemaNode schema) {
super(identifier, schema);
}
@Override
- public boolean isLeaf() {
+ public final boolean isLeaf() {
return false;
}
-
}
\ No newline at end of file
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-abstract class AbstractMixinContextNode<T extends PathArgument> extends
- AbstractInteriorContextNode<T> {
-
- protected AbstractMixinContextNode(final T identifier, final DataSchemaNode schema) {
+abstract class AbstractMixinContextNode<T extends PathArgument> extends AbstractInteriorContextNode<T> {
+ AbstractMixinContextNode(final T identifier, final DataSchemaNode schema) {
super(identifier, schema);
}
public final boolean isMixin() {
return true;
}
-
}
\ No newline at end of file
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
abstract class AbstractOpaqueContextNode<S extends DataSchemaNode> extends AbstractLeafContextNode<NodeIdentifier, S> {
- AbstractOpaqueContextNode(S schema) {
+ AbstractOpaqueContextNode(final S schema) {
super(NodeIdentifier.create(schema.getQName()), schema);
}
import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
final class AugmentationContextNode extends DataContainerContextNode<AugmentationIdentifier> {
- AugmentationContextNode(final AugmentationSchemaNode augmentation, final DataNodeContainer schema) {
- super(augmentationIdentifierFrom(augmentation), new EffectiveAugmentationSchema(augmentation, schema), null);
+ AugmentationContextNode(final AugmentationSchemaNode augmentation, final DataNodeContainer target) {
+ super(augmentationIdentifierFrom(augmentation), new EffectiveAugmentationSchema(augmentation, target), null);
}
@Override
if (schema instanceof DataSchemaNode && result.isAugmenting()) {
return fromAugmentation(schema, (AugmentationTarget) schema, result);
}
- return fromDataSchemaNode(result);
+ return lenientOf(result);
}
@Override
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-class ChoiceNodeContextNode extends AbstractMixinContextNode<NodeIdentifier> {
-
+final class ChoiceNodeContextNode extends AbstractMixinContextNode<NodeIdentifier> {
private final ImmutableMap<QName, DataSchemaContextNode<?>> byQName;
private final ImmutableMap<PathArgument, DataSchemaContextNode<?>> byArg;
- protected ChoiceNodeContextNode(final ChoiceSchemaNode schema) {
+ ChoiceNodeContextNode(final ChoiceSchemaNode schema) {
super(NodeIdentifier.create(schema.getQName()), schema);
ImmutableMap.Builder<QName, DataSchemaContextNode<?>> byQNameBuilder = ImmutableMap.builder();
ImmutableMap.Builder<PathArgument, DataSchemaContextNode<?>> byArgBuilder = ImmutableMap.builder();
for (CaseSchemaNode caze : schema.getCases()) {
for (DataSchemaNode cazeChild : caze.getChildNodes()) {
- DataSchemaContextNode<?> childOp = fromDataSchemaNode(cazeChild);
+ DataSchemaContextNode<?> childOp = DataSchemaContextNode.of(cazeChild);
byArgBuilder.put(childOp.getIdentifier(), childOp);
for (QName qname : childOp.getQNameIdentifiers()) {
byQNameBuilder.put(qname, childOp);
*/
package org.opendaylight.yangtools.yang.data.util;
-import java.util.Map;
+import static java.util.Objects.requireNonNull;
+
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
-class DataContainerContextNode<T extends PathArgument> extends
- AbstractInteriorContextNode<T> {
-
- private final DataNodeContainer schema;
- private final Map<QName, DataSchemaContextNode<?>> byQName;
- private final Map<PathArgument, DataSchemaContextNode<?>> byArg;
+abstract class DataContainerContextNode<T extends PathArgument> extends AbstractInteriorContextNode<T> {
+ private final ConcurrentMap<PathArgument, DataSchemaContextNode<?>> byArg = new ConcurrentHashMap<>();
+ private final ConcurrentMap<QName, DataSchemaContextNode<?>> byQName = new ConcurrentHashMap<>();
+ private final DataNodeContainer container;
- protected DataContainerContextNode(final T identifier, final DataNodeContainer schema,
- final DataSchemaNode node) {
- super(identifier, node);
- this.schema = schema;
- this.byArg = new ConcurrentHashMap<>();
- this.byQName = new ConcurrentHashMap<>();
+ DataContainerContextNode(final T identifier, final DataNodeContainer container, final DataSchemaNode schema) {
+ super(identifier, schema);
+ this.container = requireNonNull(container);
}
@Override
if (potential != null) {
return potential;
}
- potential = fromLocalSchemaAndQName(schema, child);
+ potential = fromLocalSchemaAndQName(container, child);
return register(potential);
}
private DataSchemaContextNode<?> fromLocalSchema(final PathArgument child) {
if (child instanceof AugmentationIdentifier) {
- return fromSchemaAndQNameChecked(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
+ return fromSchemaAndQNameChecked(container, ((AugmentationIdentifier) child).getPossibleChildNames()
.iterator().next());
}
- return fromSchemaAndQNameChecked(schema, child.getNodeType());
+ return fromSchemaAndQNameChecked(container, child.getNodeType());
}
protected DataSchemaContextNode<?> fromLocalSchemaAndQName(final DataNodeContainer schema2, final QName child) {
private DataSchemaContextNode<?> register(final DataSchemaContextNode<?> potential) {
if (potential != null) {
+ // FIXME: use putIfAbsent() to make sure we do not perform accidental overrwrites
byArg.put(potential.getIdentifier(), potential);
for (QName qname : potential.getQNameIdentifiers()) {
byQName.put(qname, potential);
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
-import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
* @param <T> Path Argument type
*/
public abstract class DataSchemaContextNode<T extends PathArgument> extends AbstractSimpleIdentifiable<T> {
+ // FIXME: this can be null only for AugmentationContextNode and in that case the interior part is handled by a
+ // separate field in DataContainerContextNode. We need to re-examine our base interface class hierarchy
+ // so that the underlying (effective in augment's case) SchemaNode is always available.
private final DataSchemaNode dataSchemaNode;
- protected DataSchemaContextNode(final T identifier, final SchemaNode schema) {
+ DataSchemaContextNode(final T identifier, final DataSchemaNode schema) {
super(identifier);
- if (schema instanceof DataSchemaNode) {
- this.dataSchemaNode = (DataSchemaNode) schema;
- } else {
- this.dataSchemaNode = null;
- }
+ this.dataSchemaNode = schema;
}
+ @Deprecated(forRemoval = true, since = "8.0.2")
+ protected DataSchemaContextNode(final T identifier, final SchemaNode schema) {
+ this(identifier, schema instanceof DataSchemaNode ? (DataSchemaNode) schema : null);
+ }
+
+ // FIXME: document this method
public boolean isMixin() {
return false;
}
+ // FIXME: document this method
public boolean isKeyedEntry() {
return false;
}
+ // FIXME: this is counter-intuitive: anydata/anyxml are considered non-leaf. This method needs a better name and
+ // a proper description.
public abstract boolean isLeaf();
protected Set<QName> getQNameIdentifiers() {
* @param child Child path argument
* @return A child node, or null if not found
*/
+ // FIXME: document PathArgument type mismatch
public abstract @Nullable DataSchemaContextNode<?> getChild(PathArgument child);
+ // FIXME: document child == null
public abstract @Nullable DataSchemaContextNode<?> getChild(QName child);
+ // FIXME: final
public @Nullable DataSchemaNode getDataSchemaNode() {
return dataSchemaNode;
}
if (result != null && schema instanceof DataSchemaNode && result.isAugmenting()) {
return fromAugmentation(schema, (AugmentationTarget) schema, result);
}
- return fromDataSchemaNode(result);
+ return lenientOf(result);
}
// FIXME: this looks like it should be a Predicate on a stream with findFirst()
.collect(Collectors.toSet()));
}
+ static @NonNull DataSchemaContextNode<?> of(final @NonNull DataSchemaNode schema) {
+ if (schema instanceof ContainerLike) {
+ return new ContainerContextNode((ContainerLike) schema);
+ } else if (schema instanceof ListSchemaNode) {
+ return fromListSchemaNode((ListSchemaNode) schema);
+ } else if (schema instanceof LeafSchemaNode) {
+ return new LeafContextNode((LeafSchemaNode) schema);
+ } else if (schema instanceof ChoiceSchemaNode) {
+ return new ChoiceNodeContextNode((ChoiceSchemaNode) schema);
+ } else if (schema instanceof LeafListSchemaNode) {
+ return fromLeafListSchemaNode((LeafListSchemaNode) schema);
+ } else if (schema instanceof AnydataSchemaNode) {
+ return new AnydataContextNode((AnydataSchemaNode) schema);
+ } else if (schema instanceof AnyxmlSchemaNode) {
+ return new AnyXmlContextNode((AnyxmlSchemaNode) schema);
+ } else {
+ throw new IllegalStateException("Unhandled schema " + schema);
+ }
+ }
+
+ // FIXME: do we tolerate null argument? do we tolerate unknown subclasses?
+ static @Nullable DataSchemaContextNode<?> lenientOf(final @Nullable DataSchemaNode schema) {
+ if (schema instanceof ContainerLike) {
+ return new ContainerContextNode((ContainerLike) schema);
+ } else if (schema instanceof ListSchemaNode) {
+ return fromListSchemaNode((ListSchemaNode) schema);
+ } else if (schema instanceof LeafSchemaNode) {
+ return new LeafContextNode((LeafSchemaNode) schema);
+ } else if (schema instanceof ChoiceSchemaNode) {
+ return new ChoiceNodeContextNode((ChoiceSchemaNode) schema);
+ } else if (schema instanceof LeafListSchemaNode) {
+ return fromLeafListSchemaNode((LeafListSchemaNode) schema);
+ } else if (schema instanceof AnydataSchemaNode) {
+ return new AnydataContextNode((AnydataSchemaNode) schema);
+ } else if (schema instanceof AnyxmlSchemaNode) {
+ return new AnyXmlContextNode((AnyxmlSchemaNode) schema);
+ } else {
+ return null;
+ }
+ }
+
/**
* Returns a DataContextNodeOperation for provided child node
*
* <p>
- * If supplied child is added by Augmentation this operation returns a
- * DataContextNodeOperation for augmentation, otherwise returns a
- * DataContextNodeOperation for child as call for
- * {@link #fromDataSchemaNode(DataSchemaNode)}.
+ * If supplied child is added by Augmentation this operation returns a DataSchemaContextNode for augmentation,
+ * otherwise returns a DataSchemaContextNode for child as call for {@link #lenientOf(DataSchemaNode)}.
*/
static @Nullable DataSchemaContextNode<?> fromAugmentation(final DataNodeContainer parent,
final AugmentationTarget parentAug, final DataSchemaNode child) {
return new AugmentationContextNode(aug, parent);
}
}
- return fromDataSchemaNode(child);
+ return lenientOf(child);
}
+ /**
+ * Get a {@link DataSchemaContextNode} for a particular {@link DataSchemaNode}.
+ *
+ * @param potential Backing DataSchemaNode
+ * @return A {@link DataSchemaContextNode}, or null if the input is {@code null} or of unhandled type
+ */
+ @Deprecated(forRemoval = true, since = "8.0.2")
public static @Nullable DataSchemaContextNode<?> fromDataSchemaNode(final DataSchemaNode potential) {
- if (potential instanceof ContainerLike) {
- return new ContainerContextNode((ContainerLike) potential);
- } else if (potential instanceof ListSchemaNode) {
- return fromListSchemaNode((ListSchemaNode) potential);
- } else if (potential instanceof LeafSchemaNode) {
- return new LeafContextNode((LeafSchemaNode) potential);
- } else if (potential instanceof ChoiceSchemaNode) {
- return new ChoiceNodeContextNode((ChoiceSchemaNode) potential);
- } else if (potential instanceof LeafListSchemaNode) {
- return fromLeafListSchemaNode((LeafListSchemaNode) potential);
- } else if (potential instanceof AnydataSchemaNode) {
- return new AnydataContextNode((AnydataSchemaNode) potential);
- } else if (potential instanceof AnyxmlSchemaNode) {
- return new AnyXmlContextNode((AnyxmlSchemaNode) potential);
- }
- return null;
+ return lenientOf(potential);
}
- private static DataSchemaContextNode<?> fromListSchemaNode(final ListSchemaNode potential) {
- List<QName> keyDefinition = potential.getKeyDefinition();
- if (keyDefinition == null || keyDefinition.isEmpty()) {
+ private static @NonNull DataSchemaContextNode<?> fromListSchemaNode(final ListSchemaNode potential) {
+ var keyDefinition = potential.getKeyDefinition();
+ if (keyDefinition.isEmpty()) {
return new UnkeyedListMixinContextNode(potential);
- }
- if (potential.isUserOrdered()) {
+ } else if (potential.isUserOrdered()) {
return new OrderedMapMixinContextNode(potential);
+ } else {
+ return new UnorderedMapMixinContextNode(potential);
}
- return new UnorderedMapMixinContextNode(potential);
}
- private static DataSchemaContextNode<?> fromLeafListSchemaNode(final LeafListSchemaNode potential) {
+ private static @NonNull DataSchemaContextNode<?> fromLeafListSchemaNode(final LeafListSchemaNode potential) {
if (potential.isUserOrdered()) {
return new OrderedLeafListMixinContextNode(potential);
}
return new UnorderedLeafListMixinContextNode(potential);
}
- public static DataSchemaContextNode<?> from(final EffectiveModelContext ctx) {
+ /**
+ * Return a DataSchemaContextNode corresponding to specified {@link EffectiveModelContext}.
+ *
+ * @param ctx EffectiveModelContext
+ * @return A DataSchemaContextNode
+ * @throws NullPointerException if {@code ctx} is null
+ * @deprecated Use {@link DataSchemaContextTree#from(EffectiveModelContext)} and
+ * {@link DataSchemaContextTree#getRoot()} instead.
+ */
+ @Deprecated(forRemoval = true, since = "8.0.2")
+ public static @NonNull DataSchemaContextNode<?> from(final EffectiveModelContext ctx) {
return new ContainerContextNode(ctx);
}
}
* @author Robert Varga
*/
public final class DataSchemaContextTree extends AbstractEffectiveModelContextProvider {
- private static final LoadingCache<EffectiveModelContext, DataSchemaContextTree> TREES = CacheBuilder.newBuilder()
- .weakKeys().weakValues().build(new CacheLoader<EffectiveModelContext, DataSchemaContextTree>() {
- @Override
- public DataSchemaContextTree load(final EffectiveModelContext key) {
- return new DataSchemaContextTree(key);
- }
- });
+ private static final LoadingCache<EffectiveModelContext, @NonNull DataSchemaContextTree> TREES =
+ CacheBuilder.newBuilder().weakKeys().weakValues().build(new CacheLoader<>() {
+ @Override
+ public DataSchemaContextTree load(final EffectiveModelContext key) {
+ return new DataSchemaContextTree(key);
+ }
+ });
- private final DataSchemaContextNode<?> root;
+ private final @NonNull ContainerContextNode root;
private DataSchemaContextTree(final EffectiveModelContext ctx) {
super(ctx);
- root = DataSchemaContextNode.from(ctx);
+ root = new ContainerContextNode(ctx);
}
public static @NonNull DataSchemaContextTree from(final @NonNull EffectiveModelContext ctx) {
* @throws NullPointerException if {@code path} is null
*/
public @NonNull Optional<@NonNull DataSchemaContextNode<?>> findChild(final @NonNull YangInstanceIdentifier path) {
- return getRoot().findChild(path);
+ return root.findChild(path);
}
public @NonNull DataSchemaContextNode<?> getRoot() {
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
final class LeafContextNode extends AbstractLeafNodeContext<NodeIdentifier, LeafSchemaNode> {
- LeafContextNode(final LeafSchemaNode potential) {
- super(NodeIdentifier.create(potential.getQName()), potential);
+ LeafContextNode(final LeafSchemaNode schema) {
+ super(NodeIdentifier.create(schema.getQName()), schema);
}
}
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
final class LeafListEntryContextNode extends AbstractLeafNodeContext<NodeWithValue<?>, LeafListSchemaNode> {
- LeafListEntryContextNode(final LeafListSchemaNode potential) {
- super(new NodeWithValue<>(potential.getQName(), Empty.value()), potential);
+ LeafListEntryContextNode(final LeafListSchemaNode schema) {
+ // FIXME: Empty() here is NOT NICE -- it assumes the list is of such entries...
+ super(new NodeWithValue<>(schema.getQName(), Empty.value()), schema);
}
@Override
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-final class ListItemContextNode extends
- DataContainerContextNode<NodeIdentifierWithPredicates> {
-
-
- protected ListItemContextNode(final NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
+final class ListItemContextNode extends DataContainerContextNode<NodeIdentifierWithPredicates> {
+ ListItemContextNode(final NodeIdentifierWithPredicates identifier, final ListSchemaNode schema) {
super(identifier, schema, schema);
}
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
final class UnkeyedListItemContextNode extends DataContainerContextNode<NodeIdentifier> {
-
- protected UnkeyedListItemContextNode(final ListSchemaNode schema) {
+ UnkeyedListItemContextNode(final ListSchemaNode schema) {
super(NodeIdentifier.create(schema.getQName()), schema, schema);
}
-
}
*/
package org.opendaylight.yangtools.yang.data.util;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-class UnkeyedListMixinContextNode extends AbstractMixinContextNode<NodeIdentifier> {
-
+final class UnkeyedListMixinContextNode extends AbstractMixinContextNode<NodeIdentifier> {
private final UnkeyedListItemContextNode innerNode;
UnkeyedListMixinContextNode(final ListSchemaNode list) {
super(NodeIdentifier.create(list.getQName()), list);
- this.innerNode = new UnkeyedListItemContextNode(list);
+ innerNode = new UnkeyedListItemContextNode(list);
}
@Override
public DataSchemaContextNode<?> getChild(final PathArgument child) {
- if (child.getNodeType().equals(getIdentifier().getNodeType())) {
- return innerNode;
- }
- return null;
+ // FIXME: 10.0.0: checkArgument() on PathArgument
+ return innerNodeIfMatch(child.getNodeType());
}
@Override
public DataSchemaContextNode<?> getChild(final QName child) {
- if (getIdentifier().getNodeType().equals(child)) {
- return innerNode;
- }
- return null;
+ return innerNodeIfMatch(child);
}
+ // FIXME: dead ringers in other AbstractMixinContextNode subclasses
+ private @Nullable DataSchemaContextNode<?> innerNodeIfMatch(final QName qname) {
+ // FIXME: 10.0.0: requireNonNull(qname)
+ return getIdentifier().getNodeType().equals(qname) ? innerNode : null;
+ }
}
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
class UnorderedLeafListMixinContextNode extends AbstractMixinContextNode<NodeIdentifier> {
+ private final LeafListEntryContextNode innerOp;
- private final DataSchemaContextNode<?> innerOp;
-
- UnorderedLeafListMixinContextNode(final LeafListSchemaNode potential) {
- super(NodeIdentifier.create(potential.getQName()), potential);
- innerOp = new LeafListEntryContextNode(potential);
+ UnorderedLeafListMixinContextNode(final LeafListSchemaNode schema) {
+ super(NodeIdentifier.create(schema.getQName()), schema);
+ innerOp = new LeafListEntryContextNode(schema);
}
@Override
- public DataSchemaContextNode<?> getChild(final PathArgument child) {
- if (child instanceof NodeWithValue) {
- return innerOp;
- }
- return null;
+ public final DataSchemaContextNode<?> getChild(final PathArgument child) {
+ // FIXME: 10.0.0: reject null and invalid
+ return child instanceof NodeWithValue ? innerOp : null;
}
@Override
- public DataSchemaContextNode<?> getChild(final QName child) {
- if (getIdentifier().getNodeType().equals(child)) {
- return innerOp;
- }
- return null;
+ public final DataSchemaContextNode<?> getChild(final QName child) {
+ // FIXME: requireNonNull, common code with UnkeyedListMixinNode
+ return getIdentifier().getNodeType().equals(child) ? innerOp : null;
}
}
*/
package org.opendaylight.yangtools.yang.data.util;
+import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
UnorderedMapMixinContextNode(final ListSchemaNode list) {
super(NodeIdentifier.create(list.getQName()), list);
- this.innerNode = new ListItemContextNode(NodeIdentifierWithPredicates.of(list.getQName()), list);
+ innerNode = new ListItemContextNode(NodeIdentifierWithPredicates.of(list.getQName()), list);
}
@Override
- public DataSchemaContextNode<?> getChild(final PathArgument child) {
- if (child.getNodeType().equals(getIdentifier().getNodeType())) {
- return innerNode;
- }
- return null;
+ public final DataSchemaContextNode<?> getChild(final PathArgument child) {
+ // FIXME: validate PathArgument type
+ return innerNodeIfMatch(child.getNodeType());
}
@Override
- public DataSchemaContextNode<?> getChild(final QName child) {
- if (getIdentifier().getNodeType().equals(child)) {
- return innerNode;
- }
- return null;
+ public final DataSchemaContextNode<?> getChild(final QName child) {
+ return innerNodeIfMatch(child);
+ }
+
+ // FIXME: dead ringers in other AbstractMixinContextNode subclasses
+ private @Nullable DataSchemaContextNode<?> innerNodeIfMatch(final QName qname) {
+ // FIXME: 10.0.0: requireNonNull(qname)
+ return getIdentifier().getNodeType().equals(qname) ? innerNode : null;
}
}