Fix sonar complains
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / AttributeOperations.java
index 47eb72af14ad4e451ef3c7bc236484d782520005..6dbb82a773a575a0f5ab4ebd08fb249dd29037bf 100644 (file)
@@ -12,23 +12,26 @@ import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.collect.ImmutableList;
-import java.util.Collection;
+import com.google.common.collect.ImmutableSet;
 import java.util.Iterator;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.AsPath;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.ClusterId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.OriginatorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.as.path.Segments;
+import org.opendaylight.protocol.util.Values;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.AsPath;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.ClusterId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Communities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.ExtendedCommunities;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.Origin;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.OriginatorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.UnrecognizedAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.attributes.as.path.Segments;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.CSegment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.AList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.as.path.segment.c.segment.a.list._case.a.list.AsSequence;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 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.schema.ChoiceNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
@@ -42,7 +45,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,178 +62,223 @@ final class AttributeOperations {
                 return new AttributeOperations(key);
             }
         });
-
+    private static final LoadingCache<QNameModule, ImmutableSet<QName>> TRANSITIVE_CACHE = CacheBuilder.newBuilder()
+        .weakKeys()
+        .weakValues().build(
+            new CacheLoader<QNameModule, ImmutableSet<QName>>() {
+                @Override
+                public ImmutableSet<QName> load(final QNameModule key) {
+                    return ImmutableSet.of(QName.create(key, Origin.QNAME.getLocalName()).intern(),
+                        QName.create(key, AsPath.QNAME.getLocalName()).intern(),
+                        QName.create(key, CNextHop.QNAME.getLocalName()).intern(),
+                        QName.create(key, Communities.QNAME.getLocalName()).intern(),
+                        QName.create(key, ExtendedCommunities.QNAME.getLocalName()).intern());
+                }
+            });
+    private final ImmutableSet<QName> transitiveCollection;
     private final Iterable<PathArgument> originatorIdPath;
     private final Iterable<PathArgument> clusterListPath;
     private final NodeIdentifier originatorIdContainer;
     private final NodeIdentifier originatorIdLeaf;
     private final NodeIdentifier clusterListContainer;
     private final NodeIdentifier clusterListLeaf;
+    private final QName clusterQname;
     private final NodeIdentifier asPathContainer;
     private final NodeIdentifier asPathSegments;
-    private final NodeIdentifier asPathChoice;
-    private final NodeIdentifier asPathList;
     private final NodeIdentifier asPathSequence;
