diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java index 546ff76..f60b370 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java @@ -3,8 +3,11 @@ package com.azure.data.cosmos.serialization.hybridrow; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.bytes.Byte2ReferenceMap; +import it.unimi.dsi.fastutil.bytes.Byte2ReferenceOpenHashMap; + +import java.util.function.Supplier; /** * Versions of HybridRow. @@ -22,30 +25,26 @@ public enum HybridRowVersion { public static final int BYTES = Byte.BYTES; - private static Int2ObjectMap mappings; - private byte value; + private static final Supplier> mappings = Suppliers.memoize(() -> { + final HybridRowVersion[] constants = HybridRowVersion.class.getEnumConstants(); + final byte[] values = new byte[constants.length]; + for (int i = 0; i < constants.length; i++) { + values[i] = constants[i].value(); + } + return new Byte2ReferenceOpenHashMap<>(values, constants); + }); - HybridRowVersion(byte value) { + private final byte value; + + HybridRowVersion(final byte value) { this.value = value; - mappings().put(value, this); } - public static HybridRowVersion from(byte value) { - return mappings().get(value); + public static HybridRowVersion from(final byte value) { + return mappings.get().get(value); } public byte value() { return this.value; } - - private static Int2ObjectMap mappings() { - if (mappings == null) { - synchronized (HybridRowVersion.class) { - if (mappings == null) { - mappings = new Int2ObjectOpenHashMap<>(); - } - } - } - return mappings; - } } \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java index f50ce5e..50843a2 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java @@ -3,8 +3,13 @@ package com.azure.data.cosmos.serialization.hybridrow; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; + +import java.util.Arrays; +import java.util.function.Supplier; public enum Result { @@ -46,30 +51,24 @@ public enum Result { public static final int BYTES = Integer.BYTES; - private static Int2ObjectMap mappings; + private static final Supplier> mappings = Suppliers.memoize(() -> { + Result[] constants = Result.class.getEnumConstants(); + int[] values = new int[constants.length]; + Arrays.setAll(values, index -> constants[index].value); + return new Int2ReferenceOpenHashMap<>(values, constants); + }); + private final int value; Result(int value) { this.value = value; - mappings().put(value, this); } public static Result from(int value) { - return mappings().get(value); + return mappings.get().get(value); } public int value() { return this.value; } - - private static Int2ObjectMap mappings() { - if (mappings == null) { - synchronized (Result.class) { - if (mappings == null) { - mappings = new Int2ObjectOpenHashMap<>(); - } - } - } - return mappings; - } } diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java index ae133c6..ab50267 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java @@ -40,6 +40,46 @@ public final class RowCursor implements Cloneable { RowCursor() { } + /** + * If existing, the layout code of the existing field, otherwise undefined. + * + * @return layout code. + */ + public LayoutType cellType() { + return this.cellType; + } + + /** + * Sets the layout type of an existing field. + * + * @param value a {@link LayoutType}. + * @return a reference to this {@link RowCursor}. + */ + public RowCursor cellType(LayoutType value) { + this.cellType = value; + return this; + } + + /** + * For types with generic parameters (e.g. {@link LayoutTuple}, the type parameters. + * + * @return a {@link TypeArgumentList} or {@code null}. + */ + public TypeArgumentList cellTypeArgs() { + return this.cellTypeArgs; + } + + /** + * Sets the layout type arguments of an existing field. + * + * @param value a {@link TypeArgumentList} or {@code null}. + * @return a reference to this {@link RowCursor}. + */ + public RowCursor cellTypeArgs(TypeArgumentList value) { + this.cellTypeArgs = value; + return this; + } + public RowCursor clone() { try { return (RowCursor) super.clone(); @@ -48,11 +88,32 @@ public final class RowCursor implements Cloneable { } } + /** + * For sized scopes (e.g. Typed Array), the number of elements. + * + * @return the number of elements or zero. + */ + public int count() { + return this.count; + } + + /** + * Sets the number of elements for a sized scope. + * + * @param count the number of elements for a sized scope. + * @return a reference to this {@link RowCursor}. + */ + public RowCursor count(int count) { + this.count = count; + return this; + } + public static RowCursor create(RowBuffer row) { final SchemaId schemaId = row.readSchemaId(1); final Layout layout = row.resolver().resolve(schemaId); - final int sparseSegmentOffset = row.computeVariableValueOffset(layout, HybridRowHeader.BYTES, layout.numVariable()); + final int sparseSegmentOffset = row.computeVariableValueOffset(layout, HybridRowHeader.BYTES, + layout.numVariable()); return new RowCursor() .layout(layout) @@ -77,66 +138,6 @@ public final class RowCursor implements Cloneable { .valueOffset(row.length()); } - /** - * If existing, the layout code of the existing field, otherwise undefined. - * - * @return layout code. - */ - public LayoutType cellType() { - return this.cellType; - } - - /** - * Sets the layout type of an existing field. - * - * @param value a {@link LayoutType}. - * @return a reference to this {@link RowCursor}. - */ - public RowCursor cellType(LayoutType value) { - this.cellType = value; - return this; - } - - /** - * For types with generic parameters (e.g. {@link LayoutTuple}, the type parameters. - * - * @return a {@link TypeArgumentList} or {@code null}. - */ - public TypeArgumentList cellTypeArgs() { - return this.cellTypeArgs; - } - - /** - * Sets the layout type arguments of an existing field. - * - * @param value a {@link TypeArgumentList} or {@code null}. - * @return a reference to this {@link RowCursor}. - */ - public RowCursor cellTypeArgs(TypeArgumentList value) { - this.cellTypeArgs = value; - return this; - } - - /** - * For sized scopes (e.g. Typed Array), the number of elements. - * - * @return the number of elements or zero. - */ - public int count() { - return this.count; - } - - /** - * Sets the number of elements for a sized scope. - * - * @param count the number of elements for a sized scope. - * @return a reference to this {@link RowCursor}. - */ - public RowCursor count(int count) { - this.count = count; - return this; - } - /** * If true, this scope is a unique index scope whose index will be built after its items are written. * @@ -203,11 +204,21 @@ public final class RowCursor implements Cloneable { * If {@code true}, this scope's nested fields cannot be updated individually. *

* The entire scope can still be replaced. + * + * @return {@code true} if this scope's nested fields cannot be updated individually, otherwise {@code false}. */ public boolean immutable() { return this.immutable; } + /** + * Sets a flag indicated whether this scope's nested fields cannot be updated individually. + *

+ * The entire scope can still be replaced. + * + * @param value {@code true} if this scope's nested fields cannot be updated individually, otherwise {@code false}. + * @return a reference to this {@link RowCursor}. + */ public RowCursor immutable(boolean value) { this.immutable = value; return this; @@ -215,11 +226,19 @@ public final class RowCursor implements Cloneable { /** * For indexed scopes (e.g. an Array scope), the zero-based index into the scope of the sparse field. + * + * @return the zero-based index into the scope of the sparse field. */ public int index() { return this.index; } + /** + * Sets the zero-based index into the scope of a sparse field in an indexed scope (e.g. an Array scope). + * + * @param value the zero-based index into the scope of the sparse field. + * @return a reference to this {@link RowCursor}. + */ public RowCursor index(int value) { this.index = value; return this; diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowOptions.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowOptions.java index dc18a70..f9d58fc 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowOptions.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowOptions.java @@ -3,8 +3,13 @@ package com.azure.data.cosmos.serialization.hybridrow; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import com.azure.data.cosmos.serialization.hybridrow.schemas.SortDirection; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; + +import java.util.Arrays; +import java.util.function.Supplier; /** * Describes the desired behavior when mutating a hybrid row. @@ -50,37 +55,31 @@ public enum RowOptions { /** * Delete an existing value. *

- * If a value exists, then it is removed. The remainder of the row is resized to accomodate + * If a value exists, then it is removed. The remainder of the row is resized to accommodate * a decrease in required space. If no value exists this operation is a no-op. */ DELETE(5); public static final int BYTES = Integer.BYTES; - private static Int2ObjectMap mappings; + private static final Supplier> mappings = Suppliers.memoize(() -> { + RowOptions[] constants = RowOptions.class.getEnumConstants(); + int[] values = new int[constants.length]; + Arrays.setAll(values, index -> constants[index].value); + return new Int2ReferenceArrayMap<>(values, constants); + }); + private final int value; RowOptions(int value) { this.value = value; - mappings().put(value, this); } public static RowOptions from(int value) { - return mappings().get(value); + return mappings.get().get(value); } public int value() { return this.value; } - - private static Int2ObjectMap mappings() { - if (mappings == null) { - synchronized (RowOptions.class) { - if (mappings == null) { - mappings = new Int2ObjectOpenHashMap<>(); - } - } - } - return mappings; - } } \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/SchemaId.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/SchemaId.java index 0dfe345..a2ad16c 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/SchemaId.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/SchemaId.java @@ -20,9 +20,11 @@ import javax.annotation.Nonnull; import java.io.IOException; import static com.google.common.base.Strings.lenientFormat; +import static it.unimi.dsi.fastutil.HashCommon.*; /** * The unique identifier for a schema. + *

* Identifiers must be unique within the scope of the database in which they are used. */ @JsonDeserialize(using = SchemaId.JsonDeserializer.class) @@ -31,10 +33,15 @@ public final class SchemaId implements Comparable { public static final int BYTES = Integer.BYTES; public static final SchemaId INVALID = null; - public static final SchemaId NONE = new SchemaId(-1); + public static final SchemaId NONE; - private static final long MAX_VALUE = 0x00000000FFFFFFFFL; - private static final Int2ReferenceMap cache = new Int2ReferenceOpenHashMap<>(); + private static final long MAX_VALUE = 0x00000000FFFFFFFEL; + private static final Int2ReferenceMap cache; + + static { + cache = new Int2ReferenceOpenHashMap<>(); + cache.put(-1, NONE = new SchemaId(-1)); + } private final int value; @@ -68,7 +75,7 @@ public final class SchemaId implements Comparable { * {@code true} if this is the same {@link SchemaId} as {@code other}. * * @param other The value to compare against. - * @return True if the two values are the same. + * @return {@code true} if the two values are the same. */ public boolean equals(SchemaId other) { if (null == other) { @@ -89,12 +96,12 @@ public final class SchemaId implements Comparable { @Override public int hashCode() { - return Integer.valueOf(this.value()).hashCode(); + return mix(this.value); } @Override public String toString() { - return String.valueOf(this.value()); + return Integer.toString(this.value); } /** @@ -118,11 +125,11 @@ public final class SchemaId implements Comparable { final long value = parser.getLongValue(); if (value < 0 || value > MAX_VALUE) { - String message = lenientFormat("expected value in [0, 4294967295], not %s", value); + String message = lenientFormat("expected value in [0, %s], not %s", MAX_VALUE, value); throw MismatchedInputException.from(parser, SchemaId.class, message); } - return new SchemaId((int) value); + return SchemaId.from((int) value); } } @@ -137,4 +144,4 @@ public final class SchemaId implements Comparable { generator.writeNumber((long) value.value() & MAX_VALUE); } } -} \ No newline at end of file +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCode.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCode.java index c3982ba..115a37c 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCode.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCode.java @@ -3,10 +3,11 @@ package com.azure.data.cosmos.serialization.hybridrow.layouts; -import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap; -import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.bytes.Byte2ReferenceMap; +import it.unimi.dsi.fastutil.bytes.Byte2ReferenceOpenHashMap; -import java.util.Map; +import java.util.function.Supplier; /** * Type coded used in the binary encoding to indicate the formatting of succeeding bytes. @@ -91,30 +92,26 @@ public enum LayoutCode { public static final int BYTES = Byte.BYTES; - private static Byte2ObjectMap mappings; - private byte value; + private static final Supplier> mappings = Suppliers.memoize(() -> { + final LayoutCode[] constants = LayoutCode.class.getEnumConstants(); + final byte[] values = new byte[constants.length]; + for (int i = 0; i < constants.length; i++) { + values[i] = constants[i].value(); + } + return new Byte2ReferenceOpenHashMap<>(values, constants); + }); - LayoutCode(byte value) { + private final byte value; + + LayoutCode(final byte value) { this.value = value; - mappings().put(value, this); } public byte value() { return this.value; } - public static LayoutCode from(byte value) { - return mappings().get(value); - } - - private static Map mappings() { - if (mappings == null) { - synchronized (LayoutCode.class) { - if (mappings == null) { - mappings = new Byte2ObjectOpenHashMap<>(); - } - } - } - return mappings; + public static LayoutCode from(final byte value) { + return mappings.get().get(value); } } \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/UpdateOptions.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/UpdateOptions.java index 0cd5c61..7d66759 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/UpdateOptions.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/UpdateOptions.java @@ -3,8 +3,12 @@ package com.azure.data.cosmos.serialization.hybridrow.layouts; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; + +import java.util.Arrays; +import java.util.function.Supplier; /** * Describes the desired behavior when writing a {@link LayoutType}. @@ -47,30 +51,24 @@ public enum UpdateOptions { public static final int BYTES = Integer.BYTES; - private static Int2ObjectMap mappings; - private int value; + private static final Supplier> mappings = Suppliers.memoize(() -> { + UpdateOptions[] constants = UpdateOptions.class.getEnumConstants(); + int[] values = new int[constants.length]; + Arrays.setAll(values, index -> constants[index].value); + return new Int2ReferenceArrayMap<>(values, constants); + }); + + private final int value; UpdateOptions(int value) { this.value = value; - mappings().put(value, this); } public static UpdateOptions from(int value) { - return mappings().get(value); + return mappings.get().get(value); } public int value() { return this.value; } - - private static Int2ObjectMap mappings() { - if (mappings == null) { - synchronized (UpdateOptions.class) { - if (mappings == null) { - mappings = new Int2ObjectOpenHashMap<>(); - } - } - } - return mappings; - } } \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SortDirection.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SortDirection.java index e58e25c..31e54e4 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SortDirection.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SortDirection.java @@ -3,8 +3,12 @@ package com.azure.data.cosmos.serialization.hybridrow.schemas; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; + +import java.util.Arrays; +import java.util.function.Supplier; /** * Describes the sort order direction. @@ -22,12 +26,17 @@ public enum SortDirection { public static final int BYTEST = Integer.BYTES; - private static Int2ObjectMap mappings; - private int value; + private static final Supplier> mappings = Suppliers.memoize(() -> { + SortDirection[] constants = SortDirection.class.getEnumConstants(); + int[] values = new int[constants.length]; + Arrays.setAll(values, index -> constants[index].value); + return new Int2ReferenceArrayMap<>(values, constants); + }); + + private final int value; SortDirection(int value) { this.value = value; - mappings().put(value, this); } public int value() { @@ -35,17 +44,6 @@ public enum SortDirection { } public static SortDirection from(int value) { - return mappings().get(value); - } - - private static Int2ObjectMap mappings() { - if (mappings == null) { - synchronized (SortDirection.class) { - if (mappings == null) { - mappings = new Int2ObjectOpenHashMap<>(); - } - } - } - return mappings; + return mappings.get().get(value); } } \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StorageKind.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StorageKind.java index 5e772f5..4382539 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StorageKind.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StorageKind.java @@ -4,8 +4,8 @@ package com.azure.data.cosmos.serialization.hybridrow.schemas; import com.google.common.base.Suppliers; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import java.util.Arrays; import java.util.function.Supplier; @@ -50,11 +50,11 @@ public enum StorageKind { public static final int BYTES = Integer.BYTES; - private static final Supplier> mappings = Suppliers.memoize(() -> { + private static final Supplier> mappings = Suppliers.memoize(() -> { StorageKind[] storageKinds = StorageKind.class.getEnumConstants(); int[] values = new int[storageKinds.length]; Arrays.setAll(values, index -> storageKinds[index].value); - return new Int2ObjectArrayMap(values, storageKinds); + return new Int2ReferenceArrayMap<>(values, storageKinds); }); private final String friendlyName; diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TypeKind.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TypeKind.java index 6a8de90..a3b357d 100644 --- a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TypeKind.java +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TypeKind.java @@ -3,12 +3,10 @@ package com.azure.data.cosmos.serialization.hybridrow.schemas; -// TODO: DANOBLE: Fixup JSON-serialized naming for agreement with the dotnet code - import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; import com.google.common.base.Suppliers; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; import java.util.Arrays; import java.util.function.Supplier; @@ -192,11 +190,11 @@ public enum TypeKind { public static final int BYTES = Integer.BYTES; - private static Supplier> mappings = Suppliers.memoize(() -> { - TypeKind[] typeKinds = TypeKind.class.getEnumConstants(); - int[] values = new int[typeKinds.length]; - Arrays.setAll(values, index -> typeKinds[index].value); - return new Int2ObjectOpenHashMap<>(values, typeKinds); + private static Supplier> mappings = Suppliers.memoize(() -> { + TypeKind[] constants = TypeKind.class.getEnumConstants(); + int[] values = new int[constants.length]; + Arrays.setAll(values, index -> constants[index].value); + return new Int2ReferenceOpenHashMap<>(values, constants); }); private final String friendlyName; @@ -217,6 +215,10 @@ public enum TypeKind { return this.friendlyName; } + public static TypeKind from(int value) { + return mappings.get().get(value); + } + /** * Returns the friendly name of this enum constant. * @@ -231,8 +233,4 @@ public enum TypeKind { public int value() { return this.value; } - - public static TypeKind from(int value) { - return mappings.get().get(value); - } }