We have a tad of a mess here. isKeyedEntry() is really indicating
whether the pathArgument() is useable. Merge the logic to enable sane
operation:
- pathStep() returns @Nullable NodeIdentifier, effectively acting as
!isKeyedEntry()
- getPathStep() returns a @NonNull NodeIdentifier or throws.
Based on this, update PathMixin, which is now guaranteed to return a
NodeIdentifier (by deferring to getPathStep()).
JIRA: YANGTOOLS-1413
Change-Id: Ic7f566d37cf0867122a472e879b2665624d5bc74
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
12 files changed:
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
*/
sealed interface PathMixin extends DataSchemaContextNode permits AbstractMixinContextNode {
/**
*/
sealed interface PathMixin extends DataSchemaContextNode permits AbstractMixinContextNode {
/**
- * The mixed-in {@link PathArgument}.
+ * The mixed-in {@link NodeIdentifier}.
- * @return Mixed-in PathArgument
+ * @return Mixed-in NodeIdentifier
- @NonNull PathArgument mixinPathArgument();
+ default @NonNull NodeIdentifier mixinPathStep() {
+ return getPathStep();
+ }
@NonNull DataSchemaNode getDataSchemaNode();
@NonNull DataSchemaNode getDataSchemaNode();
- // FIXME: YANGTOOLS-1413: this idea is wrong -- if does the wrong thing for items of leaf-list and keyed list
- // because those identifiers need a value.
- @NonNull PathArgument pathArgument();
+ /**
+ * Return the fixed {@link YangInstanceIdentifier} step, if available. This method returns {@code null} for contexts
+ * like {@link MapEntryNode} and {@link LeafSetEntryNode}, where the step depends on the actual node value.
+ *
+ * @return A {@link NodeIdentifier}, or {@code null}
+ */
+ @Nullable NodeIdentifier pathStep();
- // FIXME: YANGTOOLS-1413: document this method and (most likely) split it out to a separate interface
- boolean isKeyedEntry();
+ /**
+ * Return the fixed {@link YangInstanceIdentifier} step.
+ *
+ * @return A {@link NodeIdentifier}
+ * @throws UnsupportedOperationException if this node does not have fixed step
+ */
+ default @NonNull NodeIdentifier getPathStep() {
+ final var arg = pathStep();
+ if (arg != null) {
+ return arg;
+ }
+ throw new UnsupportedOperationException(this + " does not have a fixed path step");
+ }
/**
* Find a child node identifier by its {@link PathArgument}.
/**
* Find a child node identifier by its {@link PathArgument}.
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.concepts.Mutable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
current = current.getChild(name);
checkValid(current != null, "%s is not correct schema node identifier.", name);
while (current instanceof PathMixin mixin) {
current = current.getChild(name);
checkValid(current != null, "%s is not correct schema node identifier.", name);
while (current instanceof PathMixin mixin) {
- product.add(mixin.mixinPathArgument());
+ product.add(mixin.mixinPathStep());
current = current.getChild(name);
}
stack.enterDataTree(name);
current = current.getChild(name);
}
stack.enterDataTree(name);
* @return PathArgument representing node selection with predictes
*/
private PathArgument computeIdentifierWithPredicate(final QName name) {
* @return PathArgument representing node selection with predictes
*/
private PathArgument computeIdentifierWithPredicate(final QName name) {
- final DataSchemaContextNode currentNode = nextContextNode(name);
- checkValid(currentNode.isKeyedEntry(), "Entry %s does not allow specifying predicates.", name);
+ final var currentNode = nextContextNode(name);
+ if (currentNode.pathStep() != null) {
+ throw iae("Entry %s does not allow specifying predicates.", name);
+ }
- ImmutableMap.Builder<QName, Object> keyValues = ImmutableMap.builder();
+ final var keyValues = ImmutableMap.<QName, Object>builder();
while (!allCharactersConsumed() && PRECONDITION_START == currentChar()) {
skipCurrentChar();
skipWhitespaces();
while (!allCharactersConsumed() && PRECONDITION_START == currentChar()) {
skipCurrentChar();
skipWhitespaces();
return tmp.resolveLeafref(type);
}
return tmp.resolveLeafref(type);
}
- private PathArgument computeIdentifier(final QName name) {
- DataSchemaContextNode currentNode = nextContextNode(name);
- checkValid(!currentNode.isKeyedEntry(), "Entry %s requires key or value predicate to be present", name);
- return currentNode.pathArgument();
+ private @NonNull NodeIdentifier computeIdentifier(final QName name) {
+ final var currentNode = nextContextNode(name);
+ final var currentArg = currentNode.pathStep();
+ if (currentArg == null) {
+ throw iae("Entry %s requires key or value predicate to be present", name);
+ }
+ return currentArg;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.eclipse.jdt.annotation.NonNull;
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.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
* since the mapping is not one-to-one.
*/
public abstract class AbstractDataSchemaContextNode implements DataSchemaContextNode {
* since the mapping is not one-to-one.
*/
public abstract class AbstractDataSchemaContextNode implements DataSchemaContextNode {
- // FIXME: YANGTOOLS-1413: this field should not be needed
- private final @NonNull PathArgument pathArgument;
+ private final @Nullable NodeIdentifier pathStep;
final @NonNull DataSchemaNode dataSchemaNode;
final @NonNull DataSchemaNode dataSchemaNode;
- AbstractDataSchemaContextNode(final PathArgument pathArgument, final DataSchemaNode dataSchemaNode) {
+ AbstractDataSchemaContextNode(final NodeIdentifier pathStep, final DataSchemaNode dataSchemaNode) {
this.dataSchemaNode = requireNonNull(dataSchemaNode);
this.dataSchemaNode = requireNonNull(dataSchemaNode);
- this.pathArgument = requireNonNull(pathArgument);
+ this.pathStep = pathStep;
- public final PathArgument pathArgument() {
- return pathArgument;
- }
-
- @Override
- public boolean isKeyedEntry() {
- return false;
+ public final NodeIdentifier pathStep() {
+ return pathStep;
}
Set<QName> qnameIdentifiers() {
}
Set<QName> qnameIdentifiers() {
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
abstract class AbstractInteriorContextNode extends AbstractDataSchemaContextNode {
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
abstract class AbstractInteriorContextNode extends AbstractDataSchemaContextNode {
- AbstractInteriorContextNode(final PathArgument pathArgument, final DataSchemaNode schema) {
- super(pathArgument, schema);
+ AbstractInteriorContextNode(final NodeIdentifier pathStep, final DataSchemaNode schema) {
+ super(pathStep, schema);
}
}
\ No newline at end of file
}
}
\ No newline at end of file
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
import org.opendaylight.yangtools.yang.common.QName;
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
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.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
abstract class AbstractLeafContextNode extends AbstractDataSchemaContextNode {
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
abstract class AbstractLeafContextNode extends AbstractDataSchemaContextNode {
- AbstractLeafContextNode(final PathArgument pathArgument, final DataSchemaNode schema) {
- super(pathArgument, schema);
+ AbstractLeafContextNode(final NodeIdentifier pathStep, final DataSchemaNode schema) {
+ super(pathStep, schema);
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
* {@link ListItemContextNode}.
*/
abstract class AbstractListItemContextNode extends DataContainerContextNode {
* {@link ListItemContextNode}.
*/
abstract class AbstractListItemContextNode extends DataContainerContextNode {
- AbstractListItemContextNode(final PathArgument pathArgument, final DataNodeContainer container,
+ AbstractListItemContextNode(final NodeIdentifier pathStep, final DataNodeContainer container,
final DataSchemaNode schema) {
final DataSchemaNode schema) {
- super(pathArgument, container, schema);
+ super(pathStep, container, schema);
- protected final DataSchemaContextNode enterChild(final QName child, final SchemaInferenceStack stack) {
+ final DataSchemaContextNode enterChild(final QName child, final SchemaInferenceStack stack) {
// Stack is already pointing to the corresponding statement, now we are just working with the child
return getChild(child);
}
@Override
// Stack is already pointing to the corresponding statement, now we are just working with the child
return getChild(child);
}
@Override
- protected final DataSchemaContextNode enterChild(final PathArgument child, final SchemaInferenceStack stack) {
+ final DataSchemaContextNode enterChild(final PathArgument child, final SchemaInferenceStack stack) {
return getChild(child);
}
}
return getChild(child);
}
}
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode.PathMixin;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode.PathMixin;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
AbstractMixinContextNode(final DataSchemaNode schema) {
super(NodeIdentifier.create(schema.getQName()), schema);
}
AbstractMixinContextNode(final DataSchemaNode schema) {
super(NodeIdentifier.create(schema.getQName()), schema);
}
-
- @Override
- public PathArgument mixinPathArgument() {
- return pathArgument();
- }
}
\ No newline at end of file
}
\ No newline at end of file
for (var caze : schema.getCases()) {
for (var cazeChild : caze.getChildNodes()) {
final var childOp = AbstractDataSchemaContextNode.of(cazeChild);
for (var caze : schema.getCases()) {
for (var cazeChild : caze.getChildNodes()) {
final var childOp = AbstractDataSchemaContextNode.of(cazeChild);
- byArgBuilder.put(childOp.pathArgument(), childOp);
+ byArgBuilder.put(childOp.getPathStep(), childOp);
childToCaseBuilder.put(childOp, caze.getQName());
for (QName qname : childOp.qnameIdentifiers()) {
byQNameBuilder.put(qname, childOp);
childToCaseBuilder.put(childOp, caze.getQName());
for (QName qname : childOp.qnameIdentifiers()) {
byQNameBuilder.put(qname, childOp);
- protected DataSchemaContextNode enterChild(final QName child, final SchemaInferenceStack stack) {
+ DataSchemaContextNode enterChild(final QName child, final SchemaInferenceStack stack) {
return pushToStack(getChild(child), stack);
}
@Override
return pushToStack(getChild(child), stack);
}
@Override
- protected DataSchemaContextNode enterChild(final PathArgument child, final SchemaInferenceStack stack) {
+ DataSchemaContextNode enterChild(final PathArgument child, final SchemaInferenceStack stack) {
return pushToStack(getChild(child), stack);
}
return pushToStack(getChild(child), stack);
}
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.eclipse.jdt.annotation.NonNull;
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.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
private final ConcurrentMap<QName, AbstractDataSchemaContextNode> byQName = new ConcurrentHashMap<>();
private final DataNodeContainer container;
private final ConcurrentMap<QName, AbstractDataSchemaContextNode> byQName = new ConcurrentHashMap<>();
private final DataNodeContainer container;
- DataContainerContextNode(final PathArgument pathArgument, final DataNodeContainer container,
+ DataContainerContextNode(final NodeIdentifier pathStep, final DataNodeContainer container,
final DataSchemaNode schema) {
final DataSchemaNode schema) {
- super(pathArgument, schema);
+ super(pathStep, schema);
this.container = requireNonNull(container);
}
@Override
this.container = requireNonNull(container);
}
@Override
- public AbstractDataSchemaContextNode getChild(final PathArgument child) {
- var potential = byArg.get(child);
- if (potential != null) {
- return potential;
+ public final AbstractDataSchemaContextNode getChild(final PathArgument child) {
+ final var existing = byArg.get(child);
+ if (existing != null) {
+ return existing;
- potential = fromLocalSchema(child);
- return register(potential);
+ return register(fromLocalSchema(child));
- public AbstractDataSchemaContextNode getChild(final QName child) {
- AbstractDataSchemaContextNode potential = byQName.get(child);
- if (potential != null) {
- return potential;
+ public final AbstractDataSchemaContextNode getChild(final QName child) {
+ var existing = byQName.get(child);
+ if (existing != null) {
+ return existing;
- potential = fromLocalSchemaAndQName(container, child);
- return register(potential);
+ return register(fromLocalSchemaAndQName(container, child));
- protected final DataSchemaContextNode enterChild(final QName child, final SchemaInferenceStack stack) {
+ final DataSchemaContextNode enterChild(final QName child, final SchemaInferenceStack stack) {
return pushToStack(getChild(child), stack);
}
@Override
return pushToStack(getChild(child), stack);
}
@Override
- protected final DataSchemaContextNode enterChild(final PathArgument child, final SchemaInferenceStack stack) {
+ final DataSchemaContextNode enterChild(final PathArgument child, final SchemaInferenceStack stack) {
return pushToStack(getChild(child), stack);
}
return pushToStack(getChild(child), stack);
}
return fromSchemaAndQNameChecked(container, child.getNodeType());
}
return fromSchemaAndQNameChecked(container, child.getNodeType());
}
- protected AbstractDataSchemaContextNode fromLocalSchemaAndQName(final DataNodeContainer schema,
+ private static AbstractDataSchemaContextNode fromLocalSchemaAndQName(final DataNodeContainer schema,
final QName child) {
return fromSchemaAndQNameChecked(schema, child);
}
final QName child) {
return fromSchemaAndQNameChecked(schema, child);
}
private AbstractDataSchemaContextNode register(final AbstractDataSchemaContextNode potential) {
if (potential != null) {
// FIXME: use putIfAbsent() to make sure we do not perform accidental overrwrites
private AbstractDataSchemaContextNode register(final AbstractDataSchemaContextNode potential) {
if (potential != null) {
// FIXME: use putIfAbsent() to make sure we do not perform accidental overrwrites
- byArg.put(potential.pathArgument(), potential);
+ byArg.put(potential.getPathStep(), potential);
for (QName qname : potential.qnameIdentifiers()) {
byQName.put(qname, potential);
}
for (QName qname : potential.qnameIdentifiers()) {
byQName.put(qname, potential);
}
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
-import org.opendaylight.yangtools.yang.common.Empty;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode.SimpleValue;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
public final class LeafListEntryContextNode extends AbstractLeafContextNode implements SimpleValue {
LeafListEntryContextNode(final LeafListSchemaNode schema) {
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextNode.SimpleValue;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
public final class LeafListEntryContextNode extends AbstractLeafContextNode implements SimpleValue {
LeafListEntryContextNode(final LeafListSchemaNode schema) {
- // FIXME: YANGTOOLS-1413: Empty() here is NOT NICE -- it assumes the list is of such entries...
- super(new NodeWithValue<>(schema.getQName(), Empty.value()), schema);
- }
-
- @Override
- public boolean isKeyedEntry() {
- return true;
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
*/
package org.opendaylight.yangtools.yang.data.util.impl.legacy;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
final class MapItemContextNode extends AbstractListItemContextNode {
MapItemContextNode(final ListSchemaNode schema) {
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
final class MapItemContextNode extends AbstractListItemContextNode {
MapItemContextNode(final ListSchemaNode schema) {
- // FIXME: YANGTOOLS-1413: this is wrong: we have no predicates at all!
- super(NodeIdentifierWithPredicates.of(schema.getQName()), schema, schema);
- }
-
- @Override
- public boolean isKeyedEntry() {
- return true;
+ super(null, schema, schema);
}
}
\ No newline at end of file
}
}
\ No newline at end of file