-    private final NodeIdentifier asPathId;
+    private final QName asNumberQname;
+    private final NodeIdentifier transitiveLeaf;
 
     private AttributeOperations(final QNameModule namespace) {
-        this.asPathContainer = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsPath.QNAME.getLocalName())));
-        this.asPathSegments = new NodeIdentifier(QName.cachedReference(QName.create(namespace, Segments.QNAME.getLocalName())));
-        this.asPathChoice = new NodeIdentifier(QName.cachedReference(QName.create(namespace, CSegment.QNAME.getLocalName())));
-        this.asPathList = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AList.QNAME.getLocalName())));
-        this.asPathSequence = new NodeIdentifier(QName.cachedReference(QName.create(namespace, AsSequence.QNAME.getLocalName())));
-        this.asPathId = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "as")));
-
-        this.clusterListContainer = new NodeIdentifier(QName.cachedReference(QName.create(namespace, ClusterId.QNAME.getLocalName())));
-        this.clusterListLeaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "cluster")));
-        this.clusterListPath = ImmutableList.<PathArgument>of(this.clusterListContainer, this.clusterListLeaf);
-        this.originatorIdContainer = new NodeIdentifier(QName.cachedReference(QName.create(namespace, OriginatorId.QNAME.getLocalName())));
-        this.originatorIdLeaf = new NodeIdentifier(QName.cachedReference(QName.create(namespace, "originator")));
-        this.originatorIdPath = ImmutableList.<PathArgument>of(this.originatorIdContainer, this.originatorIdLeaf);
+        this.asPathContainer = new NodeIdentifier(QName.create(namespace, AsPath.QNAME.getLocalName()).intern());
+        this.asPathSegments = new NodeIdentifier(QName.create(namespace, Segments.QNAME.getLocalName()).intern());
+        this.asPathSequence = new NodeIdentifier(QName.create(namespace, "as-sequence").intern());
+        this.asNumberQname = QName.create(namespace, "as-number").intern();
+
+        this.clusterListContainer = new NodeIdentifier(QName.create(namespace, ClusterId.QNAME.getLocalName()).intern());
+        this.clusterQname = QName.create(namespace, "cluster").intern();
+        this.clusterListLeaf = new NodeIdentifier(this.clusterQname);
+        this.clusterListPath = ImmutableList.of(this.clusterListContainer, this.clusterListLeaf);
+        this.originatorIdContainer = new NodeIdentifier(QName.create(namespace, OriginatorId.QNAME.getLocalName()).intern());
+        this.originatorIdLeaf = new NodeIdentifier(QName.create(namespace, "originator").intern());
+        this.originatorIdPath = ImmutableList.of(this.originatorIdContainer, this.originatorIdLeaf);
+
+        this.transitiveLeaf = new NodeIdentifier(QName.create(UnrecognizedAttributes.QNAME, "transitive").intern());
+        this.transitiveCollection = TRANSITIVE_CACHE.getUnchecked(namespace);
     }
 
     static AttributeOperations getInstance(final ContainerNode attributes) {
-        return ATTRIBUTES_CACHE.getUnchecked(QNameModule.cachedReference(attributes.getNodeType().getModule()));
+        return ATTRIBUTES_CACHE.getUnchecked(attributes.getNodeType().getModule());
     }
 
-    private Collection<UnkeyedListEntryNode> reusableSequence(final UnkeyedListEntryNode segment) {
-        final Optional<NormalizedNode<?, ?>> maybeAsSequence = NormalizedNodes.findNode(segment, this.asPathChoice, this.asPathList, this.asPathSequence);
+    private LeafSetNode<?> reusableSegment(final UnkeyedListEntryNode segment) {
+        final Optional<NormalizedNode<?, ?>> maybeAsSequence = NormalizedNodes.findNode(segment, this.asPathSequence);
         if (maybeAsSequence.isPresent()) {
-            final UnkeyedListNode asList = (UnkeyedListNode) maybeAsSequence.get();
-            if (asList.getSize() < 255) {
-                return asList.getValue();
+            final LeafSetNode<?> asList = (LeafSetNode<?>) maybeAsSequence.get();
+            if (asList.getValue().size() < Values.UNSIGNED_BYTE_MAX_VALUE) {
+                return asList;
             }
         }
-
         return null;
     }
 
     ContainerNode exportedAttributes(final ContainerNode attributes, final Long localAs) {
-        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
-        b.withNodeIdentifier(attributes.getIdentifier());
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> containerBuilder = Builders.containerBuilder();
+        containerBuilder.withNodeIdentifier(attributes.getIdentifier());
 
         // First filter out non-transitive attributes
         // FIXME: removes MULTI_EXIT_DISC, too.
-        spliceTransitives(b, attributes);
+        spliceTransitives(containerBuilder, attributes);
 
-        /*
-         * This is very ugly, as our AS_PATH model is needlessly complex. The top-level container contains a list
-         * of segments, each of which is a choice containing another list. Both are unkeyed lists, so we need to
-         * perform a wholesale replace.
-         */
-        final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> sb = Builders.unkeyedListBuilder();
-        sb.withNodeIdentifier(this.asPathSegments);
+        final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> segmentsBuilder = Builders.unkeyedListBuilder();
+        segmentsBuilder.withNodeIdentifier(this.asPathSegments);
 
         final Optional<NormalizedNode<?, ?>> maybeOldAsSegments = NormalizedNodes.findNode(attributes, this.asPathContainer, this.asPathSegments);
         if (maybeOldAsSegments.isPresent() && !((UnkeyedListNode) maybeOldAsSegments.get()).getValue().isEmpty()) {
-            // Builder of inner list
-            final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> ilb = Builders.unkeyedListBuilder();
-            ilb.withNodeIdentifier(this.asPathSegments);
-            ilb.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSequence).withChild(ImmutableNodes.leafNode(this.asPathId, localAs)).build());
 
             /*
-             * We need to check the first entry in the outer list, to check if the choice is a-list. If it is and its
-             * total number of elements is less than 255, we need to modify that one. Otherwise we need to create a
-             * new entry.
+             * We need to check the first segment.
+             * If it has as-set then new as-sequence with local AS is prepended.
+             * If it has as-sequence, we may add local AS when it has less than 255 elements.
+             * Otherwise we need to create new as-sequence for local AS.
              */
+
+            final ListNodeBuilder<Object,LeafSetEntryNode<Object>> asSequenceBuilder = Builders.orderedLeafSetBuilder();
+            // add local AS
+            asSequenceBuilder.withNodeIdentifier(this.asPathSequence).addChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.asNumberQname, localAs)).withValue(localAs).build());
+
             final Iterator<UnkeyedListEntryNode> oldAsSegments = ((UnkeyedListNode) maybeOldAsSegments.get()).getValue().iterator();
             final UnkeyedListEntryNode firstSegment = oldAsSegments.next();
