import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedMap;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
private static class IdentifiableItemCodec implements Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> {
- private final ImmutableSortedMap<QName, ValueContext> keyValueContexts;
+ private final Map<QName, ValueContext> keyValueContexts;
private final ListSchemaNode schema;
private final Constructor<? extends Identifier<?>> constructor;
private final Class<?> identifiable;
final Class<?> identifiable, final Map<QName, ValueContext> keyValueContexts) {
this.schema = schema;
this.identifiable = identifiable;
- this.keyValueContexts = ImmutableSortedMap.copyOf(keyValueContexts);
this.constructor = getConstructor(keyClass);
+
+ /*
+ * We need to re-index to make sure we instantiate nodes in the order in which
+ * they are defined.
+ */
+ final Map<QName, ValueContext> keys = new LinkedHashMap<>();
+ for (QName qname : schema.getKeyDefinition()) {
+ keys.put(qname, keyValueContexts.get(qname));
+ }
+ this.keyValueContexts = ImmutableMap.copyOf(keys);
}
@Override
public IdentifiableItem<?, ?> deserialize(final NodeIdentifierWithPredicates input) {
- ArrayList<Object> bindingValues = new ArrayList<>();
-
- for(QName key: schema.getKeyDefinition()) {
+ final Collection<QName> keys = schema.getKeyDefinition();
+ final ArrayList<Object> bindingValues = new ArrayList<>(keys.size());
+ for (QName key : keys) {
Object yangValue = input.getKeyValues().get(key);
bindingValues.add(keyValueContexts.get(key).deserialize(yangValue));
}
+
+ final Identifier<?> identifier;
try {
- final Identifier<?> identifier = constructor.newInstance(bindingValues.toArray());
- @SuppressWarnings({ "rawtypes", "unchecked" })
- final IdentifiableItem identifiableItem = new IdentifiableItem(identifiable, identifier);
- return identifiableItem;
+ identifier = constructor.newInstance(bindingValues.toArray());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException(e);
+ throw new IllegalStateException(String.format("Failed to instantiate key class %s", constructor.getDeclaringClass()), e);
}
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ final IdentifiableItem identifiableItem = new IdentifiableItem(identifiable, identifier);
+ return identifiableItem;
}
@Override
public NodeIdentifierWithPredicates serialize(final IdentifiableItem<?, ?> input) {
Object value = input.getKey();
- Map<QName, Object> values = new HashMap<>();
+ Map<QName, Object> values = new LinkedHashMap<>();
for (Entry<QName, ValueContext> valueCtx : keyValueContexts.entrySet()) {
values.put(valueCtx.getKey(), valueCtx.getValue().getAndSerialize(value));
}
return new NodeIdentifierWithPredicates(schema.getQName(), values);
}
-
}
@SuppressWarnings("unchecked")
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
}
private PathArgument serializeIdentifiableItem(final IdentifiableItem<?,?> argument, final QName previousQname) {
- Map<QName, Object> predicates = new HashMap<>();
@SuppressWarnings("rawtypes")
Class type = argument.getType();
@SuppressWarnings("unchecked")
ValueWithQName combinedInput = new ValueWithQName(previousQname, argument.getKey());
@SuppressWarnings("unchecked")
CompositeNode compositeOutput = keyCodec.serialize(combinedInput);
+
+ final Map<QName, Object> predicates = new LinkedHashMap<>();
for (Node<?> outputValue : compositeOutput.getValue()) {
predicates.put(outputValue.getNodeType(), outputValue.getValue());
}
private static abstract class AbstractPathArgument implements PathArgument {
private static final long serialVersionUID = -4546547994250849340L;
private final QName nodeType;
+ private volatile transient Integer hash = null;
protected AbstractPathArgument(final QName nodeType) {
this.nodeType = Preconditions.checkNotNull(nodeType);
return nodeType.compareTo(o.getNodeType());
}
- @Override
- public int hashCode() {
+ protected int hashCodeImpl() {
return 31 + getNodeType().hashCode();
}
+ @Override
+ public final int hashCode() {
+ Integer ret = hash;
+ if (ret == null) {
+ synchronized (this) {
+ ret = hash;
+ if (ret == null) {
+ ret = hashCodeImpl();
+ hash = ret;
+ }
+ }
+ }
+
+ return ret;
+ }
+
@Override
public boolean equals(final Object obj) {
if (this == obj) {
}
@Override
- public int hashCode() {
+ protected int hashCodeImpl() {
final int prime = 31;
- int result = super.hashCode();
+ int result = super.hashCodeImpl();
result = prime * result;
for (Entry<QName, Object> entry : keyValues.entrySet()) {
}
@Override
- public int hashCode() {
+ protected int hashCodeImpl() {
final int prime = 31;
- int result = super.hashCode();
+ int result = super.hashCodeImpl();
result = prime * result + ((value == null) ? 0 : YangInstanceIdentifier.hashCode(value));
return result;
}
private final Writer writer;
private final String indent;
- private URI currentNamespace = null;
private int currentDepth = 0;
+ private URI currentNamespace;
private JSONNormalizedNodeStreamWriter(final SchemaContext schemaContext,
final Writer writer, final int indentSize) {
- this.schemaContext = Preconditions.checkNotNull(schemaContext);
- this.writer = Preconditions.checkNotNull(writer);
-
- Preconditions.checkArgument(indentSize >= 0, "Indent size must be non-negative");
- if (indentSize != 0) {
- indent = Strings.repeat(" ", indentSize);
- } else {
- indent = null;
- }
-
- this.codecs = CodecFactory.create(schemaContext);
- this.tracker = SchemaTracker.create(schemaContext);
+ this(schemaContext, SchemaPath.ROOT, writer, null, indentSize);
}
private JSONNormalizedNodeStreamWriter(final SchemaContext schemaContext, final SchemaPath path,
- final Writer writer, final URI initialNs,final int indentSize) {
+ final Writer writer, final URI initialNs, final int indentSize) {
this.schemaContext = Preconditions.checkNotNull(schemaContext);
this.writer = Preconditions.checkNotNull(writer);
} else {
indent = null;
}
- this.currentNamespace = initialNs;
this.codecs = CodecFactory.create(schemaContext);
- this.tracker = SchemaTracker.create(schemaContext,path);
+ this.tracker = SchemaTracker.create(schemaContext, path);
+
+ this.currentNamespace = initialNs;
}
/**
*/
package org.opendaylight.yangtools.yang.data.codec.gson;
-import com.google.common.base.Function;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
import java.io.IOException;
+import java.util.Collection;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import javax.annotation.Nonnull;
-
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.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
class ListEntryNodeDataWithSchema extends CompositeNodeDataWithSchema {
- private static final Function<SimpleNodeDataWithSchema, Object> VALUE_FUNCTION = new Function<SimpleNodeDataWithSchema, Object>() {
- @Override
- public Object apply(@Nonnull final SimpleNodeDataWithSchema input) {
- return input.getValue();
- }
- };
private final Map<QName, SimpleNodeDataWithSchema> qNameToKeys = new HashMap<>();
@Override
public void write(final NormalizedNodeStreamWriter writer) throws IOException {
- final int keyCount = ((ListSchemaNode) getSchema()).getKeyDefinition().size();
- if (keyCount == 0) {
+ final Collection<QName> keyDef = ((ListSchemaNode) getSchema()).getKeyDefinition();
+ if (keyDef.isEmpty()) {
writer.startUnkeyedListItem(provideNodeIdentifier(), childSizeHint());
super.write(writer);
writer.endNode();
return;
}
- Preconditions.checkState(keyCount == qNameToKeys.size(), "Input is missing some of the keys of %s", getSchema().getQName());
+ Preconditions.checkState(keyDef.size() == qNameToKeys.size(), "Input is missing some of the keys of %s", getSchema().getQName());
+
+ // Need to restore schema order...
+ final Map<QName, Object> predicates = new LinkedHashMap<>();
+ for (QName qname : keyDef) {
+ predicates.put(qname, qNameToKeys.get(qname).getValue());
+ }
+
writer.startMapEntryNode(
- new NodeIdentifierWithPredicates(getSchema().getQName(), Maps.transformValues(qNameToKeys, VALUE_FUNCTION)),
+ new NodeIdentifierWithPredicates(getSchema().getQName(), predicates),
childSizeHint());
super.write(writer);
writer.endNode();
return leafNode(new NodeIdentifier(name), value);
}
- public static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder(final QName nodeName,final QName keyName,final Object keyValue) {
+ public static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder(final QName nodeName, final QName keyName, final Object keyValue) {
return ImmutableMapEntryNodeBuilder.create()
- .withNodeIdentifier(new NodeIdentifierWithPredicates(nodeName, keyName,keyValue))
+ .withNodeIdentifier(new NodeIdentifierWithPredicates(nodeName, keyName, keyValue))
.withChild(leafNode(keyName, keyValue));
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
+import com.google.common.base.Preconditions;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataValidationException;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-
public final class ImmutableMapEntryNodeSchemaAwareBuilder extends ImmutableMapEntryNodeBuilder{
private final ListSchemaNode schema;
private YangInstanceIdentifier.NodeIdentifierWithPredicates constructNodeIdentifier() {
Collection<QName> keys = schema.getKeyDefinition();
- if(keys.isEmpty()) {
+ if (keys.isEmpty()) {
keys = childrenQNamesToPaths.keySet();
}
- final Map<QName, Object> keysToValues = Maps.newHashMap();
+ final Map<QName, Object> keysToValues = new LinkedHashMap<>();
for (QName key : keys) {
- final DataContainerChild<?, ?> valueForKey = getChild(childrenQNamesToPaths.get(key));
+ final DataContainerChild<?, ?> valueForKey = getChild(childrenQNamesToPaths.get(key));
DataValidationException.checkListKey(valueForKey, key, new YangInstanceIdentifier.NodeIdentifierWithPredicates(
- schema.getQName(), keysToValues));
+ schema.getQName(), keysToValues));
keysToValues.put(key, valueForKey.getValue());
}
import com.google.common.base.Splitter;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
// predicates
final Matcher matcher = PREDICATE_PATTERN.matcher(xPathArgument);
- final Map<QName, Object> predicates = new HashMap<>();
+ final Map<QName, Object> predicates = new LinkedHashMap<>();
QName currentQName = mainQName;
while (matcher.find()) {
instance.userOrdered = userOrdered;
// KEY
- if (keys == null) {
- instance.keyDefinition = ImmutableList.of();
- } else {
+ if (keys != null) {
keyDefinition = new ArrayList<>();
for (String key : keys) {
DataSchemaNode keyPart = instance.getDataChildByName(key);
throw new YangParseException(getModuleName(), getLine(), "Failed to resolve list key for name "
+ key);
}
- keyDefinition.add(keyPart.getQName());
+
+ final QName qname = keyPart.getQName();
+ if (!keyDefinition.contains(qname)) {
+ keyDefinition.add(qname);
+ }
}
instance.keyDefinition = ImmutableList.copyOf(keyDefinition);
+ } else {
+ instance.keyDefinition = ImmutableList.of();
}
// ORIGINAL NODE