- final MethodHandle inv = MethodHandles.spreadInvoker(tmpCtor.type(), 0);
- this.ctor = inv.asType(inv.type().changeReturnType(Identifier.class)).bindTo(tmpCtor);
-
- /*
- * We need to re-index to make sure we instantiate nodes in the order in which they are defined. We will also
- * need to instantiate values in the same order.
- */
- predicateTemplate = ImmutableMapTemplate.ordered(schema.getKeyDefinition());
- this.keyValueContexts = predicateTemplate.instantiateTransformed(keyValueContexts, (key, value) -> value);
-
- /*
- * When instantiating binding objects we need to specify constructor arguments
- * in alphabetic order. We play a couple of tricks here to optimize CPU/memory
- * trade-offs.
- *
- * We do not have to perform a sort if the source collection has less than two
- * elements.
- *
- * We always perform an ImmutableList.copyOf(), as that will turn into a no-op
- * if the source is already immutable. It will also produce optimized implementations
- * for empty and singleton collections.
- *
- * BUG-2755: remove this if order is made declaration-order-dependent
- */
- final List<QName> unsortedKeys = schema.getKeyDefinition();
- final List<QName> sortedKeys;
- if (unsortedKeys.size() > 1) {
- final List<QName> tmp = new ArrayList<>(unsortedKeys);
+
+ @Override
+ Identifier<?> deserializeIdentifier(final Map<QName, Object> keyValues) throws Throwable {
+ return (Identifier<?>) ctor.invokeExact(keyContext.deserialize(keyValues.get(keyName)));
+ }
+
+ @Override
+ NodeIdentifierWithPredicates serializeIdentifier(final QName qname, final Identifier<?> key) {
+ return new NodeIdentifierWithPredicates(qname, predicateTemplate.instantiateWithValue(
+ keyContext.getAndSerialize(key)));
+ }
+ }
+
+ private static final class MultiKey extends IdentifiableItemCodec {
+ private final ImmutableOffsetMapTemplate<QName> predicateTemplate;
+ private final ImmutableOffsetMap<QName, ValueContext> keyValueContexts;
+ private final ImmutableList<QName> keysInBindingOrder;
+ private final MethodHandle ctor;
+
+ MultiKey(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+ final Class<?> identifiable, final Map<QName, ValueContext> keyValueContexts) {
+ super(schema, keyClass, identifiable);
+
+ final MethodHandle tmpCtor = getConstructor(keyClass);
+ final MethodHandle inv = MethodHandles.spreadInvoker(tmpCtor.type(), 0);
+ this.ctor = inv.asType(inv.type().changeReturnType(Identifier.class)).bindTo(tmpCtor);
+
+ /*
+ * We need to re-index to make sure we instantiate nodes in the order in which they are defined. We will
+ * also need to instantiate values in the same order.
+ */
+ final List<QName> keyDef = schema.getKeyDefinition();
+ predicateTemplate = ImmutableOffsetMapTemplate.ordered(keyDef);
+ this.keyValueContexts = predicateTemplate.instantiateTransformed(keyValueContexts, (key, value) -> value);
+
+ /*
+ * When instantiating binding objects we need to specify constructor arguments in alphabetic order. If the
+ * order matches definition order, we try to reuse the key definition.
+ *
+ * BUG-2755: remove this if order is made declaration-order-dependent
+ */
+ final List<QName> tmp = new ArrayList<>(keyDef);