*/
package org.opendaylight.yangtools.yang.data.util;
-
-import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
-import java.util.Collections;
-import java.util.HashSet;
+import com.google.common.collect.Iterables;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
-import javax.annotation.Nullable;
-import org.opendaylight.yangtools.concepts.Identifiable;
+import java.util.stream.Collectors;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.concepts.AbstractIdentifiable;
import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
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.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AnydataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AnyxmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
/**
- * Schema derived data providing necessary information for mapping
- * between {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode}
- * and serialization format defined in RFC6020, since the mapping
- * is not one-to-one.
+ * Schema derived data providing necessary information for mapping between
+ * {@link org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode} and serialization format defined in RFC6020,
+ * since the mapping is not one-to-one.
*
* @param <T> Path Argument type
- *
*/
-public abstract class DataSchemaContextNode<T extends PathArgument> implements Identifiable<T> {
-
- private final T identifier;
+public abstract class DataSchemaContextNode<T extends PathArgument> extends AbstractIdentifiable<T> {
private final DataSchemaNode dataSchemaNode;
- @Override
- public T getIdentifier() {
- return identifier;
- };
-
protected DataSchemaContextNode(final T identifier, final SchemaNode schema) {
- super();
- this.identifier = identifier;
+ super(identifier);
if (schema instanceof DataSchemaNode) {
this.dataSchemaNode = (DataSchemaNode) schema;
} else {
return false;
}
+ public abstract boolean isLeaf();
+
protected Set<QName> getQNameIdentifiers() {
- return Collections.singleton(identifier.getNodeType());
+ return ImmutableSet.of(getIdentifier().getNodeType());
}
- public abstract @Nullable DataSchemaContextNode<?> getChild(final PathArgument child);
+ /**
+ * Find a child node identifier by its {@link PathArgument}.
+ *
+ * @param child Child path argument
+ * @return A child node, or null if not found
+ */
+ public abstract @Nullable DataSchemaContextNode<?> getChild(PathArgument child);
public abstract @Nullable DataSchemaContextNode<?> getChild(QName child);
- public abstract boolean isLeaf();
-
-
public @Nullable DataSchemaNode getDataSchemaNode() {
return dataSchemaNode;
}
- static final DataSchemaNode findChildSchemaNode(final DataNodeContainer parent, final QName child) {
- DataSchemaNode potential = parent.getDataChildByName(child);
- if (potential == null) {
- Iterable<ChoiceSchemaNode> choices = FluentIterable.from(
- parent.getChildNodes()).filter(ChoiceSchemaNode.class);
- potential = findChoice(choices, child);
+ /**
+ * Find a child node as identified by a {@link YangInstanceIdentifier} relative to this node.
+ *
+ * @param path Path towards the child node
+ * @return Child node if present, or empty when corresponding child is not found.
+ * @throws NullPointerException if {@code path} is null
+ */
+ public final @NonNull Optional<@NonNull DataSchemaContextNode<?>> findChild(
+ final @NonNull YangInstanceIdentifier path) {
+ DataSchemaContextNode<?> currentOp = this;
+ for (PathArgument arg : path.getPathArguments()) {
+ currentOp = currentOp.getChild(arg);
+ if (currentOp == null) {
+ return Optional.empty();
+ }
}
- return potential;
+ return Optional.of(currentOp);
+ }
+
+ static DataSchemaNode findChildSchemaNode(final DataNodeContainer parent, final QName child) {
+ final DataSchemaNode potential = parent.getDataChildByName(child);
+ return potential == null ? findChoice(Iterables.filter(parent.getChildNodes(), ChoiceSchemaNode.class), child)
+ : potential;
}
static DataSchemaContextNode<?> fromSchemaAndQNameChecked(final DataNodeContainer schema, final QName child) {
- DataSchemaNode result = findChildSchemaNode(schema, child);
+ final DataSchemaNode result = findChildSchemaNode(schema, child);
// We try to look up if this node was added by augmentation
- if ((schema instanceof DataSchemaNode) && result.isAugmenting()) {
+ if (result != null && schema instanceof DataSchemaNode && result.isAugmenting()) {
return fromAugmentation(schema, (AugmentationTarget) schema, result);
}
return fromDataSchemaNode(result);
}
+ // FIXME: this looks like it should be a Predicate on a stream with findFirst()
private static ChoiceSchemaNode findChoice(final Iterable<ChoiceSchemaNode> choices, final QName child) {
- ChoiceSchemaNode foundChoice = null;
- choiceLoop: for (ChoiceSchemaNode choice : choices) {
- for (ChoiceCaseNode caze : choice.getCases()) {
+ for (ChoiceSchemaNode choice : choices) {
+ // FIXME: this looks weird: what are we looking for again?
+ for (CaseSchemaNode caze : choice.getCases()) {
if (findChildSchemaNode(caze, child) != null) {
- foundChoice = choice;
- break choiceLoop;
+ return choice;
}
}
}
- return foundChoice;
- }
-
- public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchema augmentation) {
- ImmutableSet.Builder<QName> potentialChildren = ImmutableSet.builder();
- for (DataSchemaNode child : augmentation.getChildNodes()) {
- potentialChildren.add(child.getQName());
- }
- return new AugmentationIdentifier(potentialChildren.build());
+ return null;
}
- static DataNodeContainer augmentationProxy(final AugmentationSchema augmentation,
- final DataNodeContainer schema) {
- Set<DataSchemaNode> children = new HashSet<>();
- for (DataSchemaNode augNode : augmentation.getChildNodes()) {
- children.add(schema.getDataChildByName(augNode.getQName()));
- }
- return new EffectiveAugmentationSchema(augmentation, children);
+ /**
+ * Create AugmentationIdentifier from an AugmentationSchemaNode.
+ *
+ * @param schema Augmentation schema
+ * @return AugmentationIdentifier for the schema
+ * @throws NullPointerException if {@code schema} is null
+ */
+ public static AugmentationIdentifier augmentationIdentifierFrom(final AugmentationSchemaNode schema) {
+ return new AugmentationIdentifier(schema.getChildNodes().stream().map(DataSchemaNode::getQName)
+ .collect(Collectors.toSet()));
}
/**
* 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)}.
- *
- *
- * @param parent
- * @param parentAug
- * @param child
- * @return
*/
static @Nullable DataSchemaContextNode<?> fromAugmentation(final DataNodeContainer parent,
final AugmentationTarget parentAug, final DataSchemaNode child) {
- AugmentationSchema augmentation = null;
- for (AugmentationSchema aug : parentAug.getAvailableAugmentations()) {
- DataSchemaNode potential = aug.getDataChildByName(child.getQName());
- if (potential != null) {
- augmentation = aug;
- break;
+ for (AugmentationSchemaNode aug : parentAug.getAvailableAugmentations()) {
+ if (aug.findDataChildByName(child.getQName()).isPresent()) {
+ return new AugmentationContextNode(aug, parent);
}
}
- if (augmentation != null) {
- return new AugmentationContextNode(augmentation, parent);
- }
return fromDataSchemaNode(child);
}
return new ChoiceNodeContextNode((ChoiceSchemaNode) potential);
} else if (potential instanceof LeafListSchemaNode) {
return fromLeafListSchemaNode((LeafListSchemaNode) potential);
- } else if (potential instanceof AnyXmlSchemaNode) {
- return new AnyXmlContextNode((AnyXmlSchemaNode) potential);
+ } else if (potential instanceof AnydataSchemaNode) {
+ return new AnydataContextNode((AnydataSchemaNode) potential);
+ } else if (potential instanceof AnyxmlSchemaNode) {
+ return new AnyXmlContextNode((AnyxmlSchemaNode) potential);
}
return null;
}
return new UnorderedLeafListMixinContextNode(potential);
}
- public static DataSchemaContextNode<?> from(final SchemaContext ctx) {
+ public static DataSchemaContextNode<?> from(final EffectiveModelContext ctx) {
return new ContainerContextNode(ctx);
}
}