-            final Collection<UnkeyedListEntryNode> reusable = reusableSequence(firstSegment);
-            if (reusable != null) {
-                for (final UnkeyedListEntryNode child : reusable) {
-                    ilb.withChild(child);
+            final LeafSetNode<?> reusableAsSeq = reusableSegment(firstSegment);
+            // first segment contains as-sequence with less then 255 elements and it's append to local AS
+            if (reusableAsSeq != null) {
+                for (final LeafSetEntryNode<?> child : reusableAsSeq.getValue())  {
+                    asSequenceBuilder.withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.asNumberQname, child.getValue())).withValue(child.getValue()).build());
                 }
             }
-
-            // Builder of inner container
-            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> icb = Builders.containerBuilder();
-            icb.withNodeIdentifier(this.asPathList);
-            icb.withChild(ilb.build());
-
-            // Choice inside the outer list
-            final DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> ocb = Builders.choiceBuilder();
-            ocb.withNodeIdentifier(this.asPathChoice);
-            ocb.withChild(icb.build());
-
             // Add the new first segment
-            sb.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(ocb.build()).build());
+            segmentsBuilder.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(asSequenceBuilder.build()).build());
 
-            // If we did not merge into the original segment, add it
-            if (reusable == null) {
-                sb.withChild(firstSegment);
+            // When first segment contains as-set or full as-sequence, append it
+            if (reusableAsSeq == null) {
+                segmentsBuilder.withChild(firstSegment);
             }
 
             // Add all subsequent segments
             while (oldAsSegments.hasNext()) {
-                sb.withChild(oldAsSegments.next());
+                segmentsBuilder.withChild(oldAsSegments.next());
             }
         } else {
             // Segments are completely empty, create a completely new AS_PATH container with
             // a single entry
-            sb.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(
-                Builders.choiceBuilder().withNodeIdentifier(this.asPathChoice).withChild(
-                    Builders.containerBuilder().withNodeIdentifier(this.asPathList).withChild(
-                        Builders.unkeyedListBuilder().withNodeIdentifier(this.asPathSequence).withChild(
-                            Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSequence).withChild(
-                                ImmutableNodes.leafNode(this.asPathId, localAs)).build()).build()).build()).build()).build());
-
+            segmentsBuilder.withChild(Builders.unkeyedListEntryBuilder().withNodeIdentifier(this.asPathSegments).withChild(
+                Builders.orderedLeafSetBuilder().withNodeIdentifier(this.asPathSequence).addChild(
+                    Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.asNumberQname, localAs)).withValue(localAs).build()).build()).build());
         }
 
