From 27cb0ab92721e17a14dea60fcfee8bb9a0e0ae4b Mon Sep 17 00:00:00 2001 From: Robert Varga Date: Thu, 22 Nov 2018 23:32:00 +0100 Subject: [PATCH] Improve ListEntryNodeDataWithSchema ImmutableMapTemplate allows us to more efficiently instantiate NodeIdentifierPredicates, as it takes care of ordering of keys while maintaining an efficient internal representations. It furthermore provides a keySet() method, which is useful for quickly checking if a leaf is part of key definition -- unlike ListSchemaNode.getKeyDefinition(), which is a List and therefore must be linearly searched. It also allows us to skip HashMap allocation for unkeyed lists, clearly showing that the class should be split into two. JIRA: YANGTOOLS-917 Change-Id: If2d7bbbc5c4fe1ca96097f374f4313aabb411908 Signed-off-by: Robert Varga (cherry picked from commit e31b3dc700002b19d92ecc68463ab2711d8af99c) --- .../util/ListEntryNodeDataWithSchema.java | 77 +++++++++++-------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/ListEntryNodeDataWithSchema.java b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/ListEntryNodeDataWithSchema.java index 04010de515..ebb7362222 100644 --- a/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/ListEntryNodeDataWithSchema.java +++ b/yang/yang-data-util/src/main/java/org/opendaylight/yangtools/yang/data/util/ListEntryNodeDataWithSchema.java @@ -8,12 +8,13 @@ package org.opendaylight.yangtools.yang.data.util; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Verify.verify; import java.io.IOException; import java.util.Collection; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; +import org.opendaylight.yangtools.util.ImmutableMapTemplate; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamAttributeWriter; @@ -30,63 +31,71 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; * Represents a YANG list entry node. */ public class ListEntryNodeDataWithSchema extends CompositeNodeDataWithSchema { + // This template results in Maps in schema definition order + private final ImmutableMapTemplate predicateTemplate; + private final Map keyValues; - private final Map qnameToKeys = new HashMap<>(); - + // FIXME: 3.0.0: require ListSchemaNode + // FIXME: 3.0.0: hide this constructor and provide specialized keyed/unkeyed classes public ListEntryNodeDataWithSchema(final DataSchemaNode schema) { super(schema); + + final Collection keyDef = ((ListSchemaNode) getSchema()).getKeyDefinition(); + if (keyDef.isEmpty()) { + predicateTemplate = null; + keyValues = null; + } else { + predicateTemplate = ImmutableMapTemplate.ordered(keyDef); + keyValues = new HashMap<>(); + } } @Override public void addChild(final AbstractNodeDataWithSchema newChild) { - final DataSchemaNode childSchema = newChild.getSchema(); - if (childSchema instanceof LeafSchemaNode && isPartOfKey((LeafSchemaNode) childSchema)) { - qnameToKeys.put(childSchema.getQName(), (SimpleNodeDataWithSchema)newChild); + if (predicateTemplate != null) { + final DataSchemaNode childSchema = newChild.getSchema(); + if (childSchema instanceof LeafSchemaNode) { + populateKeyValue(childSchema.getQName(), newChild); + } } super.addChild(newChild); } - private boolean isPartOfKey(final LeafSchemaNode potentialKey) { - for (QName qname : ((ListSchemaNode) getSchema()).getKeyDefinition()) { - if (qname.equals(potentialKey.getQName())) { - return true; - } + private void populateKeyValue(final QName childName, final AbstractNodeDataWithSchema child) { + if (predicateTemplate.keySet().contains(childName)) { + verify(child instanceof SimpleNodeDataWithSchema); + keyValues.put(childName, (SimpleNodeDataWithSchema)child); } - return false; } @Override public void write(final NormalizedNodeStreamWriter writer) throws IOException { - final Collection keyDef = ((ListSchemaNode) getSchema()).getKeyDefinition(); - if (keyDef.isEmpty()) { - writer.nextDataSchemaNode(getSchema()); + writer.nextDataSchemaNode(getSchema()); + if (predicateTemplate != null) { + writeKeyedListItem(writer); + } else { writer.startUnkeyedListItem(provideNodeIdentifier(), childSizeHint()); - super.write(writer); - writer.endNode(); - return; } - checkState(keyDef.size() == qnameToKeys.size(), "Input is missing some of the keys of %s", - getSchema().getQName()); + super.write(writer); + writer.endNode(); + } - // Need to restore schema order... - final Map predicates = new LinkedHashMap<>(); - for (QName qname : keyDef) { - predicates.put(qname, qnameToKeys.get(qname).getValue()); - } + private void writeKeyedListItem(final NormalizedNodeStreamWriter writer) throws IOException { + // FIXME: 3.0.0: remove this check? predicateTemplate will throw an IllegalArgumentException if anything + // goes wrong -- which is a change of behavior, as now we're throwing an ISE. Do we want that? + final Collection keySet = predicateTemplate.keySet(); + checkState(keySet.size() == keyValues.size(), + "Map entry corresponding to %s is missing some of required keys %s", getSchema().getQName(), keySet); - writer.nextDataSchemaNode(getSchema()); + final NodeIdentifierWithPredicates identifier = new NodeIdentifierWithPredicates(getSchema().getQName(), + predicateTemplate.instantiateTransformed(keyValues, (key, node) -> node.getValue())); if (writer instanceof NormalizedNodeStreamAttributeWriter && getAttributes() != null) { - ((NormalizedNodeStreamAttributeWriter) writer).startMapEntryNode( - new NodeIdentifierWithPredicates(getSchema().getQName(), predicates), childSizeHint(), - getAttributes()); + ((NormalizedNodeStreamAttributeWriter) writer).startMapEntryNode(identifier, childSizeHint(), + getAttributes()); } else { - writer.startMapEntryNode(new NodeIdentifierWithPredicates(getSchema().getQName(), predicates), - childSizeHint()); + writer.startMapEntryNode(identifier, childSizeHint()); } - - super.write(writer); - writer.endNode(); } } -- 2.36.6