-        b.withChild(Builders.containerBuilder().withNodeIdentifier(this.asPathContainer).withChild(sb.build()).build());
-        return b.build();
+        containerBuilder.withChild(Builders.containerBuilder().withNodeIdentifier(this.asPathContainer).withChild(segmentsBuilder.build()).build());
+        return containerBuilder.build();
     }
 
+    /**
+     * Attributes when reflecting a route from Internal iBGP (Application Peer)
+     * @param attributes
+     * @return
+     */
+    ContainerNode reflectedAttributes(final ContainerNode attributes) {
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> attributesContainer = Builders.containerBuilder(attributes);
+
+        // if there was a CLUSTER_LIST attribute, add it
+        final Optional<NormalizedNode<?, ?>> maybeClusterList = NormalizedNodes.findNode(attributes, this.clusterListPath);
+        if (maybeClusterList.isPresent()) {
+            // Create a new CLUSTER_LIST builder
+            final ListNodeBuilder<Object, LeafSetEntryNode<Object>> clusterBuilder = Builders.orderedLeafSetBuilder();
+            clusterBuilder.withNodeIdentifier(this.clusterListLeaf);
+            AttributeOperations.addOtherClusterEntries(maybeClusterList, clusterBuilder);
+            // Now wrap it in a container and add it to attributes
+            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> clusterListCont= Builders.containerBuilder();
+            clusterListCont.withNodeIdentifier(this.clusterListContainer);
+            clusterListCont.withChild(clusterBuilder.build());
+            attributesContainer.withChild(clusterListCont.build());
+        }
+
+        return attributesContainer.build();
+    }
 
     // Attributes when reflecting a route
     ContainerNode reflectedAttributes(final ContainerNode attributes, final Ipv4Address originatorId, final ClusterIdentifier clusterId) {
-        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> b = Builders.containerBuilder(attributes);
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> attributesContainer = Builders.containerBuilder(attributes);
 
         // Create a new CLUSTER_LIST builder
-        final ListNodeBuilder<Object, LeafSetEntryNode<Object>> clb = Builders.leafSetBuilder();
-        clb.withNodeIdentifier(this.clusterListLeaf);
+        final ListNodeBuilder<Object, LeafSetEntryNode<Object>> clusterBuilder = Builders.orderedLeafSetBuilder();
+        clusterBuilder.withNodeIdentifier(this.clusterListLeaf);
 
         // prepend local CLUSTER_ID
-        clb.withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(ClusterId.QNAME, clusterId)).withValue(clusterId).build());
+        clusterBuilder.withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(new NodeWithValue(this.clusterQname, clusterId.getValue())).
+            withValue(clusterId.getValue()).build());
 
         // if there was a CLUSTER_LIST attribute, add all other entries
         final Optional<NormalizedNode<?, ?>> maybeClusterList = NormalizedNodes.findNode(attributes, this.clusterListPath);
         if (maybeClusterList.isPresent()) {
-            final NormalizedNode<?, ?> clusterList = maybeClusterList.get();
-            if (clusterList instanceof LeafSetNode) {
-                for (final LeafSetEntryNode<?> n : ((LeafSetNode<?>)clusterList).getValue()) {
-                    // There's no way we can safely avoid this cast
-                    @SuppressWarnings("unchecked")
-                    final LeafSetEntryNode<Object> child = (LeafSetEntryNode<Object>)n;
-                    clb.addChild(child);
-                }
-            } else {
-                LOG.warn("Ignoring malformed CLUSTER_LIST {}", clusterList);
-            }
+            AttributeOperations.addOtherClusterEntries(maybeClusterList, clusterBuilder);
         } else {
             LOG.debug("Creating fresh CLUSTER_LIST attribute");
         }
 
         // Now wrap it in a container and add it to attributes
-        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> cb = Builders.containerBuilder();
-        cb.withNodeIdentifier(this.clusterListContainer);
-        cb.withChild(clb.build());
-        b.withChild(cb.build());
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> clusterListCont = Builders.containerBuilder();
+        clusterListCont.withNodeIdentifier(this.clusterListContainer);
+        clusterListCont.withChild(clusterBuilder.build());
+        attributesContainer.withChild(clusterListCont.build());
 
         // add ORIGINATOR_ID if not present
         final Optional<NormalizedNode<?, ?>> maybeOriginatorId = NormalizedNodes.findNode(attributes, this.originatorIdPath);
         if (!maybeOriginatorId.isPresent()) {
-            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> oib = Builders.containerBuilder();
-            oib.withNodeIdentifier(this.originatorIdContainer);
-            oib.withChild(ImmutableNodes.leafNode(this.originatorIdLeaf, originatorId.getValue()));
-            b.withChild(oib.build());
+            final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> originatorIDBuilder = Builders.containerBuilder();
+            originatorIDBuilder.withNodeIdentifier(this.originatorIdContainer);
+            originatorIDBuilder.withChild(ImmutableNodes.leafNode(this.originatorIdLeaf, originatorId.getValue()));
+            attributesContainer.withChild(originatorIDBuilder.build());
         }
 
-        return b.build();
+        return attributesContainer.build();
+    }
+
+    private static void addOtherClusterEntries(final Optional<NormalizedNode<?, ?>> maybeClusterList, final ListNodeBuilder<Object,
+        LeafSetEntryNode<Object>> clb) {
+        final NormalizedNode<?, ?> clusterList = maybeClusterList.get();
+        if (clusterList instanceof LeafSetNode) {
+            for (final LeafSetEntryNode<?> n : ((LeafSetNode<?>) clusterList).getValue()) {
+                // There's no way we can safely avoid this cast
+                @SuppressWarnings("unchecked")
+                final LeafSetEntryNode<Object> child = (LeafSetEntryNode<Object>) n;
+                clb.addChild(child);
+            }
+        } else {
+            LOG.warn("Ignoring malformed CLUSTER_LIST {}", clusterList);
+        }
     }
 
     private boolean isTransitiveAttribute(final DataContainerChild<? extends PathArgument, ?> child) {
-        // FIXME: perform a filtering operation
-        return true;
+        if (child.getIdentifier() instanceof AugmentationIdentifier) {
+            final AugmentationIdentifier ai = (AugmentationIdentifier) child.getIdentifier();
+            for (final QName name : ai.getPossibleChildNames()) {
+                LOG.trace("Augmented QNAME {}", name);
+                if (this.transitiveCollection.contains(name)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        if (this.transitiveCollection.contains(child.getNodeType())) {
+            return true;
+        }
+        if (UnrecognizedAttributes.QNAME.equals(child.getNodeType())) {
+            final Optional<NormalizedNode<?, ?>> maybeTransitive = NormalizedNodes.findNode(child, this.transitiveLeaf);
+            if (maybeTransitive.isPresent()) {
+                return (Boolean) maybeTransitive.get().getValue();
+            }
+        }
+        return false;
     }
 
     private boolean spliceTransitives(final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> target, final ContainerNode attributes) {
@@ -287,11 +334,10 @@ final class AttributeOperations {
 
         final NormalizedNode<?, ?> originatorId = maybeOriginatorId.get();
         if (originatorId instanceof LeafNode) {
-            return ((LeafNode<?>)originatorId).getValue();
+            return originatorId.getValue();
         }
 
         LOG.warn("Unexpected ORIGINATOR_ID node {}, ignoring it", originatorId);
         return null;
     }
-
 }