From c36b0adfe8b10c4e116e0b3018a2e609615f7dec Mon Sep 17 00:00:00 2001 From: David Noble Date: Wed, 9 Oct 2019 14:07:57 -0700 Subject: [PATCH] Feature/java/port from dotnet (#1) * Add pom.xml placeholder and Hybrid Row whitepaper * Checkpoint for safe keeping * Progressed on port from dotnet to java * Progressed on port from C# to Java * Brought in Utf8AnyString.java * Progressed on port from C# to Java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Updated documents releated to release of Microsoft Code under MIT License * Updated JRE copyright notices * Progressed on port from dotnet to java * Renamed jre as java because Java is used to can refer to two things: the platform and the language. In this case we are referring to the Java Platform, not the Java Runtime Environment. * Progressed on port * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on dotnet port to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Progressed on port from dotnet to java * Code cleanup, especially in Utf8String class which is much improved. * Progressed on port from dotnet to java. * Simplified Utf8String some more * Code cleanup * Excluding most tests with the expectation that we'll bring them in as we continue to expand our test matrix. * Added and debugged some tests * Added and debugged some tests * Added and debugged some tests * Added, revised, and debugged some tests and test issues * Added, revised, and debugged some tests and test issues * Added, revised, and debugged some tests and test issues * Optimized imports * Removed dead code * Updated java docs * Added, revised, and debugged some tests and test issues * Added, revised, and debugged some tests and test issues * Added, revised, and debugged some tests and test issues * Added, revised, and debugged some tests and test issues. Updated javadocs and pom.xml. We now add SystemSchema.json to azure-cosmos-serialization.jar. Javadocs don't currently build. * Javadoc update * Test update * Progressed on deserializing schemas. * Progressed on deserializing schemas. * Progressed on deserializing schemas. * testLoadSchmea passes * code cleanup in prep for next step: loading a namespace that includes a schema with a udt: the one that the Spark connector team needs. * code cleanup in prep for next step: loading a namespace that includes a schema with a udt: the one that the Spark connector team needs. * RootSegment.json now loads * Progressed on RowReader * Progressed on RowReader * RowReaderTest against RootSegment.json/RootSegment.hybridrow succeeds * RowReaderTest against RootSegment.json/RootSegment.hybridrow succeeds * Move RowScanner and DataItem out of test into main * Move RowScanner and DataItem out of test into main * Move RowScanner and DataItem out of test into main * RowIterable now works. RowIterable and RowScanner now include indexes of array elements. * RowIterable and RowScanner now support additional data types * RowScanner now implements Iterable and RowIterable has been removed. * POM now packages SystemSchema.json and SystemSchema class now loads the packaged SystemSchema.json * Updated pom.xml with required licensing info and attempted to produce javadocs. * Progressed on adding support for unsupported Utf8String features * Refinements to Utf8String and Utf8StringTest * Utf8StringTest improvements * Refinements to Utf8String and Utf8StringTest * Added caching of UTF-16 string caching to Utf8String to reduce the time and space cost of Utf8String.toUtf16(). Also: addressed a number of javadoc issues. * Addressed a number of javadoc issues and the javadocs now build. * Utf8String refinements with inefficient support instead of no support for Utf8String.charAt(int) * Bumped netty.version and updated javadocs for Utf8String * Code cleanup (javadoc improvements + tidying) * Utf8String optimizations * Tweaks * Tweaks --- .gitignore | 2 + CONTRIBUTING.md | 14 + LICENSE | 21 - LICENSE.TXT | 21 + README.md | 15 +- .../Hybrid-row-whitepaper.docx | Bin dotnet/src/Core/UtfAnyString.cs | 480 +++ .../serialization/hybridrow/ISpanResizer.java | 25 + .../hybridrow/MemorySpanResizer.java | 55 + .../layouts/SamplingStringComparer.java | 48 + .../layouts/SamplingUtf8StringComparer.java | 49 + .../hybridrow/recordio/Record.java | 37 + .../hybridrow/recordio/RecordIOFormatter.java | 78 + .../hybridrow/recordio/RecordIOParser.java | 354 ++ .../hybridrow/recordio/RecordIOStream.java | 368 ++ .../hybridrow/recordio/RecordSerializer.java | 68 + .../hybridrow/recordio/SegmentSerializer.java | 123 + .../schemas/PropertySchemaConverter.java | 84 + .../schemas/StrictBooleanConverter.java | 37 + .../schemas/StrictIntegerConverter.java | 47 + .../hybridrow/perf/BenchmarkSuiteBase.java | 140 + .../perf/BsonJsonModelRowGenerator.java | 130 + .../hybridrow/perf/BsonReaderExtensions.java | 54 + .../hybridrow/perf/BsonRowGenerator.java | 314 ++ .../perf/CodeGenMicroBenchmarkSuite.java | 311 ++ .../hybridrow/perf/CodeGenRowGenerator.java | 1169 +++++ .../perf/GenerateBenchmarkSuite.java | 108 + .../hybridrow/perf/JsonModelRowGenerator.java | 193 + .../hybridrow/perf/Measurements.java | 62 + .../perf/MicroBenchmarkSuiteBase.java | 127 + .../hybridrow/perf/ProtobufRowGenerator.java | 338 ++ .../hybridrow/perf/ReaderBenchmark.java | 317 ++ .../hybridrow/perf/RowReaderExtensions.java | 88 + .../perf/SchematizedMicroBenchmarkSuite.java | 639 +++ .../hybridrow/perf/TestData.java | 19 + .../UnschematizedMicroBenchmarkSuite.java | 339 ++ .../perf/cassandrahotel/protobuf/Address.java | 316 ++ .../Available_Rooms_By_Hotel_Date.java | 320 ++ .../CassandraHotelSchemaReflection.java | 120 + .../perf/cassandrahotel/protobuf/Guests.java | 445 ++ .../perf/cassandrahotel/protobuf/Hotels.java | 316 ++ .../cassandrahotel/protobuf/PostalCode.java | 232 + .../hybridrow/unit/ArrayAssert.java | 45 + .../hybridrow/unit/AssertThrowsException.java | 109 + .../unit/CrossVersioningUnitTests.java | 614 +++ .../unit/CustomerExampleUnitTests.java | 892 ++++ .../hybridrow/unit/DeleteRowDispatcher.java | 167 + .../hybridrow/unit/IDispatchable.java | 11 + .../hybridrow/unit/IDispatcher.java | 42 + .../unit/LayoutCompilerUnitTests.java | 3238 ++++++++++++++ .../hybridrow/unit/LayoutTypeUnitTests.java | 46 + .../hybridrow/unit/NullRowDispatcher.java | 87 + .../hybridrow/unit/NullableUnitTests.java | 753 ++++ .../hybridrow/unit/PermuteExtensions.java | 33 + .../unit/RandomGeneratorUnitTests.java | 77 + .../hybridrow/unit/ReadRowDispatcher.java | 239 ++ .../hybridrow/unit/RecordIOUnitTests.java | 242 ++ .../hybridrow/unit/ResultAssert.java | 80 + .../hybridrow/unit/RowBufferUnitTests.java | 70 + .../unit/RowOperationDispatcher.java | 437 ++ .../hybridrow/unit/RowReaderUnitTests.java | 426 ++ .../hybridrow/unit/RowWriterUnitTests.java | 509 +++ .../hybridrow/unit/SchemaHashUnitTests.java | 272 ++ .../hybridrow/unit/SchemaIdUnitTests.java | 44 + .../hybridrow/unit/SchemaUnitTests.java | 994 +++++ .../hybridrow/unit/SerializerUnitTest.java | 317 ++ .../hybridrow/unit/TaggedUnitTests.java | 256 ++ .../hybridrow/unit/TupleUnitTests.java | 1104 +++++ .../hybridrow/unit/TypedArrayUnitTests.java | 663 +++ .../hybridrow/unit/TypedMapUnitTests.java | 1575 +++++++ .../hybridrow/unit/TypedSetUnitTests.java | 1995 +++++++++ .../unit/UpdateOptionsUnitTests.java | 20 + .../hybridrow/unit/WriteRowDispatcher.java | 247 ++ .../unit/customerschema/Address.java | 47 + .../customerschema/AddressSerializer.java | 96 + .../hybridrow/unit/customerschema/Guest.java | 94 + .../hybridrow/unit/customerschema/Hotel.java | 50 + .../unit/customerschema/PostalCode.java | 41 + .../customerschema/PostalCodeSerializer.java | 69 + .../unit/internal/MurmurHash3UnitTests.java | 126 + java/pom.xml | 293 ++ .../java/com/azure/data/cosmos/core/Json.java | 74 + .../java/com/azure/data/cosmos/core/Out.java | 86 + .../com/azure/data/cosmos/core/Reference.java | 79 + .../azure/data/cosmos/core/Utf8String.java | 1422 +++++++ .../azure/data/cosmos/core/UtfAnyString.java | 309 ++ .../serialization/hybridrow/Float128.java | 55 + .../serialization/hybridrow/HashCode128.java | 77 + .../hybridrow/HybridRowHeader.java | 56 + .../hybridrow/HybridRowVersion.java | 50 + .../serialization/hybridrow/NullValue.java | 41 + .../serialization/hybridrow/Result.java | 74 + .../serialization/hybridrow/RowBuffer.java | 3761 +++++++++++++++++ .../serialization/hybridrow/RowCursor.java | 415 ++ .../serialization/hybridrow/RowCursors.java | 137 + .../serialization/hybridrow/RowOptions.java | 85 + .../serialization/hybridrow/SchemaId.java | 160 + .../serialization/hybridrow/UnixDateTime.java | 78 + .../hybridrow/codecs/DateTimeCodec.java | 144 + .../hybridrow/codecs/DecimalCodec.java | 200 + .../hybridrow/codecs/Float128Codec.java | 72 + .../hybridrow/codecs/GuidCodec.java | 115 + .../hybridrow/internal/Murmur3Hash.java | 129 + .../serialization/hybridrow/io/DataItem.java | 108 + .../serialization/hybridrow/io/RowReader.java | 1274 ++++++ .../hybridrow/io/RowReaderExtensions.java | 95 + .../hybridrow/io/RowScanner.java | 545 +++ .../hybridrow/io/RowSerializable.java | 21 + .../serialization/hybridrow/io/RowWriter.java | 794 ++++ .../serialization/hybridrow/io/Segment.java | 43 + .../json/RowReaderJsonExtensions.java | 441 ++ .../hybridrow/json/RowReaderJsonSettings.java | 43 + .../hybridrow/layouts/ILayoutType.java | 10 + .../hybridrow/layouts/Layout.java | 242 ++ .../hybridrow/layouts/LayoutArray.java | 52 + .../hybridrow/layouts/LayoutBinary.java | 197 + .../hybridrow/layouts/LayoutBit.java | 119 + .../hybridrow/layouts/LayoutBoolean.java | 141 + .../hybridrow/layouts/LayoutBuilder.java | 180 + .../hybridrow/layouts/LayoutCode.java | 119 + .../hybridrow/layouts/LayoutCodeTraits.java | 41 + .../hybridrow/layouts/LayoutColumn.java | 242 ++ .../layouts/LayoutCompilationException.java | 20 + .../hybridrow/layouts/LayoutCompiler.java | 433 ++ .../hybridrow/layouts/LayoutDateTime.java | 96 + .../hybridrow/layouts/LayoutDecimal.java | 92 + .../hybridrow/layouts/LayoutEndScope.java | 48 + .../hybridrow/layouts/LayoutFloat128.java | 95 + .../hybridrow/layouts/LayoutFloat32.java | 94 + .../hybridrow/layouts/LayoutFloat64.java | 97 + .../hybridrow/layouts/LayoutGuid.java | 96 + .../hybridrow/layouts/LayoutIndexedScope.java | 32 + .../hybridrow/layouts/LayoutInt16.java | 94 + .../hybridrow/layouts/LayoutInt32.java | 94 + .../hybridrow/layouts/LayoutInt64.java | 93 + .../hybridrow/layouts/LayoutInt8.java | 94 + .../hybridrow/layouts/LayoutListReadable.java | 25 + .../hybridrow/layouts/LayoutListWritable.java | 26 + .../layouts/LayoutMongoDbObjectId.java | 88 + .../hybridrow/layouts/LayoutNull.java | 85 + .../hybridrow/layouts/LayoutNullable.java | 144 + .../hybridrow/layouts/LayoutObject.java | 68 + .../layouts/LayoutPropertyScope.java | 10 + .../hybridrow/layouts/LayoutResolver.java | 13 + .../layouts/LayoutResolverNamespace.java | 64 + .../layouts/LayoutResolverSimple.java | 27 + .../hybridrow/layouts/LayoutTagged.java | 118 + .../hybridrow/layouts/LayoutTagged2.java | 131 + .../hybridrow/layouts/LayoutTuple.java | 106 + .../hybridrow/layouts/LayoutType.java | 401 ++ .../layouts/LayoutTypePrimitive.java | 197 + .../hybridrow/layouts/LayoutTypeScope.java | 227 + .../hybridrow/layouts/LayoutTypedArray.java | 101 + .../hybridrow/layouts/LayoutTypedMap.java | 135 + .../hybridrow/layouts/LayoutTypedSet.java | 121 + .../hybridrow/layouts/LayoutTypedTuple.java | 132 + .../hybridrow/layouts/LayoutTypes.java | 56 + .../hybridrow/layouts/LayoutUDT.java | 71 + .../hybridrow/layouts/LayoutUInt16.java | 94 + .../hybridrow/layouts/LayoutUInt32.java | 97 + .../hybridrow/layouts/LayoutUInt64.java | 95 + .../hybridrow/layouts/LayoutUInt8.java | 101 + .../hybridrow/layouts/LayoutUniqueScope.java | 151 + .../hybridrow/layouts/LayoutUnixDateTime.java | 94 + .../hybridrow/layouts/LayoutUtf8.java | 246 ++ .../hybridrow/layouts/LayoutUtf8Readable.java | 27 + .../hybridrow/layouts/LayoutUtf8Writable.java | 29 + .../hybridrow/layouts/LayoutVarInt.java | 120 + .../hybridrow/layouts/LayoutVarUInt.java | 120 + .../hybridrow/layouts/StringToken.java | 93 + .../hybridrow/layouts/StringTokenizer.java | 110 + .../hybridrow/layouts/SystemSchema.java | 85 + .../hybridrow/layouts/TypeArgument.java | 90 + .../hybridrow/layouts/TypeArgumentList.java | 156 + .../hybridrow/layouts/UpdateOptions.java | 74 + .../hybridrow/schemas/ArrayPropertyType.java | 39 + .../hybridrow/schemas/MapPropertyType.java | 46 + .../hybridrow/schemas/Namespace.java | 132 + .../hybridrow/schemas/ObjectPropertyType.java | 40 + .../hybridrow/schemas/PartitionKey.java | 24 + .../hybridrow/schemas/PrimarySortKey.java | 46 + .../schemas/PrimitivePropertyType.java | 51 + .../hybridrow/schemas/Property.java | 104 + .../hybridrow/schemas/PropertyType.java | 125 + .../hybridrow/schemas/Schema.java | 290 ++ .../hybridrow/schemas/SchemaException.java | 20 + .../hybridrow/schemas/SchemaHash.java | 213 + .../schemas/SchemaLanguageVersion.java | 70 + .../hybridrow/schemas/SchemaOptions.java | 66 + .../hybridrow/schemas/SchemaValidator.java | 326 ++ .../hybridrow/schemas/ScopePropertyType.java | 24 + .../hybridrow/schemas/SetPropertyType.java | 31 + .../hybridrow/schemas/SortDirection.java | 49 + .../hybridrow/schemas/StaticKey.java | 28 + .../hybridrow/schemas/StorageKind.java | 84 + .../hybridrow/schemas/TaggedPropertyType.java | 42 + .../hybridrow/schemas/TuplePropertyType.java | 37 + .../hybridrow/schemas/TypeKind.java | 236 ++ .../hybridrow/schemas/UdtPropertyType.java | 76 + .../data/cosmos/core/Utf8StringTest.java | 505 +++ .../data/cosmos/core/UtfAnyStringTest.java | 74 + .../hybridrow/codecs/DateTimeCodecTest.java | 90 + .../hybridrow/codecs/DecimalCodecTest.java | 133 + .../hybridrow/codecs/GuidCodecTest.java | 96 + .../hybridrow/io/RowReaderTest.java | 290 ++ .../hybridrow/layouts/SystemSchemaTest.java | 31 + .../hybridrow/schemas/NamespaceTest.java | 143 + java/src/test/resources/log4j.properties | 6 + layout.xlsx | Bin 0 -> 27664 bytes schemas/SystemSchema.json | 54 + test-data/BatchApiSchema.json | 96 + test-data/CoverageSchema.json | 211 + test-data/CrossVersioningExpected.json | 8 + test-data/CrossVersioningSchema.json | 127 + test-data/CustomerSchema.json | 76 + test-data/MovieSchema.json | 40 + test-data/NullableSchema.json | 26 + test-data/PerfCounterSchema.json | 72 + test-data/ReaderSchema.json | 143 + test-data/RootSegment.bin | Bin 0 -> 1048576 bytes test-data/RootSegment.hybridrow | Bin 0 -> 14147 bytes test-data/RootSegment.json | 609 +++ test-data/SchemaHashCoverageSchema.json | 171 + test-data/TagSchema.json | 28 + test-data/TaggedApiSchema.json | 28 + test-data/TodoSchema.json | 75 + 226 files changed, 47672 insertions(+), 34 deletions(-) create mode 100644 CONTRIBUTING.md delete mode 100644 LICENSE create mode 100644 LICENSE.TXT rename Hybrid Row Whitepaper.docx => docs/Hybrid-row-whitepaper.docx (100%) create mode 100644 dotnet/src/Core/UtfAnyString.cs create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/ISpanResizer.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/MemorySpanResizer.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingStringComparer.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingUtf8StringComparer.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/Record.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOFormatter.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOParser.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOStream.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordSerializer.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/SegmentSerializer.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertySchemaConverter.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictBooleanConverter.java create mode 100644 java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictIntegerConverter.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BenchmarkSuiteBase.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonJsonModelRowGenerator.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonReaderExtensions.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonRowGenerator.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenMicroBenchmarkSuite.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenRowGenerator.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/GenerateBenchmarkSuite.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/JsonModelRowGenerator.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/Measurements.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/MicroBenchmarkSuiteBase.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ProtobufRowGenerator.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ReaderBenchmark.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/RowReaderExtensions.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/SchematizedMicroBenchmarkSuite.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/TestData.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/UnschematizedMicroBenchmarkSuite.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Address.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Available_Rooms_By_Hotel_Date.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/CassandraHotelSchemaReflection.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Guests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Hotels.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/PostalCode.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ArrayAssert.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/AssertThrowsException.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CrossVersioningUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CustomerExampleUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/DeleteRowDispatcher.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatchable.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatcher.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutCompilerUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutTypeUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullRowDispatcher.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/PermuteExtensions.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RandomGeneratorUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ReadRowDispatcher.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RecordIOUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ResultAssert.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowBufferUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowOperationDispatcher.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowReaderUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowWriterUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaHashUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaIdUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SerializerUnitTest.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TaggedUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TupleUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedArrayUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedMapUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedSetUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/UpdateOptionsUnitTests.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/WriteRowDispatcher.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Address.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/AddressSerializer.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Guest.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Hotel.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCode.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCodeSerializer.java create mode 100644 java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/internal/MurmurHash3UnitTests.java create mode 100644 java/pom.xml create mode 100644 java/src/main/java/com/azure/data/cosmos/core/Json.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/Out.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/Reference.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/Utf8String.java create mode 100644 java/src/main/java/com/azure/data/cosmos/core/UtfAnyString.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/NullValue.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowOptions.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/SchemaId.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/UnixDateTime.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/Float128Codec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodec.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/internal/Murmur3Hash.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/DataItem.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderExtensions.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowScanner.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowSerializable.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/Segment.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonExtensions.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonSettings.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/ILayoutType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBit.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBoolean.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBuilder.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCode.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCodeTraits.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutColumn.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompilationException.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompiler.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDecimal.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutEndScope.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat128.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat32.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat64.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutIndexedScope.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt16.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt32.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt64.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt8.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListReadable.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListWritable.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutMongoDbObjectId.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNull.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutObject.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutPropertyScope.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolver.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverNamespace.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverSimple.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged2.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTuple.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypePrimitive.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypeScope.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedArray.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedMap.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedSet.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedTuple.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypes.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUDT.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt16.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt32.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt64.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt8.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUniqueScope.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUnixDateTime.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Readable.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Writable.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringToken.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchema.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgument.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgumentList.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/UpdateOptions.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ArrayPropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/MapPropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Namespace.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ObjectPropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PartitionKey.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimarySortKey.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimitivePropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Property.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Schema.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaException.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaHash.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaLanguageVersion.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaOptions.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaValidator.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ScopePropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SetPropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SortDirection.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StaticKey.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StorageKind.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TaggedPropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TuplePropertyType.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TypeKind.java create mode 100644 java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/UdtPropertyType.java create mode 100644 java/src/test/java/com/azure/data/cosmos/core/Utf8StringTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/core/UtfAnyStringTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodecTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodecTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodecTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchemaTest.java create mode 100644 java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/schemas/NamespaceTest.java create mode 100644 java/src/test/resources/log4j.properties create mode 100644 layout.xlsx create mode 100644 schemas/SystemSchema.json create mode 100644 test-data/BatchApiSchema.json create mode 100644 test-data/CoverageSchema.json create mode 100644 test-data/CrossVersioningExpected.json create mode 100644 test-data/CrossVersioningSchema.json create mode 100644 test-data/CustomerSchema.json create mode 100644 test-data/MovieSchema.json create mode 100644 test-data/NullableSchema.json create mode 100644 test-data/PerfCounterSchema.json create mode 100644 test-data/ReaderSchema.json create mode 100644 test-data/RootSegment.bin create mode 100644 test-data/RootSegment.hybridrow create mode 100644 test-data/RootSegment.json create mode 100644 test-data/SchemaHashCoverageSchema.json create mode 100644 test-data/TagSchema.json create mode 100644 test-data/TaggedApiSchema.json create mode 100644 test-data/TodoSchema.json diff --git a/.gitignore b/.gitignore index 3e759b7..1ebbeff 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +target/ # Visual Studio 2015/2017 cache/options directory .vs/ @@ -328,3 +329,4 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ +*.iml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ebf23ac --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to +agree to a Contributor License Agreement (CLA) declaring that you have the right to, +and actually do, grant us the rights to use your contribution. For details, visit +https://cla.microsoft.com. + +When you submit a pull request, a CLA-bot will automatically determine whether you need +to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the +instructions provided by the bot. You will only need to do this once across all repositories using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) +or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4b1ad51..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - MIT License - - Copyright (c) Microsoft Corporation. All rights reserved. - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE diff --git a/LICENSE.TXT b/LICENSE.TXT new file mode 100644 index 0000000..4437826 --- /dev/null +++ b/LICENSE.TXT @@ -0,0 +1,21 @@ +Copyright (c) Microsoft Corporation. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index b81a84e..fe1d34b 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,3 @@ +# PLACEHOLDER -# Contributing - -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. - -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. +TODO: DANOBLE: Write README.md diff --git a/Hybrid Row Whitepaper.docx b/docs/Hybrid-row-whitepaper.docx similarity index 100% rename from Hybrid Row Whitepaper.docx rename to docs/Hybrid-row-whitepaper.docx diff --git a/dotnet/src/Core/UtfAnyString.cs b/dotnet/src/Core/UtfAnyString.cs new file mode 100644 index 0000000..34ebd40 --- /dev/null +++ b/dotnet/src/Core/UtfAnyString.cs @@ -0,0 +1,480 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +#pragma warning disable CA2225 // Operator overloads have named alternates + +// ReSharper disable once UseNameofExpression +namespace Microsoft.Azure.Cosmos.Core.Utf8 +{ + using System; + using System.Diagnostics; + using System.Runtime.CompilerServices; + + /// A string whose memory representation may be either UTF8 or UTF16. + /// + /// This type supports polymorphic use of and + /// when equality, hashing, and comparison are needed against either encoding. An API leveraging + /// can avoid separate method overloads while still accepting either + /// encoding without imposing additional allocations. + /// + [DebuggerDisplay("{ToString()}")] + public readonly struct UtfAnyString : + IEquatable, IComparable, + IEquatable, IComparable, + IEquatable, IComparable + { + public static UtfAnyString Empty => string.Empty; + + private readonly object buffer; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public UtfAnyString(string utf16String) + { + this.buffer = utf16String; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public UtfAnyString(Utf8String utf8String) + { + this.buffer = utf8String; + } + + public bool IsUtf8 => this.buffer is Utf8String; + + public bool IsUtf16 => this.buffer is string; + + /// True if the length is empty. + public bool IsNull => object.ReferenceEquals(null, this.buffer); + + /// True if the length is empty. + public bool IsEmpty + { + get + { + if (object.ReferenceEquals(null, this.buffer)) + { + return false; + } + + switch (this.buffer) + { + case string s: + return s.Length == 0; + default: + return ((Utf8String)this.buffer).IsEmpty; + } + } + } + + public static implicit operator UtfAnyString(string utf16String) + { + return new UtfAnyString(utf16String); + } + + public static implicit operator string(UtfAnyString str) + { + return str.buffer?.ToString(); + } + + public override string ToString() + { + // ReSharper disable once AssignNullToNotNullAttribute + return this.buffer?.ToString(); + } + + public Utf8String ToUtf8String() + { + if (object.ReferenceEquals(null, this.buffer)) + { + return null; + } + + switch (this.buffer) + { + case string s: + return Utf8String.TranscodeUtf16(s); + default: + return (Utf8String)this.buffer; + } + } + + public bool ReferenceEquals(UtfAnyString other) + { + return this.buffer == other.buffer; + } + + public bool Equals(UtfAnyString other) + { + if (object.ReferenceEquals(null, this.buffer)) + { + return object.ReferenceEquals(null, other.buffer); + } + + switch (this.buffer) + { + case string s: + return other.Equals(s); + default: + return other.Equals((Utf8String)this.buffer); + } + } + + public bool Equals(Utf8Span other) + { + return other.Equals(this.buffer); + } + + public override bool Equals(object obj) + { + switch (obj) + { + case string s: + return this.Equals(s); + case Utf8String s: + return this.Equals(s); + case UtfAnyString s: + return this.Equals(s); + } + + return false; + } + + public bool Equals(Utf8String other) + { + if (object.ReferenceEquals(null, other)) + { + return object.ReferenceEquals(null, this.buffer); + } + + return other.Equals(this.buffer); + } + + public bool Equals(string other) + { + if (object.ReferenceEquals(null, this.buffer)) + { + return object.ReferenceEquals(null, other); + } + + switch (this.buffer) + { + case string s: + return string.Equals(s, other, StringComparison.Ordinal); + default: + return ((Utf8String)this.buffer).Equals(other); + } + } + + public static bool operator ==(UtfAnyString left, UtfAnyString right) + { + return left.Equals(right); + } + + public static bool operator !=(UtfAnyString left, UtfAnyString right) + { + return !left.Equals(right); + } + + public static bool operator ==(UtfAnyString left, string right) + { + return left.Equals(right); + } + + public static bool operator !=(UtfAnyString left, string right) + { + return !left.Equals(right); + } + + public static bool operator ==(string left, UtfAnyString right) + { + return right.Equals(left); + } + + public static bool operator !=(string left, UtfAnyString right) + { + return !right.Equals(left); + } + + public static bool operator ==(UtfAnyString left, Utf8String right) + { + return left.Equals(right); + } + + public static bool operator !=(UtfAnyString left, Utf8String right) + { + return !left.Equals(right); + } + + public static bool operator ==(Utf8String left, UtfAnyString right) + { + return right.Equals(left); + } + + public static bool operator !=(Utf8String left, UtfAnyString right) + { + return !right.Equals(left); + } + + public static bool operator ==(UtfAnyString left, Utf8Span right) + { + return left.Equals(right); + } + + public static bool operator !=(UtfAnyString left, Utf8Span right) + { + return !left.Equals(right); + } + + public static bool operator ==(Utf8Span left, UtfAnyString right) + { + return right.Equals(left); + } + + public static bool operator !=(Utf8Span left, UtfAnyString right) + { + return !right.Equals(left); + } + + public override int GetHashCode() + { + uint hash1 = 5381; + uint hash2 = hash1; + + if (object.ReferenceEquals(null, this.buffer)) + { + return unchecked((int)(hash1 + (hash2 * 1566083941))); + } + + switch (this.buffer) + { + case string s: + unchecked + { + Utf16LittleEndianCodePointEnumerator thisEnumerator = new Utf16LittleEndianCodePointEnumerator(s); + for (int i = 0; thisEnumerator.MoveNext(); i++) + { + uint c = thisEnumerator.Current; + if (i % 2 == 0) + { + hash1 = ((hash1 << 5) + hash1) ^ c; + } + else + { + hash2 = ((hash2 << 5) + hash2) ^ c; + } + } + + return (int)(hash1 + (hash2 * 1566083941)); + } + + default: + return this.buffer.GetHashCode(); + } + } + + public static bool operator <(UtfAnyString left, UtfAnyString right) + { + return left.CompareTo(right) < 0; + } + + public static bool operator <=(UtfAnyString left, UtfAnyString right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator >(UtfAnyString left, UtfAnyString right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >=(UtfAnyString left, UtfAnyString right) + { + return left.CompareTo(right) >= 0; + } + + public static bool operator <(UtfAnyString left, string right) + { + return left.CompareTo(right) < 0; + } + + public static bool operator <=(UtfAnyString left, string right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator >(UtfAnyString left, string right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >=(UtfAnyString left, string right) + { + return left.CompareTo(right) >= 0; + } + + public static bool operator <(string left, UtfAnyString right) + { + return right.CompareTo(left) >= 0; + } + + public static bool operator <=(string left, UtfAnyString right) + { + return right.CompareTo(left) > 0; + } + + public static bool operator >(string left, UtfAnyString right) + { + return right.CompareTo(left) <= 0; + } + + public static bool operator >=(string left, UtfAnyString right) + { + return right.CompareTo(left) < 0; + } + + public static bool operator <(UtfAnyString left, Utf8String right) + { + return left.CompareTo(right) < 0; + } + + public static bool operator <=(UtfAnyString left, Utf8String right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator >(UtfAnyString left, Utf8String right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >=(UtfAnyString left, Utf8String right) + { + return left.CompareTo(right) >= 0; + } + + public static bool operator <(Utf8String left, UtfAnyString right) + { + return right.CompareTo(left) >= 0; + } + + public static bool operator <=(Utf8String left, UtfAnyString right) + { + return right.CompareTo(left) > 0; + } + + public static bool operator >(Utf8String left, UtfAnyString right) + { + return right.CompareTo(left) <= 0; + } + + public static bool operator >=(Utf8String left, UtfAnyString right) + { + return right.CompareTo(left) < 0; + } + + public static bool operator <(UtfAnyString left, Utf8Span right) + { + return left.CompareTo(right) < 0; + } + + public static bool operator <=(UtfAnyString left, Utf8Span right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator >(UtfAnyString left, Utf8Span right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >=(UtfAnyString left, Utf8Span right) + { + return left.CompareTo(right) >= 0; + } + + public static bool operator <(Utf8Span left, UtfAnyString right) + { + return right.CompareTo(left) >= 0; + } + + public static bool operator <=(Utf8Span left, UtfAnyString right) + { + return right.CompareTo(left) > 0; + } + + public static bool operator >(Utf8Span left, UtfAnyString right) + { + return right.CompareTo(left) <= 0; + } + + public static bool operator >=(Utf8Span left, UtfAnyString right) + { + return right.CompareTo(left) < 0; + } + + public int CompareTo(UtfAnyString other) + { + if (object.ReferenceEquals(null, other.buffer)) + { + return object.ReferenceEquals(null, this.buffer) ? 0 : 1; + } + + switch (other.buffer) + { + case string s: + return this.CompareTo(s); + default: + return this.CompareTo((Utf8String)other.buffer); + } + } + + public int CompareTo(Utf8String other) + { + if (object.ReferenceEquals(null, this.buffer)) + { + return object.ReferenceEquals(null, other) ? 0 : -1; + } + + switch (this.buffer) + { + case string s: + return -other.Span.CompareTo(s); + default: + return -other.Span.CompareTo((Utf8String)this.buffer); + } + } + + public int CompareTo(Utf8Span other) + { + if (object.ReferenceEquals(null, this.buffer)) + { + return -1; + } + + switch (this.buffer) + { + case string s: + return -other.CompareTo(s); + default: + return -other.CompareTo((Utf8String)this.buffer); + } + } + + public int CompareTo(string other) + { + if (object.ReferenceEquals(null, this.buffer)) + { + return object.ReferenceEquals(null, other) ? 0 : -1; + } + + switch (this.buffer) + { + case string s: + return string.Compare(s, other, StringComparison.Ordinal); + default: + return ((Utf8String)this.buffer).CompareTo(other); + } + } + } +} diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/ISpanResizer.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/ISpanResizer.java new file mode 100644 index 0000000..bb25c0d --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/ISpanResizer.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +public interface ISpanResizer { + /** + * Resizes an existing a buffer. + * The type of the elements of the memory. + * + * @param minimumLength The minimum required length (in elements) of the memory. + * @param buffer Optional existing memory to be copied to the new buffer. Ownership of is + * transferred as part of this call and it should not be used by the caller after this call + * completes. + * @return A new memory whose size is at least as big as + * and containing the content of . + */ + + Span Resize(int minimumLength); + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: Span Resize(int minimumLength, Span buffer = default); + Span Resize(int minimumLength, Span buffer); +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/MemorySpanResizer.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/MemorySpanResizer.java new file mode 100644 index 0000000..712863d --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/MemorySpanResizer.java @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class MemorySpanResizer implements ISpanResizer { + private Memory memory; + + + public MemorySpanResizer() { + this(0); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public MemorySpanResizer(int initialCapacity = 0) + public MemorySpanResizer(int initialCapacity) { + checkArgument(initialCapacity >= 0); + + //C# TO JAVA CONVERTER WARNING: Java does not allow direct instantiation of arrays of generic type parameters: + //ORIGINAL LINE: this.memory = initialCapacity == 0 ? default : new Memory(new T[initialCapacity]); + this.memory = initialCapacity == 0 ? null : new Memory((T[])new Object[initialCapacity]); + } + + public Memory getMemory() { + return this.memory; + } + + /** + * + */ + + public Span Resize(int minimumLength) { + return Resize(minimumLength, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public Span Resize(int minimumLength, Span buffer = default) + public Span Resize(int minimumLength, Span buffer) { + if (this.memory.Length < minimumLength) { + //C# TO JAVA CONVERTER WARNING: Java does not allow direct instantiation of arrays of generic type + // parameters: + //ORIGINAL LINE: this.memory = new Memory(new T[Math.Max(minimumLength, buffer.Length)]); + this.memory = new Memory((T[])new Object[Math.max(minimumLength, buffer.Length)]); + } + + Span next = this.memory.Span; + if (!buffer.IsEmpty && next.Slice(0, buffer.Length) != buffer) { + buffer.CopyTo(next); + } + + return next; + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingStringComparer.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingStringComparer.java new file mode 100644 index 0000000..2427305 --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingStringComparer.java @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +public class SamplingStringComparer implements IEqualityComparer { + + public static final SamplingStringComparer Default = new SamplingStringComparer(); + + public final boolean equals(String x, String y) { + checkArgument(x != null); + checkArgument(y != null); + + return x.equals(y); + } + + public final int hashCode(String obj) { + checkArgument(obj != null); + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint hash1 = 5381; + int hash1 = 5381; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint hash2 = hash1; + int hash2 = hash1; + final int numSamples = 4; + final int modulus = 13; + + ReadOnlySpan utf16 = obj.AsSpan(); + int max = Math.min(utf16.Length, numSamples); + for (int i = 0; i < max; i++) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint c = utf16[(i * modulus) % utf16.Length]; + int c = utf16[(i * modulus) % utf16.Length]; + if (i % 2 == 0) { + hash1 = ((hash1 << 5) + hash1) ^ c; + } else { + hash2 = ((hash2 << 5) + hash2) ^ c; + } + } + + return hash1 + (hash2 * 1566083941); + } + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingUtf8StringComparer.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingUtf8StringComparer.java new file mode 100644 index 0000000..c2f589e --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SamplingUtf8StringComparer.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +public class SamplingUtf8StringComparer implements IEqualityComparer { + public static final SamplingUtf8StringComparer Default = new SamplingUtf8StringComparer(); + + public final boolean equals(Utf8String x, Utf8String y) { + checkArgument(x != null); + checkArgument(y != null); + + return x.Span.equals(y.Span); + } + + public final int hashCode(Utf8String obj) { + checkArgument(obj != null); + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint hash1 = 5381; + int hash1 = 5381; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint hash2 = hash1; + int hash2 = hash1; + final int numSamples = 4; + final int modulus = 13; + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ReadOnlySpan utf8 = obj.Span.Span; + ReadOnlySpan utf8 = obj.Span.Span; + int max = Math.min(utf8.Length, numSamples); + for (int i = 0; i < max; i++) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint c = utf8[(i * modulus) % utf8.Length]; + int c = utf8[(i * modulus) % utf8.Length]; + if (i % 2 == 0) { + hash1 = ((hash1 << 5) + hash1) ^ c; + } else { + hash2 = ((hash2 << 5) + hash2) ^ c; + } + } + + return hash1 + (hash2 * 1566083941); + } + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/Record.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/Record.java new file mode 100644 index 0000000..490d34e --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/Record.java @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.recordio; + +public final class Record { + + public static Record empty() { + return new Record(0, 0); + } + + private int crc32; + private int length; + + public Record(int length, int crc32) { + this.length = length; + this.crc32 = crc32; + } + + public int crc32() { + return this.crc32; + } + + public Record crc32(int value) { + this.crc32 = value; + return this; + } + + public int length() { + return this.length; + } + + public Record length(int value) { + this.length = value; + return this; + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOFormatter.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOFormatter.java new file mode 100644 index 0000000..689825b --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOFormatter.java @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.recordio; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowHeader; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.ISpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.SystemSchema; + +public final class RecordIOFormatter { + + public static final Layout RECORD_LAYOUT = SystemSchema.layoutResolver.resolve(SystemSchema.RECORD_SCHEMA_ID); + public static final Layout SEGMENT_LAYOUT = SystemSchema.layoutResolver.resolve(SystemSchema.SEGMENT_SCHEMA_ID); + + public static Result FormatRecord(ReadOnlyMemory body, Out row) { + return FormatRecord(body, row, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public static Result FormatRecord(ReadOnlyMemory body, out RowBuffer row, + // ISpanResizer resizer = default) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public static Result FormatRecord(ReadOnlyMemory body, Out row, + ISpanResizer resizer) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: resizer = resizer != null ? resizer : DefaultSpanResizer.Default; + resizer = resizer != null ? resizer : DefaultSpanResizer < Byte >.Default; + int estimatedSize = HybridRowHeader.BYTES + RecordIOFormatter.RECORD_LAYOUT.getSize() + body.Length; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint crc32 = Crc32.Update(0, body.Span); + int crc32 = Crc32.Update(0, body.Span); + Record record = new Record(body.Length, crc32); + return RecordIOFormatter.FormatObject(resizer, estimatedSize, RecordIOFormatter.RECORD_LAYOUT, record.clone(), + RecordSerializer.Write, row.clone()); + } + + public static Result FormatSegment(Segment segment, Out row) { + return FormatSegment(segment, row, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public static Result FormatSegment(Segment segment, out RowBuffer row, ISpanResizer + // resizer = default) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public static Result FormatSegment(Segment segment, Out row, ISpanResizer resizer) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: resizer = resizer != null ? resizer : DefaultSpanResizer.Default; + resizer = resizer != null ? resizer : DefaultSpanResizer < Byte >.Default; + int estimatedSize = + HybridRowHeader.BYTES + RecordIOFormatter.SEGMENT_LAYOUT.getSize() + segment.comment() == null ? null : + segment.comment().length() != null ? segment.comment().length() : 0 + segment.sdl() == null ? null : + segment.sdl().length() != null ? segment.sdl().length() : 0 + 20; + + return RecordIOFormatter.FormatObject(resizer, estimatedSize, RecordIOFormatter.SEGMENT_LAYOUT, + segment.clone(), SegmentSerializer.Write, row.clone()); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static Result FormatObject(ISpanResizer resizer, int initialCapacity, Layout + // layout, T obj, RowWriter.WriterFunc writer, out RowBuffer row) + private static Result FormatObject(ISpanResizer resizer, int initialCapacity, Layout layout, T obj, + RowWriter.WriterFunc writer, Out row) { + row.setAndGet(new RowBuffer(initialCapacity, resizer)); + row.get().initLayout(HybridRowVersion.V1, layout, SystemSchema.layoutResolver); + Result r = RowWriter.WriteBuffer(row.clone(), obj, writer); + if (r != Result.SUCCESS) { + row.setAndGet(null); + return r; + } + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOParser.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOParser.java new file mode 100644 index 0000000..d6547b5 --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOParser.java @@ -0,0 +1,354 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.recordio; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowHeader; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.Segment; +import com.azure.data.cosmos.serialization.hybridrow.layouts.SystemSchema; +import io.netty.buffer.ByteBuf; +import it.unimi.dsi.fastutil.bytes.Byte2ObjectMap; +import it.unimi.dsi.fastutil.bytes.Byte2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkState; + +public final class RecordIOParser { + + private Record record; + private Segment segment; + private State state = State.values()[0]; + + /** + * Processes one buffers worth of data possibly advancing the parser state + * + * @param buffer1 The buffer to consume + * @param type Indicates the type of Hybrid Row produced in {@code record} + * @param record If non-empty, then the body of the next record in the sequence + * @param need The smallest number of bytes needed to advanced the parser state further + *

+ * It is recommended that this method not be called again until at least this number of bytes are + * available. + * @param consumed The number of bytes consumed from the input buffer + *

+ * This number may be less than the total buffer size if the parser moved to a new state. + * @return {@link Result#SUCCESS} if no error has occurred;, otherwise the {@link Result} of the last error + * encountered during parsing. + *

+ * > + */ + @Nonnull + public Result process( + @Nonnull final ByteBuf buffer, + @Nonnull final Out type, + @Nonnull final Out record, + @Nonnull final Out need, + @Nonnull final Out consumed) { + + Result result = Result.FAILURE; + type.set(ProductionType.NONE); + record.set(null); + + final int start = buffer.readerIndex(); + + switch (this.state) { + + case STATE: + this.state = State.NEED_SEGMENT_LENGTH; + // TODO: C# TO JAVA CONVERTER: There is no 'goto' in Java: + // goto case State.NeedSegmentLength; + + case NEED_SEGMENT_LENGTH: { + + final int minimalSegmentRowSize = HybridRowHeader.BYTES + RecordIOFormatter.SEGMENT_LAYOUT.size(); + + if (buffer.readableBytes() < minimalSegmentRowSize) { + consumed.set(buffer.readerIndex() - start); + need.set(minimalSegmentRowSize); + return Result.INSUFFICIENT_BUFFER; + } + + ByteBuf span = buffer.slice(buffer.readerIndex(), minimalSegmentRowSize); + RowBuffer row = new RowBuffer(span, HybridRowVersion.V1, SystemSchema.layoutResolver); + Reference tempReference_row = + new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + Reference tempReference_reader = + new Reference(reader); + Out tempOut_segment = + new Out(); + result = SegmentSerializer.read(tempReference_reader, tempOut_segment); + this.segment = tempOut_segment.get(); + reader = tempReference_reader.get(); + if (result != Result.SUCCESS) { + break; + } + + this.state = State.NEED_SEGMENT; + // TODO: C# TO JAVA CONVERTER: There is no 'goto' in Java: + goto case State.NEED_SEGMENT + } + + case NEED_SEGMENT: { + if (buffer.Length < this.segment.length()) { + need.set(this.segment.length()); + consumed.set(buffer.Length - buffer.Length); + return Result.INSUFFICIENT_BUFFER; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Span span = b.Span.Slice(0, this.segment.Length); + Span span = buffer.Span.Slice(0, this.segment.length()); + RowBuffer row = new RowBuffer(span, HybridRowVersion.V1, SystemSchema.layoutResolver); + Reference tempReference_row2 = + new Reference(row); + RowReader reader = new RowReader(tempReference_row2); + row = tempReference_row2.get(); + Reference tempReference_reader2 = + new Reference(reader); + Out tempOut_segment2 + = new Out(); + result = SegmentSerializer.read(tempReference_reader2, tempOut_segment2); + this.segment = tempOut_segment2.get(); + reader = tempReference_reader2.get(); + if (result != Result.SUCCESS) { + break; + } + + record.set(buffer.Slice(0, span.Length)); + buffer = buffer.Slice(span.Length); + need.set(0); + this.state = State.NEED_HEADER; + consumed.set(buffer.Length - buffer.Length); + type.set(ProductionType.SEGMENT); + return Result.SUCCESS; + } + + case NEED_HEADER: { + if (buffer.Length < HybridRowHeader.BYTES) { + need.set(HybridRowHeader.BYTES); + consumed.set(buffer.Length - buffer.Length); + return Result.INSUFFICIENT_BUFFER; + } + + HybridRowHeader header; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + MemoryMarshal.TryRead(buffer.Span, out header); + if (header.Version != HybridRowVersion.V1) { + result = Result.INVALID_ROW; + break; + } + + if (SchemaId.opEquals(header.SchemaId, + SystemSchema.SEGMENT_SCHEMA_ID)) { + // TODO: C# TO JAVA CONVERTER: There is no 'goto' in Java: + goto case State.NEED_SEGMENT + } + + if (SchemaId.opEquals(header.SchemaId, + SystemSchema.RECORD_SCHEMA_ID)) { + // TODO: C# TO JAVA CONVERTER: There is no 'goto' in Java: + goto case State.NEED_RECORD + } + + result = Result.INVALID_ROW; + break; + } + + case NEED_RECORD: { + int minimalRecordRowSize = HybridRowHeader.BYTES + RecordIOFormatter.RECORD_LAYOUT.size(); + if (buffer.Length < minimalRecordRowSize) { + need.set(minimalRecordRowSize); + consumed.set(buffer.Length - buffer.Length); + return Result.INSUFFICIENT_BUFFER; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Span span = b.Span.Slice(0, minimalRecordRowSize); + Span span = buffer.Span.Slice(0, minimalRecordRowSize); + RowBuffer row = new RowBuffer(span, HybridRowVersion.V1, SystemSchema.layoutResolver); + Reference tempReference_row3 = + new Reference(row); + RowReader reader = new RowReader(tempReference_row3); + row = tempReference_row3.get(); + Reference tempReference_reader3 = new Reference(reader); + Out tempOut_record = new Out(); + result = RecordSerializer.read(tempReference_reader3, tempOut_record); + this.record = tempOut_record.get(); + reader = tempReference_reader3.get(); + if (result != Result.SUCCESS) { + break; + } + + buffer = buffer.Slice(span.Length); + this.state = State.NEED_ROW; + // TODO: C# TO JAVA CONVERTER: There is no 'goto' in Java: + goto case State.NEED_ROW + } + + case NEED_ROW: { + if (buffer.Length < this.record.length()) { + need.set(this.record.length()); + consumed.set(buffer.Length - buffer.Length); + return Result.INSUFFICIENT_BUFFER; + } + + record.set(buffer.Slice(0, this.record.length())); + + // Validate that the record has not been corrupted. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint crc32 = Crc32.Update(0, record.Span); + int crc32 = Crc32.Update(0, record.get().Span); + if (crc32 != this.record.crc32()) { + result = Result.INVALID_ROW; + break; + } + + buffer = buffer.Slice(this.record.length()); + need.set(0); + this.state = State.NEED_HEADER; + consumed.set(buffer.Length - buffer.Length); + type.set(ProductionType.RECORD); + return Result.SUCCESS; + } + } + + this.state = State.ERROR; + need.set(0); + consumed.set(buffer.Length - buffer.Length); + return result; + } + + /** + * True if a valid segment has been parsed. + */ + public boolean haveSegment() { + return this.state.value() >= State.NEED_HEADER.value(); + } + + /** + * If a valid segment has been parsed then current active segment, otherwise undefined. + */ + public Segment segment() { + checkState(this.haveSegment()); + return this.segment; + } + + /** + * Describes the type of Hybrid Rows produced by the parser. + */ + public enum ProductionType { + /** + * No hybrid row was produced. The parser needs more data. + */ + NONE(0), + + /** + * A new segment row was produced. + */ + SEGMENT(1), + + /** + * A record in the current segment was produced. + */ + RECORD(2); + + public static final int BYTES = Integer.BYTES; + + private static Int2ObjectMap mappings; + private int value; + + ProductionType(int value) { + this.value = value; + mappings().put(value, this); + } + + public int value() { + return this.value; + } + + public static ProductionType from(int value) { + return mappings().get(value); + } + + private static Int2ObjectMap mappings() { + if (mappings == null) { + synchronized (ProductionType.class) { + if (mappings == null) { + mappings = new Int2ObjectOpenHashMap<>(); + } + } + } + return mappings; + } + } + + /** + * The states for the internal state machine. + * Note: numerical ordering of these states matters. + */ + private enum State { + STATE( + (byte) 0, "Start: no buffers have yet been provided to the parser"), + ERROR( + (byte) 1, "Unrecoverable parse error encountered"), + NEED_SEGMENT_LENGTH( + (byte) 2, "Parsing segment header length"), + NEED_SEGMENT( + (byte) 3, "Parsing segment header"), + NEED_HEADER( + (byte) 4, "Parsing HybridRow header"), + NEED_RECORD( + (byte) 5, "Parsing record header"), + NEED_ROW( + (byte) 6, "Parsing row body"); + + public static final int BYTES = Byte.SIZE; + + private static Byte2ObjectMap mappings; + private final String description; + private final byte value; + + State(byte value, String description) { + this.description = description; + this.value = value; + mappings().put(value, this); + } + + public String description() { + return this.description; + } + + public byte value() { + return this.value; + } + + public static State from(byte value) { + return mappings().get(value); + } + + private static Byte2ObjectMap mappings() { + if (mappings == null) { + synchronized (State.class) { + if (mappings == null) { + mappings = new Byte2ObjectOpenHashMap<>(); + } + } + } + return mappings; + } + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOStream.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOStream.java new file mode 100644 index 0000000..43f2868 --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordIOStream.java @@ -0,0 +1,368 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.recordio; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.MemorySpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; + +import java.io.InputStream; +import java.io.OutputStream; + +public final class RecordIOStream { +/** + * A function that produces RecordIO record bodies. + *

+ * Record bodies are returned as memory blocks. It is expected that each block is a + * HybridRow, but any binary data is allowed. + * + * @param index The 0-based index of the record within the segment to be produced. + * @return A tuple with: Success if the body was produced without error, the error code otherwise. + * And, the byte sequence of the record body's row buffer. + */ + public delegate ValueTask + + ProduceFuncAsync(long index);<(Result,ReadOnlyMemory)> + + /** + * Reads an entire RecordIO stream. + * + * @param stm The stream to read from. + * @param visitRecord A (required) delegate that is called once for each record. + *

+ * is passed a {@link Memory{T}} of the byte sequence + * of the + * record body's row buffer. + *

+ *

If returns an error then the sequence is aborted.

+ * @param visitSegment An (optional) delegate that is called once for each segment header. + *

+ * If is not provided then segment headers are parsed but + * skipped + * over. + *

+ *

+ * is passed a {@link Memory{T}} of the byte sequence of + * the segment header's row buffer. + *

+ *

If returns an error then the sequence is aborted.

+ * @param resizer Optional memory resizer. + * @return Success if the stream is parsed without error, the error code otherwise. + */ + + public static Task ReadRecordIOAsync(Stream stm, Func, Result> visitRecord, + Func, Result> visitSegment) { + return ReadRecordIOAsync(stm, visitRecord, visitSegment, null); + } + + public static Task ReadRecordIOAsync(Stream stm, Func, Result> visitRecord) { + return ReadRecordIOAsync(stm, visitRecord, null, null); + } + + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: public static async Task ReadRecordIOAsync(this Stream stm, Func, Result> + // visitRecord, Func, Result> visitSegment = default, MemorySpanResizer resizer = default) + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public static Task ReadRecordIOAsync(InputStream stm, + tangible.Func1Param, Result> visitRecord, + tangible.Func1Param, Result> visitSegment, + MemorySpanResizer resizer) { + checkArgument(stm != null); + checkArgument(visitRecord != null); + + // Create a reusable, resizable buffer if the caller didn't provide one. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: resizer = resizer != null ? resizer : new MemorySpanResizer(); + resizer = resizer != null ? resizer : new MemorySpanResizer(); + + RecordIOParser parser = null; + int need = 0; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Memory active = resizer.Memory; + Memory active = resizer.getMemory(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Memory avail = default; + Memory avail = null; + while (true) { + checkState(avail.Length < active.Length); + checkState(active.Length > 0); + checkState(active.Length >= need); + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + int read = await stm.ReadAsync(active.Slice(avail.Length)); + if (read == 0) { + break; + } + + avail = active.Slice(0, avail.Length + read); + + // If there isn't enough data to move the parser forward then just read again. + if (avail.Length < need) { + continue; + } + + // Process the available data until no more forward progress is possible. + while (avail.Length > 0) { + // Loop around processing available data until we don't have anymore + RecordIOParser.ProductionType prodType; + Out tempOut_prodType = new Out(); + Memory record; + Out> tempOut_record = new Out>(); + Out tempOut_need = new Out(); + int consumed; + Out tempOut_consumed = new Out(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Result r = parser.Process(avail, out RecordIOParser.ProductionType prodType, out + // Memory record, out need, out int consumed); + Result r = parser.process(avail, tempOut_prodType, tempOut_record, tempOut_need, tempOut_consumed); + consumed = tempOut_consumed.get(); + need = tempOut_need.get(); + record = tempOut_record.get(); + prodType = tempOut_prodType.get(); + + if ((r != Result.SUCCESS) && (r != Result.INSUFFICIENT_BUFFER)) { + return r; + } + + active = active.Slice(consumed); + avail = avail.Slice(consumed); + if (avail.IsEmpty) { + active = resizer.getMemory(); + } + + // If there wasn't enough data to move the parser forward then get more data. + if (r == Result.INSUFFICIENT_BUFFER) { + if (need > active.Length) { + resizer.Resize(need, avail.Span); + active = resizer.getMemory(); + avail = resizer.getMemory().Slice(0, avail.Length); + } + + break; + } + + // Validate the Segment + if (prodType == RecordIOParser.ProductionType.SEGMENT) { + checkState(!record.IsEmpty); + r = visitSegment == null ? null : visitSegment.invoke(record) != null ? + visitSegment.invoke(record) : Result.SUCCESS; + if (r != Result.SUCCESS) { + return r; + } + } + + // Consume the record. + if (prodType == RecordIOParser.ProductionType.RECORD) { + checkState(!record.IsEmpty); + + r = visitRecord.invoke(record); + if (r != Result.SUCCESS) { + return r; + } + } + } + } + + // Make sure we processed all of the available data. + checkState(avail.Length == 0); + return Result.SUCCESS; + } + + /** + * Writes a RecordIO segment into a stream. + * + * @param stm The stream to write to. + * @param segment The segment header to write. + * @param produce A function to produces the record bodies for the segment. + *

+ * The function is called until either an error is encountered or it + * produces an empty body. An empty body terminates the segment. + *

+ *

If returns an error then the sequence is aborted.

+ * @param resizer Optional memory resizer for RecordIO metadata row buffers. + *

+ * Note: This should NOT be the same resizer used to process any rows as both + * blocks of memory are used concurrently. + *

+ * @return Success if the stream is written without error, the error code otherwise. + */ + + public static Task WriteRecordIOAsync(Stream stm, Segment segment, ProduceFunc produce) { + return WriteRecordIOAsync(stm, segment, produce, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public static Task WriteRecordIOAsync(this Stream stm, Segment segment, ProduceFunc + // produce, MemorySpanResizer resizer = default) + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.Stream is input or + // output: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public static Task WriteRecordIOAsync(Stream stm, Segment segment, ProduceFunc produce, + MemorySpanResizer resizer) { + return RecordIOStream.WriteRecordIOAsync(stm, + segment.clone(), index -> + { + ReadOnlyMemory buffer; + Out> tempOut_buffer = new Out>(); + buffer = tempOut_buffer.get(); + return new ValueTask<(Result, ReadOnlyMemory < Byte >) > ((r,buffer)) + }, resizer); + } + + /** + * Writes a RecordIO segment into a stream. + * + * @param stm The stream to write to. + * @param segment The segment header to write. + * @param produce A function to produces the record bodies for the segment. + *

+ * The function is called until either an error is encountered or it + * produces an empty body. An empty body terminates the segment. + *

+ *

If returns an error then the sequence is aborted.

+ * @param resizer Optional memory resizer for RecordIO metadata row buffers. + *

+ * Note: This should NOT be the same resizer used to process any rows as both + * blocks of memory are used concurrently. + *

+ * @return Success if the stream is written without error, the error code otherwise. + */ + + public static Task WriteRecordIOAsync(Stream stm, Segment segment, ProduceFuncAsync produce) { + return WriteRecordIOAsync(stm, segment, produce, null); + } + + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: public static async Task WriteRecordIOAsync(this Stream stm, Segment segment, + // ProduceFuncAsync produce, MemorySpanResizer resizer = default) + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public static Task WriteRecordIOAsync(OutputStream stm, Segment segment, ProduceFuncAsync produce, + MemorySpanResizer resizer) { + // Create a reusable, resizable buffer if the caller didn't provide one. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: resizer = resizer != null ? resizer : new MemorySpanResizer(); + resizer = resizer != null ? resizer : new MemorySpanResizer(); + + // Write a RecordIO stream. + Memory metadata; + Out> tempOut_metadata = new Out>(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Result r = RecordIOStream.FormatSegment(segment, resizer, out Memory metadata); + Result r = RecordIOStream.FormatSegment(segment.clone(), resizer, tempOut_metadata); + metadata = tempOut_metadata.get(); + if (r != Result.SUCCESS) { + return r; + } + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await stm.WriteAsync(metadata); + + long index = 0; + while (true) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ReadOnlyMemory body; + ReadOnlyMemory body; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# deconstruction assignments: + (r, body) =await produce (index++); + if (r != Result.SUCCESS) { + return r; + } + + if (body.IsEmpty) { + break; + } + + Out> tempOut_metadata2 = new Out>(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: r = RecordIOStream.FormatRow(body, resizer, out metadata); + r = RecordIOStream.FormatRow(body, resizer, tempOut_metadata2); + metadata = tempOut_metadata2.get(); + if (r != Result.SUCCESS) { + return r; + } + + // Metadata and Body memory blocks should not overlap since they are both in + // play at the same time. If they do this usually means that the same resizer + // was incorrectly used for both. Check the resizer parameter passed to + // WriteRecordIOAsync for metadata. + checkState(!metadata.Span.Overlaps(body.Span)); + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await stm.WriteAsync(metadata); + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await stm.WriteAsync(body); + } + + return Result.SUCCESS; + } + + /** + * Compute and format a record header for the given record body. + * + * @param body The body whose record header should be formatted. + * @param resizer The resizer to use in allocating a buffer for the record header. + * @param block The byte sequence of the written row buffer. + * @return Success if the write completes without error, the error code otherwise. + */ + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static Result FormatRow(ReadOnlyMemory body, MemorySpanResizer resizer, out Memory block) + private static Result FormatRow(ReadOnlyMemory body, MemorySpanResizer resizer, Out> block) { + RowBuffer row; + Out tempOut_row = new Out(); + Result r = RecordIOFormatter.FormatRecord(body, tempOut_row, resizer); + row = tempOut_row.get(); + if (r != Result.SUCCESS) { + block.setAndGet(null); + return r; + } + + block.setAndGet(resizer.getMemory().Slice(0, row.Length)); + return Result.SUCCESS; + } + + /** + * Format a segment. + * + * @param segment The segment to format. + * @param resizer The resizer to use in allocating a buffer for the segment. + * @param block The byte sequence of the written row buffer. + * @return Success if the write completes without error, the error code otherwise. + */ + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static Result FormatSegment(Segment segment, MemorySpanResizer resizer, out + // Memory block) + private static Result FormatSegment(Segment segment, MemorySpanResizer resizer, + Out> block) { + RowBuffer row; + Out tempOut_row = + new Out(); + Result r = RecordIOFormatter.FormatSegment(segment.clone(), tempOut_row, resizer); + row = tempOut_row.get(); + if (r != Result.SUCCESS) { + block.setAndGet(null); + return r; + } + + block.setAndGet(resizer.getMemory().Slice(0, row.Length)); + return Result.SUCCESS; + } + + /** + * A function that produces RecordIO record bodies. + *

+ * Record bodies are returned as memory blocks. It is expected that each block is a + * HybridRow, but any binary data is allowed. + * + * @param index The 0-based index of the record within the segment to be produced. + * @param buffer The byte sequence of the record body's row buffer. + * @return Success if the body was produced without error, the error code otherwise. + */ + @FunctionalInterface + public interface ProduceFunc { + Result invoke(long index, Out> buffer); + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordSerializer.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordSerializer.java new file mode 100644 index 0000000..bdb05d4 --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/RecordSerializer.java @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.recordio; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.UtfAnyString; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkState; + +public final class RecordSerializer { + + @Nonnull + public static Result read(RowReader reader, Out record) { + + Out value = new Out<>(); + record.set(Record.empty()); + + while (reader.read()) { + + String path = reader.path().toUtf16(); + checkState(path != null); + Result result; + + // TODO: use Path tokens here + + switch (path) { + + case "length": + + result = reader.readInt32(value); + record.get().length(value.get()); + + if (result != Result.SUCCESS) { + return result; + } + break; + + case "crc32": + + result = reader.readInt32(value); + record.get().crc32(value.get()); + + if (result != Result.SUCCESS) { + return result; + } + break; + } + } + + return Result.SUCCESS; + } + + @Nonnull + public static Result write(RowWriter writer, TypeArgument typeArg, Record record) { + Result result = writer.writeInt32(new UtfAnyString("length"), record.length()); + if (result != Result.SUCCESS) { + return result; + } + return writer.writeUInt32(new UtfAnyString("crc32"), record.crc32()); + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/SegmentSerializer.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/SegmentSerializer.java new file mode 100644 index 0000000..78db48b --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/recordio/SegmentSerializer.java @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.recordio; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.core.UtfAnyString; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; +import com.azure.data.cosmos.serialization.hybridrow.io.Segment; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import io.netty.buffer.ByteBuf; + +import java.util.Objects; + +import static com.google.common.base.Preconditions.checkState; + +public final class SegmentSerializer { + + private static final UtfAnyString COMMENT = new UtfAnyString("comment"); + private static final UtfAnyString LENGTH = new UtfAnyString("length"); + private static final UtfAnyString SDL = new UtfAnyString("sdl"); + + public static Result read(ByteBuf buffer, LayoutResolver resolver, Out segment) { + RowReader reader = new RowReader(new RowBuffer(buffer, HybridRowVersion.V1, resolver)); + return SegmentSerializer.read(reader, segment); + } + + public static Result read(RowReader reader, Out segment) { + + segment.set(new Segment(null, null)); + + final Out comment = new Out<>(); + final Out length = new Out<>(); + final Out sdl = new Out<>(); + + while (reader.read()) { + + // TODO: Use Path tokens here. + + switch (Objects.requireNonNull(reader.path().toUtf16())) { + + case "length": { + + Result result = reader.readInt32(length); + segment.get().length(length.get()); + + if (result != Result.SUCCESS) { + return result; + } + + if (reader.length() < segment.get().length()) { + // RowBuffer isn't big enough to contain the rest of the header so just return the length + return Result.SUCCESS; + } + + break; + } + case "comment": { + + Result result = reader.readString(comment); + segment.get().comment(comment.get()); + + if (result != Result.SUCCESS) { + return result; + } + + break; + } + case "sdl": { + + Result result = reader.readString(sdl); + segment.get().sdl(sdl.get()); + + if (result != Result.SUCCESS) { + return result; + } + + break; + } + } + } + + return Result.SUCCESS; + } + + public static Result write(RowWriter writer, TypeArgument typeArg, Segment segment) { + + Result result; + + if (segment.comment() != null) { + result = writer.writeString(COMMENT, segment.comment()); + if (result != Result.SUCCESS) { + return result; + } + } + + if (segment.sdl() != null) { + result = writer.writeString(SDL, segment.sdl()); + if (result != Result.SUCCESS) { + return result; + } + } + + // Defer writing the length until all other fields of the segment header are written. + // The length is then computed based on the current size of the underlying RowBuffer. + // Because the length field is itself fixed, writing the length can never change the length. + + int length = writer.length(); + result = writer.writeInt32(LENGTH, length); + if (result != Result.SUCCESS) { + return result; + } + + checkState(length == writer.length()); + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertySchemaConverter.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertySchemaConverter.java new file mode 100644 index 0000000..4d92ef9 --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertySchemaConverter.java @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import Newtonsoft.Json.*; +import Newtonsoft.Json.Converters.*; +import Newtonsoft.Json.Linq.*; + +/** + * Helper class for parsing the polymorphic {@link PropertyType} subclasses from JSON. + */ +public class PropertySchemaConverter extends JsonConverter { + @Override + public boolean getCanWrite() { + return false; + } + + @Override + public boolean CanConvert(java.lang.Class objectType) { + return objectType.isAssignableFrom(PropertyType.class); + } + + @Override + public Object ReadJson(JsonReader reader, java.lang.Class objectType, Object existingValue, + JsonSerializer serializer) { + PropertyType p; + if (reader.TokenType != JsonToken.StartObject) { + throw new JsonSerializationException(); + } + + JObject propSchema = JObject.Load(reader); + TypeKind propType; + + JToken value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + if (!propSchema.TryGetValue("type", out value)) { + throw new JsonSerializationException("Required \"type\" property missing."); + } + + try (JsonReader typeReader = value.CreateReader()) { + typeReader.Read(); // Move to the start token + propType = TypeKind.forValue((new StringEnumConverter(true)).ReadJson(typeReader, TypeKind.class, null, + serializer)); + } + + switch (propType) { + case Array: + p = new ArrayPropertyType(); + break; + case SET: + p = new SetPropertyType(); + break; + case MAP: + p = new MapPropertyType(); + break; + case Object: + p = new ObjectPropertyType(); + break; + case Tuple: + p = new TuplePropertyType(); + break; + case TAGGED: + p = new TaggedPropertyType(); + break; + case Schema: + p = new UdtPropertyType(); + break; + default: + p = new PrimitivePropertyType(); + break; + } + + serializer.Populate(propSchema.CreateReader(), p); + return p; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [ExcludeFromCodeCoverage] public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + @Override + public void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer) { + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictBooleanConverter.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictBooleanConverter.java new file mode 100644 index 0000000..596536b --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictBooleanConverter.java @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import Newtonsoft.Json.*; + +public class StrictBooleanConverter extends JsonConverter { + @Override + public boolean getCanWrite() { + return false; + } + + @Override + public boolean CanConvert(java.lang.Class objectType) { + return objectType == Boolean.class; + } + + @Override + public Object ReadJson(JsonReader reader, java.lang.Class objectType, Object existingValue, + JsonSerializer serializer) { + switch (reader.TokenType) { + case JsonToken.Boolean: + return serializer.Deserialize(reader, objectType); + default: + throw new JsonSerializationException(String.format("Token \"%1$s\" of type %2$s was not a JSON bool", + reader.Value, reader.TokenType)); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [ExcludeFromCodeCoverage] public override void WriteJson(JsonWriter writer, object value, + // JsonSerializer serializer) + @Override + public void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer) { + } +} \ No newline at end of file diff --git a/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictIntegerConverter.java b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictIntegerConverter.java new file mode 100644 index 0000000..7626519 --- /dev/null +++ b/java/exclusions/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StrictIntegerConverter.java @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import Newtonsoft.Json.*; + +import java.math.BigInteger; + +public class StrictIntegerConverter extends JsonConverter { + @Override + public boolean getCanWrite() { + return false; + } + + @Override + public boolean CanConvert(java.lang.Class objectType) { + return StrictIntegerConverter.IsIntegerType(objectType); + } + + @Override + public Object ReadJson(JsonReader reader, java.lang.Class objectType, Object existingValue, + JsonSerializer serializer) { + switch (reader.TokenType) { + case JsonToken.Integer: + return serializer.Deserialize(reader, objectType); + default: + throw new JsonSerializationException(String.format("Token \"%1$s\" of type %2$s was not a JSON " + + "integer", reader.Value, reader.TokenType)); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [ExcludeFromCodeCoverage] public override void WriteJson(JsonWriter writer, object value, + // JsonSerializer serializer) + @Override + public void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer) { + } + + private static boolean IsIntegerType(java.lang.Class type) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: if (type == typeof(long) || type == typeof(ulong) || type == typeof(int) || type == typeof + // (uint) || type == typeof(short) || type == typeof(ushort) || type == typeof(byte) || type == typeof(sbyte) + // || type == typeof(BigInteger)) + return type == Long.class || type == Long.class || type == Integer.class || type == Integer.class || type == Short.class || type == Short.class || type == Byte.class || type == Byte.class || type == BigInteger.class; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BenchmarkSuiteBase.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BenchmarkSuiteBase.java new file mode 100644 index 0000000..e7b841d --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BenchmarkSuiteBase.java @@ -0,0 +1,140 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.MemorySpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolverNamespace; +import com.azure.data.cosmos.serialization.hybridrow.layouts.SystemSchema; +import com.azure.data.cosmos.serialization.hybridrow.recordio.RecordIOStream; +import com.azure.data.cosmos.serialization.hybridrow.io.Segment; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.stream.Stream; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +public class BenchmarkSuiteBase { + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + //ORIGINAL LINE: private protected const int InitialCapacity = 2 * 1024 * 1024; + protected static final int InitialCapacity = 2 * 1024 * 1024; + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + //ORIGINAL LINE: private protected LayoutResolverNamespace DefaultResolver = (LayoutResolverNamespace) + // SystemSchema.LayoutResolver; + protected LayoutResolverNamespace DefaultResolver = (LayoutResolverNamespace)SystemSchema.layoutResolver; + + // TODO: C# TO JAVA CONVERTER: Methods returning tuples are not converted by C# to Java Converter: + // private protected async Task<(List>, LayoutResolverNamespace)> + // LoadExpectedAsync(string expectedFile) + // { + // LayoutResolverNamespace resolver = this.DefaultResolver; + // List> expected = new List>(); + // using (Stream stm = new FileStream(expectedFile, FileMode.Open)) + // { + // // Read a RecordIO stream. + // MemorySpanResizer resizer = new MemorySpanResizer(BenchmarkSuiteBase.InitialCapacity); + // Result r = await stm.ReadRecordIOAsync(record => + // { + // r = BenchmarkSuiteBase.LoadOneRow(record, resolver, out Dictionary + // rowValue); + // ResultAssert.IsSuccess(r); + // expected.Add(rowValue); + // return Result.Success; + // } + // , segment => + // { + // r = SegmentSerializer.Read(segment.Span, SystemSchema.LayoutResolver, out Segment s); + // ResultAssert.IsSuccess(r); + // Assert.IsNotNull(s.SDL); + // resolver = new LayoutResolverNamespace(Namespace.Parse(s.SDL), resolver); + // return Result.Success; + // } + // , resizer); + // + // ResultAssert.IsSuccess(r); + // } + // + // return (expected, resolver); + // } + + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + //ORIGINAL LINE: private protected static Result LoadOneRow(Memory buffer, LayoutResolver resolver, out + // Dictionary rowValue) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + protected static Result LoadOneRow(Memory buffer, LayoutResolver resolver, + Out> rowValue) { + RowBuffer row = new RowBuffer(buffer.Span, HybridRowVersion.V1, resolver); + Reference tempReference_row = + new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + Reference tempReference_reader = + new Reference(reader); + Result tempVar = DiagnosticConverter.ReaderToDynamic(tempReference_reader, rowValue); + reader = tempReference_reader.get(); + return tempVar; + } + + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: private protected static async Task WriteAllRowsAsync(string file, string sdl, LayoutResolver + // resolver, Layout layout, List> rows) + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + protected static Task WriteAllRowsAsync(String file, String sdl, LayoutResolver resolver, Layout layout, + ArrayList> rows) { + try (Stream stm = new FileStream(file, FileMode.Truncate)) { + // Create a reusable, resizable buffer. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MemorySpanResizer resizer = new MemorySpanResizer(BenchmarkSuiteBase + // .InitialCapacity); + MemorySpanResizer resizer = new MemorySpanResizer(BenchmarkSuiteBase.InitialCapacity); + + // Write a RecordIO stream. + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'out' keyword - these are + // not converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Result r = await stm.WriteRecordIOAsync(new Segment("HybridRow.Tests.Perf Expected + // Results", sdl), (long index, out ReadOnlyMemory body) => + Result r = await RecordIOStream.WriteRecordIOAsync(stm, + new Segment("HybridRow.Tests.Perf Expected Results", sdl), (long index, out ReadOnlyMemorybody) -> + { + body = null; + if (index >= rows.size()) { + return Result.SUCCESS; + } + + StreamingRowGenerator writer = new StreamingRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, + resolver, resizer); + + Result r2 = writer.WriteBuffer(rows.get((int)index)); + if (r2 != Result.SUCCESS) { + return r2; + } + + body = resizer.getMemory().Slice(0, writer.getLength()); + return Result.SUCCESS; + }); + + ResultAssert.IsSuccess(r); + } + } + + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + //ORIGINAL LINE: private protected static class ResultAssert + protected static class ResultAssert { + public static void IsSuccess(Result actual) { + assert actual == Result.SUCCESS || Result.SUCCESS == actual; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonJsonModelRowGenerator.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonJsonModelRowGenerator.java new file mode 100644 index 0000000..73d36f1 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonJsonModelRowGenerator.java @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import org.bson.BsonWriter; +import org.bson.BsonBinaryWriter +import java.io.Closeable; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +import static com.google.common.base.Strings.lenientFormat; + +public final class BsonJsonModelRowGenerator implements Closeable { + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.MemoryStream is + // input or output: + private MemoryStream stream; + private BsonWriter writer; + + public BsonJsonModelRowGenerator(int capacity) { + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.MemoryStream + // is input or output: + this.stream = new MemoryStream(capacity); + this.writer = new BsonBinaryWriter(this.stream); + } + + public int getLength() { + return (int)this.stream.Position; + } + + public void Reset() { + this.stream.SetLength(0); + this.stream.Position = 0; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ToArray() + public byte[] ToArray() { + return this.stream.ToArray(); + } + + public void WriteBuffer(HashMap dict) { + this.writer.writeStartDocument(); + for ((Utf8String propPath,Object propValue) : dict) + { + this.JsonModelSwitch(propPath, propValue); + } + + this.writer.writeEndDocument(); + } + + public void close() throws IOException { + this.writer.Dispose(); + this.stream.Dispose(); + } + + private void JsonModelSwitch(Utf8String path, Object value) { + if (path != null) { + this.writer.writeName(path.toString()); + } + + switch (value) { + case null: + this.writer.writeNull(); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case bool x: + case + boolean x: + this.writer.writeBoolean(x); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case long x: + case + long x: + this.writer.writeInt64(x); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case double x: + case + double x: + this.writer.writeDouble(x); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case string x: + case String + x: + this.writer.writeString(x); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case Utf8String x: + case Utf8String + x: + this.writer.writeString(x.toString()); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case byte[] x: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + case + byte[] x: + this.writer.writeBytes(x); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case Dictionary x: + case HashMap < Utf8String, Object > x: + this.writer.writeStartDocument(); + for ((Utf8String propPath,Object propValue) :x) + { + this.JsonModelSwitch(propPath, propValue); + } + + this.writer.writeEndDocument(); + return; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case List x: + case ArrayList < Object > x: + this.writer.writeStartArray(); + for (Object item : x) { + this.JsonModelSwitch(null, item); + } + + this.writer.writeEndArray(); + + return; + default: + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s", value.getClass().getSimpleName())); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonReaderExtensions.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonReaderExtensions.java new file mode 100644 index 0000000..07332cf --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonReaderExtensions.java @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import MongoDB.Bson.*; +import MongoDB.Bson.IO.*; + +public final class BsonReaderExtensions { + public static void VisitBsonDocument(BsonReader bsonReader) { + bsonReader.ReadStartDocument(); + BsonType type; + while ((type = bsonReader.ReadBsonType()) != BsonType.EndOfDocument) { + String path = bsonReader.ReadName(); + switch (type) { + case BsonType.Array: + BsonReaderExtensions.VisitBsonArray(bsonReader); + break; + + case BsonType.Document: + BsonReaderExtensions.VisitBsonDocument(bsonReader); + break; + + default: + bsonReader.SkipValue(); + break; + } + } + + bsonReader.ReadEndDocument(); + } + + private static void VisitBsonArray(BsonReader bsonReader) { + bsonReader.ReadStartArray(); + BsonType type; + while ((type = bsonReader.ReadBsonType()) != BsonType.EndOfDocument) { + switch (type) { + case BsonType.Array: + BsonReaderExtensions.VisitBsonArray(bsonReader); + break; + + case BsonType.Document: + BsonReaderExtensions.VisitBsonDocument(bsonReader); + break; + + default: + bsonReader.SkipValue(); + break; + } + } + + bsonReader.ReadEndArray(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonRowGenerator.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonRowGenerator.java new file mode 100644 index 0000000..0092278 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/BsonRowGenerator.java @@ -0,0 +1,314 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import MongoDB.Bson.*; +import MongoDB.Bson.IO.*; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import org.bson.BsonBinaryWriter; +import org.bson.BsonWriter; + +import java.io.Closeable; +import java.io.IOException; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.UUID; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.lenientFormat; + +public final class BsonRowGenerator implements Closeable { + private Layout layout; + private LayoutResolver resolver; + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.MemoryStream is + // input or output: + private MemoryStream stream; + private BsonWriter writer; + + public BsonRowGenerator(int capacity, Layout layout, LayoutResolver resolver) { + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.MemoryStream + // is input or output: + this.stream = new MemoryStream(capacity); + this.writer = new BsonBinaryWriter(this.stream); + this.layout = layout; + this.resolver = resolver; + } + + public int getLength() { + return (int)this.stream.Position; + } + + public void Reset() { + this.stream.SetLength(0); + this.stream.Position = 0; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ToArray() + public byte[] ToArray() { + return this.stream.ToArray(); + } + + public void WriteBuffer(HashMap dict) { + this.writer.writeStartDocument(); + for (LayoutColumn c : this.layout.columns()) { + this.LayoutCodeSwitch(c.path(), c.typeArg().clone(), dict.get(c.path())); + } + + this.writer.writeEndDocument(); + } + + public void close() throws IOException { + this.writer.Dispose(); + this.stream.Dispose(); + } + + private void DispatchArray(TypeArgument typeArg, Object value) { + + checkArgument(typeArg.typeArgs().count() == 1); + this.writer.writeStartArray(); + + for (Object item : (ArrayList)value) { + this.LayoutCodeSwitch(null, typeArg.typeArgs().get(0).clone(), item); + } + + this.writer.writeEndArray(); + } + + private void DispatchMap(TypeArgument typeArg, Object value) { + checkArgument(typeArg.typeArgs().count() == 2); + + this.writer.writeStartArray(); + for (Object item : (ArrayList)value) { + this.DispatchTuple(typeArg.clone(), item); + } + + this.writer.writeEndArray(); + } + + private void DispatchNullable(TypeArgument typeArg, Object value) { + checkArgument(typeArg.typeArgs().count() == 1); + + if (value != null) { + this.LayoutCodeSwitch(null, typeArg.typeArgs().get(0).clone(), value); + } else { + this.writer.writeNull(); + } + } + + private void DispatchObject(TypeArgument typeArg, Object value) { + this.writer.writeStartDocument(); + // TODO: support properties in an object scope. + this.writer.writeEndDocument(); + } + + private void DispatchSet(TypeArgument typeArg, Object value) { + checkArgument(typeArg.typeArgs().count() == 1); + + this.writer.WriteStartArray(); + for (Object item : (ArrayList)value) { + this.LayoutCodeSwitch(null, typeArg.typeArgs().get(0).clone(), item); + } + + this.writer.WriteEndArray(); + } + + private void DispatchTuple(TypeArgument typeArg, Object value) { + checkArgument(typeArg.typeArgs().count() >= 2); + ArrayList items = (ArrayList)value; + checkArgument(items.size() == typeArg.typeArgs().count()); + + this.writer.WriteStartArray(); + for (int i = 0; i < items.size(); i++) { + Object item = items.get(i); + this.LayoutCodeSwitch(null, typeArg.typeArgs().get(i).clone(), item); + } + + this.writer.WriteEndArray(); + } + + private void DispatchUDT(TypeArgument typeArg, Object value) { + this.writer.WriteStartDocument(); + + HashMap dict = (HashMap)value; + Layout udt = this.resolver.resolve(typeArg.typeArgs().schemaId().clone()); + for (LayoutColumn c : udt.columns()) { + this.LayoutCodeSwitch(c.path(), c.typeArg().clone(), dict.get(c.path())); + } + + this.writer.WriteEndDocument(); + } + + private void LayoutCodeSwitch(UtfAnyString path, TypeArgument typeArg, Object value) { + if (!path.IsNull) { + this.writer.WriteName(path); + } + + switch (typeArg.type().LayoutCode) { + case Null: + this.writer.WriteNull(); + return; + + case Boolean: + this.writer.WriteBoolean(value == null ? false : (Boolean)value); + return; + + case Int8: + this.writer.WriteInt32(value == null ? 0 : (byte)value); + return; + + case Int16: + this.writer.WriteInt32(value == null ? 0 : (Short)value); + return; + + case Int32: + this.writer.WriteInt32(value == null ? 0 : (Integer)value); + return; + + case Int64: + this.writer.WriteInt64(value == null ? 0 : (Long)value); + return; + + case UInt8: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.writer.WriteInt32(value == null ? default(byte) : (byte)value); + this.writer.WriteInt32(value == null ? 0 : (Byte)value); + return; + + case UInt16: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.writer.WriteInt32(value == null ? default(ushort) : (ushort)value); + this.writer.WriteInt32(value == null ? 0 : (short)value); + return; + + case UInt32: + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.writer.WriteInt32(value == null ? default(int) : unchecked((int)(uint)value)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + this.writer.WriteInt32(value == null ? 0 : (int)(int)value); + return; + + case UInt64: + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.writer.WriteInt64(value == null ? default(long) : unchecked((long)(ulong)value)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + this.writer.WriteInt64(value == null ? 0 : (long)(long)value); + return; + + case VarInt: + this.writer.WriteInt64(value == null ? 0 : (Long)value); + return; + + case VarUInt: + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.writer.WriteInt64(value == null ? default(long) : unchecked((long)(ulong)value)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + this.writer.WriteInt64(value == null ? 0 : (long)(long)value); + return; + + case Float32: + this.writer.WriteDouble(value == null ? 0 : (Float)value); + return; + + case Float64: + this.writer.WriteDouble(value == null ? 0 : (Double)value); + return; + + case Float128: + Decimal128 d128 = null; + if (value != null) { + Float128 f128 = (Float128)value; + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: d128 = unchecked(Decimal128.FromIEEEBits((ulong)f128.High, (ulong)f128.Low)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + d128 = Decimal128.FromIEEEBits((long) f128.high(), (long) f128.low()); + } + + this.writer.WriteDecimal128(d128); + return; + + case Decimal: + this.writer.WriteDecimal128(value == null ? null : new Decimal128((BigDecimal)value)); + return; + + case DateTime: + this.writer.WriteDateTime(value == null ? 0 : ((LocalDateTime)value).getTime()); + return; + + case UnixDateTime: + this.writer.WriteDateTime(value == null ? 0 : ((UnixDateTime)value).getMilliseconds()); + return; + + case Guid: + this.writer.WriteString(value == null ? "" : ((UUID)value).toString()); + return; + + case MongoDbObjectId: + this.writer.WriteObjectId(value == null ? null : new ObjectId(((MongoDbObjectId)value).ToByteArray())); + return; + + case Utf8: + this.writer.WriteString(value == null ? "" : ((Utf8String)value).toString()); + return; + + case Binary: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.writer.WriteBytes(value == null ? default(byte[]) : (byte[])value); + this.writer.WriteBytes(value == null ? null : (byte[])value); + return; + + case ObjectScope: + case ImmutableObjectScope: + this.DispatchObject(typeArg.clone(), value); + return; + + case TypedArrayScope: + case ImmutableTypedArrayScope: + this.DispatchArray(typeArg.clone(), value); + return; + + case TypedSetScope: + case ImmutableTypedSetScope: + this.DispatchSet(typeArg.clone(), value); + return; + + case TypedMapScope: + case ImmutableTypedMapScope: + this.DispatchMap(typeArg.clone(), value); + return; + + case TupleScope: + case ImmutableTupleScope: + case TypedTupleScope: + case ImmutableTypedTupleScope: + case TaggedScope: + case ImmutableTaggedScope: + case Tagged2Scope: + case ImmutableTagged2Scope: + this.DispatchTuple(typeArg.clone(), value); + return; + + case NullableScope: + case ImmutableNullableScope: + this.DispatchNullable(typeArg.clone(), value); + return; + + case Schema: + case ImmutableSchema: + this.DispatchUDT(typeArg.clone(), value); + return; + + default: + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s", typeArg.clone())); + return; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenMicroBenchmarkSuite.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenMicroBenchmarkSuite.java new file mode 100644 index 0000000..3cb402e --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenMicroBenchmarkSuite.java @@ -0,0 +1,311 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Result; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Tests involving generated (early bound) code compiled from schema based on a partial implementation + * of Cassandra Hotel Schema described here: https: //www.oreilly.com/ideas/cassandra-data-modeling . + *

+ * The tests here differ from {@link SchematizedMicroBenchmarkSuite} in that they rely on + * the schema being known at compile time instead of runtime. This allows code to be generated that + * directly addresses the schema structure instead of dynamically discovering schema structure at + * runtime. + *

+ */ +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public sealed class CodeGenMicroBenchmarkSuite : MicroBenchmarkSuiteBase +public final class CodeGenMicroBenchmarkSuite extends MicroBenchmarkSuiteBase { + private static final int GuestCount = 1000; + private static final int HotelCount = 10000; + private static final int RoomsCount = 10000; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task CodeGenGuestsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task CodeGenGuestsReadBenchmarkAsync() + public Task CodeGenGuestsReadBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.CodeGenReadBenchmark(resolver, "Guests", "Guests", + CodeGenMicroBenchmarkSuite.GuestCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task CodeGenGuestsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task CodeGenGuestsWriteBenchmarkAsync() + public Task CodeGenGuestsWriteBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.CodeGenWriteBenchmark(resolver, "Guests", "Guests", + CodeGenMicroBenchmarkSuite.GuestCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task CodeGenHotelReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task CodeGenHotelReadBenchmarkAsync() + public Task CodeGenHotelReadBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.CodeGenReadBenchmark(resolver, "Hotels", "Hotels", + CodeGenMicroBenchmarkSuite.HotelCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task CodeGenHotelWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task CodeGenHotelWriteBenchmarkAsync() + public Task CodeGenHotelWriteBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.CodeGenWriteBenchmark(resolver, "Hotels", "Hotels", + CodeGenMicroBenchmarkSuite.HotelCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task CodeGenRoomsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task CodeGenRoomsReadBenchmarkAsync() + public Task CodeGenRoomsReadBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.CodeGenReadBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", + CodeGenMicroBenchmarkSuite.RoomsCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task CodeGenRoomsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task CodeGenRoomsWriteBenchmarkAsync() + public Task CodeGenRoomsWriteBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.CodeGenWriteBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", + CodeGenMicroBenchmarkSuite.RoomsCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task ProtobufGuestsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task ProtobufGuestsReadBenchmarkAsync() + public Task ProtobufGuestsReadBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.ProtobufReadBenchmark("Guests", "Guests", CodeGenMicroBenchmarkSuite.GuestCount, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task ProtobufGuestsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task ProtobufGuestsWriteBenchmarkAsync() + public Task ProtobufGuestsWriteBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.ProtobufWriteBenchmark("Guests", "Guests", CodeGenMicroBenchmarkSuite.GuestCount, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task ProtobufHotelReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task ProtobufHotelReadBenchmarkAsync() + public Task ProtobufHotelReadBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.ProtobufReadBenchmark("Hotels", "Hotels", CodeGenMicroBenchmarkSuite.HotelCount, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task ProtobufHotelWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task ProtobufHotelWriteBenchmarkAsync() + public Task ProtobufHotelWriteBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.ProtobufWriteBenchmark("Hotels", "Hotels", CodeGenMicroBenchmarkSuite.HotelCount, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task ProtobufRoomsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task ProtobufRoomsReadBenchmarkAsync() + public Task ProtobufRoomsReadBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.ProtobufReadBenchmark("Available_Rooms_By_Hotel_Date", "Rooms", + CodeGenMicroBenchmarkSuite.RoomsCount, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task ProtobufRoomsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task ProtobufRoomsWriteBenchmarkAsync() + public Task ProtobufRoomsWriteBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + CodeGenMicroBenchmarkSuite.ProtobufWriteBenchmark("Available_Rooms_By_Hotel_Date", "Rooms", + CodeGenMicroBenchmarkSuite.RoomsCount, expected); + } + + private static void CodeGenReadBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName, + int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.CodeGenWriter = new CodeGenRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver); + + for (HashMap tableValue : expected) { + context.CodeGenWriter.Reset(); + + Result r = context.CodeGenWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(context.CodeGenWriter.ToArray()); + expectedSerialized.add(context.CodeGenWriter.ToArray()); + } + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("CodeGen", "Read", dataSetName, "HybridRowGen", innerLoopIterations, ref context, (ref BenchmarkContext ctx, byte[] tableValue) => + MicroBenchmarkSuiteBase.Benchmark("CodeGen", "Read", dataSetName, "HybridRowGen", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, byte[] tableValue) -> + { + Result r = ctx.CodeGenWriter.ReadBuffer(tableValue); + ResultAssert.IsSuccess(r); + }, (ref BenchmarkContext ctx, byte[] tableValue) -> tableValue.length, expectedSerialized); + context = tempReference_context.get(); + } + + private static void CodeGenWriteBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName + , int innerLoopIterations, ArrayList> expected) { + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.CodeGenWriter = new CodeGenRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver); + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + MicroBenchmarkSuiteBase.Benchmark("CodeGen", "Write", dataSetName, "HybridRowGen", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, HashMap tableValue) -> + { + ctx.CodeGenWriter.Reset(); + + Result r = ctx.CodeGenWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + }, (ref BenchmarkContext ctx, HashMap tableValue) -> ctx.CodeGenWriter.Length, expected); + context = tempReference_context.get(); + } + + private static void ProtobufReadBenchmark(String schemaName, String dataSetName, int innerLoopIterations, + ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + BenchmarkContext context = new BenchmarkContext(); + context.ProtobufWriter = new ProtobufRowGenerator(schemaName, BenchmarkSuiteBase.InitialCapacity); + + for (HashMap tableValue : expected) { + context.ProtobufWriter.WriteBuffer(tableValue); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(context.ProtobufWriter.ToArray()); + expectedSerialized.add(context.ProtobufWriter.ToArray()); + } + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("CodeGen", "Read", dataSetName, "Protobuf", + // innerLoopIterations, ref context, (ref BenchmarkContext ctx, byte[] tableValue) => ctx.ProtobufWriter + // .ReadBuffer(tableValue), (ref BenchmarkContext ctx, byte[] tableValue) => tableValue.Length, + // expectedSerialized); + MicroBenchmarkSuiteBase.Benchmark("CodeGen", "Read", dataSetName, "Protobuf", innerLoopIterations, + tempReference_context, + (ref BenchmarkContext ctx, byte[] tableValue) -> ctx.ProtobufWriter.ReadBuffer(tableValue), + (ref BenchmarkContext ctx, byte[] tableValue) -> tableValue.length, expectedSerialized); + context = tempReference_context.get(); + } + + private static void ProtobufWriteBenchmark(String schemaName, String dataSetName, int innerLoopIterations, + ArrayList> expected) { + BenchmarkContext context = new BenchmarkContext(); + context.ProtobufWriter = new ProtobufRowGenerator(schemaName, BenchmarkSuiteBase.InitialCapacity); + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + MicroBenchmarkSuiteBase.Benchmark("CodeGen", "Write", dataSetName, "Protobuf", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, HashMap tableValue) -> + { + ctx.ProtobufWriter.WriteBuffer(tableValue); + }, (ref BenchmarkContext ctx, HashMap tableValue) -> ctx.ProtobufWriter.Length, expected); + context = tempReference_context.get(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenRowGenerator.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenRowGenerator.java new file mode 100644 index 0000000..ff3590d --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/CodeGenRowGenerator.java @@ -0,0 +1,1169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.ISpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypeScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.StringToken; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.UUID; + +import static com.google.common.base.Strings.lenientFormat; + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal ref struct CodeGenRowGenerator +//C# TO JAVA CONVERTER WARNING: Java has no equivalent to the C# ref struct: +public final class CodeGenRowGenerator { + private HybridRowSerializer dispatcher; + private RowBuffer row = new RowBuffer(); + + + public CodeGenRowGenerator(int capacity, Layout layout, LayoutResolver resolver) { + this(capacity, layout, resolver, null); + } + + public CodeGenRowGenerator() { + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public CodeGenRowGenerator(int capacity, Layout layout, LayoutResolver resolver, + // ISpanResizer resizer = default) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public CodeGenRowGenerator(int capacity, Layout layout, LayoutResolver resolver, ISpanResizer resizer) { + this.row = new RowBuffer(capacity, resizer); + this.row.initLayout(HybridRowVersion.V1, layout, resolver); + + switch (layout.name()) { + case "Hotels": + this.dispatcher = new HotelsHybridRowSerializer(layout, resolver); + break; + + case "Guests": + this.dispatcher = new GuestsHybridRowSerializer(layout, resolver); + break; + + case "Available_Rooms_By_Hotel_Date": + this.dispatcher = new RoomsHybridRowSerializer(layout, resolver); + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown schema will be ignored: %s", layout.name())); + this.dispatcher = null; + break; + } + } + + public int getLength() { + return this.row.length(); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public Result ReadBuffer(byte[] buffer) + public Result ReadBuffer(byte[] buffer) { + this.row = new RowBuffer(buffer.AsSpan(), HybridRowVersion.V1, this.row.resolver()); + Reference tempReference_row = + new Reference(this.row); + RowCursor root = RowCursor.create(tempReference_row); + this.row = tempReference_row.get(); + Reference tempReference_row2 = + new Reference(this.row); + Reference tempReference_root = + new Reference(root); + Result tempVar = this.dispatcher.ReadBuffer(tempReference_row2, tempReference_root); + root = tempReference_root.get(); + this.row = tempReference_row2.get(); + return tempVar; + } + + public void Reset() { + Layout layout = this.row.resolver().resolve(this.row.header().schemaId().clone()); + this.row.initLayout(HybridRowVersion.V1, layout, this.row.resolver()); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ToArray() + public byte[] ToArray() { + return this.row.toArray(); + } + + public Result WriteBuffer(HashMap tableValue) { + Reference tempReference_row = + new Reference(this.row); + RowCursor root = RowCursor.create(tempReference_row); + this.row = tempReference_row.get(); + Reference tempReference_row2 = + new Reference(this.row); + Reference tempReference_root = + new Reference(root); + Result tempVar = this.dispatcher.WriteBuffer(tempReference_row2, tempReference_root, tableValue); + root = tempReference_root.get(); + this.row = tempReference_row2.get(); + return tempVar; + } + + public CodeGenRowGenerator clone() { + CodeGenRowGenerator varCopy = new CodeGenRowGenerator(); + + varCopy.row = this.row.clone(); + varCopy.dispatcher = this.dispatcher; + + return varCopy; + } + + private final static class AddressHybridRowSerializer extends HybridRowSerializer { + private static final Utf8String CityName = Utf8String.TranscodeUtf16("city"); + private static final Utf8String PostalCodeName = Utf8String.TranscodeUtf16("postal_code"); + private static final Utf8String StateName = Utf8String.TranscodeUtf16("state"); + private static final Utf8String StreetName = Utf8String.TranscodeUtf16("street"); + private LayoutColumn city; + private LayoutColumn postalCode; + private PostalCodeHybridRowSerializer postalCodeSerializer; + private StringToken postalCodeToken = new StringToken(); + private LayoutColumn state; + private LayoutColumn street; + + public AddressHybridRowSerializer(Layout layout, LayoutResolver resolver) { + Out tempOut_street = new Out(); + layout.TryFind(AddressHybridRowSerializer.StreetName, tempOut_street); + this.street = tempOut_street.get(); + Out tempOut_city = new Out(); + layout.TryFind(AddressHybridRowSerializer.CityName, tempOut_city); + this.city = tempOut_city.get(); + Out tempOut_state = new Out(); + layout.TryFind(AddressHybridRowSerializer.StateName, tempOut_state); + this.state = tempOut_state.get(); + Out tempOut_postalCode = new Out(); + layout.TryFind(AddressHybridRowSerializer.PostalCodeName, tempOut_postalCode); + this.postalCode = tempOut_postalCode.get(); + Out tempOut_postalCodeToken = new Out(); + layout.getTokenizer().TryFindToken(this.postalCode.path(), tempOut_postalCodeToken); + this.postalCodeToken = tempOut_postalCodeToken.get(); + this.postalCodeSerializer = new PostalCodeHybridRowSerializer(resolver.resolve(this.postalCode.typeArgs().schemaId().clone()), resolver); + } + + @Override + public Result ReadBuffer(Reference row, Reference root) { + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Result r = LayoutType.Utf8.ReadVariable(row, root, this.street, out _); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + r = LayoutType.Utf8.ReadVariable(row, root, this.city, out _); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + r = LayoutType.Utf8.ReadFixed(row, root, this.state, out _); + if (r != Result.SUCCESS) { + return r; + } + + root.get().Find(row, this.postalCodeToken.clone()); + RowCursor childScope; + Out tempOut_childScope = new Out(); + r = LayoutType.UDT.ReadScope(row, root, tempOut_childScope); + childScope = tempOut_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope = new Reference(childScope); + r = this.postalCodeSerializer.ReadBuffer(row, tempReference_childScope); + childScope = tempReference_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope2 = new Reference(childScope); + RowCursors.skip(root.get().clone(), row, tempReference_childScope2); + childScope = tempReference_childScope2.get(); + return Result.SUCCESS; + } + + @Override + public Result WriteBuffer(Reference row, Reference root, HashMap tableValue) { + for ((Utf8String key,Object value) :tableValue) + { + Result r; + switch (0) { + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' statements: + //ORIGINAL LINE: case 0 when key.Equals(AddressHybridRowSerializer.StreetName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.street, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' statements: + //ORIGINAL LINE: case 0 when key.Equals(AddressHybridRowSerializer.CityName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.city, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' statements: + //ORIGINAL LINE: case 0 when key.Equals(AddressHybridRowSerializer.StateName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteFixed(row, root, this.state, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' statements: + //ORIGINAL LINE: case 0 when key.Equals(AddressHybridRowSerializer.PostalCodeName): + case 0 + if (value != null) { + root.get().Find(row, this.postalCodeToken.clone()); + RowCursor childScope; + Out tempOut_childScope = new Out(); + r = LayoutType.UDT.WriteScope(row, root, this.postalCode.typeArgs().clone(), tempOut_childScope); + childScope = tempOut_childScope.get(); + + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope = new Reference(childScope); + r = this.postalCodeSerializer.WriteBuffer(row, tempReference_childScope, (HashMap)value); + childScope = tempReference_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope2 = new Reference(childScope); + RowCursors.skip(root.get().clone(), row, tempReference_childScope2); + childScope = tempReference_childScope2.get(); + } + + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown property name: %s", key)); + break; + } + } + + return Result.SUCCESS; + } + } + + private final static class GuestsHybridRowSerializer extends HybridRowSerializer { + private static final Utf8String AddressesName = Utf8String.TranscodeUtf16("addresses"); + private static final Utf8String ConfirmNumberName = Utf8String.TranscodeUtf16("confirm_number"); + private static final Utf8String EmailsName = Utf8String.TranscodeUtf16("emails"); + private static final Utf8String FirstNameName = Utf8String.TranscodeUtf16("first_name"); + private static final Utf8String GuestIdName = Utf8String.TranscodeUtf16("guest_id"); + private static final Utf8String LastNameName = Utf8String.TranscodeUtf16("last_name"); + private static final Utf8String PhoneNumbersName = Utf8String.TranscodeUtf16("phone_numbers"); + private static final Utf8String TitleName = Utf8String.TranscodeUtf16("title"); + private AddressHybridRowSerializer addressSerializer; + private LayoutTypeScope.WriterFunc> addressSerializerWriter; + private LayoutColumn addresses; + private TypeArgumentList addressesFieldType = new TypeArgumentList(); + private StringToken addressesToken = new StringToken(); + private LayoutColumn confirmNumber; + private LayoutColumn emails; + private StringToken emailsToken = new StringToken(); + private LayoutColumn firstName; + private LayoutColumn guestId; + private LayoutColumn lastName; + private LayoutColumn phoneNumbers; + private StringToken phoneNumbersToken = new StringToken(); + private LayoutColumn title; + + public GuestsHybridRowSerializer(Layout layout, LayoutResolver resolver) { + Out tempOut_guestId = + new Out(); + layout.TryFind(GuestsHybridRowSerializer.GuestIdName, tempOut_guestId); + this.guestId = tempOut_guestId.get(); + Out tempOut_firstName = new Out(); + layout.TryFind(GuestsHybridRowSerializer.FirstNameName, tempOut_firstName); + this.firstName = tempOut_firstName.get(); + Out tempOut_lastName + = new Out(); + layout.TryFind(GuestsHybridRowSerializer.LastNameName, tempOut_lastName); + this.lastName = tempOut_lastName.get(); + Out tempOut_title = + new Out(); + layout.TryFind(GuestsHybridRowSerializer.TitleName, tempOut_title); + this.title = tempOut_title.get(); + Out tempOut_emails = + new Out(); + layout.TryFind(GuestsHybridRowSerializer.EmailsName, tempOut_emails); + this.emails = tempOut_emails.get(); + Out tempOut_phoneNumbers = new Out(); + layout.TryFind(GuestsHybridRowSerializer.PhoneNumbersName, tempOut_phoneNumbers); + this.phoneNumbers = tempOut_phoneNumbers.get(); + Out tempOut_addresses = new Out(); + layout.TryFind(GuestsHybridRowSerializer.AddressesName, tempOut_addresses); + this.addresses = tempOut_addresses.get(); + Out tempOut_confirmNumber = new Out(); + layout.TryFind(GuestsHybridRowSerializer.ConfirmNumberName, tempOut_confirmNumber); + this.confirmNumber = tempOut_confirmNumber.get(); + Out tempOut_emailsToken = new Out(); + layout.getTokenizer().TryFindToken(this.emails.path(), tempOut_emailsToken); + this.emailsToken = tempOut_emailsToken.get(); + Out tempOut_phoneNumbersToken = new Out(); + layout.getTokenizer().TryFindToken(this.phoneNumbers.path(), tempOut_phoneNumbersToken); + this.phoneNumbersToken = tempOut_phoneNumbersToken.get(); + Out tempOut_addressesToken = new Out(); + layout.getTokenizer().TryFindToken(this.addresses.path(), tempOut_addressesToken); + this.addressesToken = tempOut_addressesToken.get(); + + this.addressesFieldType = + new TypeArgumentList(new TypeArgument[] { new TypeArgument(LayoutType.TypedTuple, + this.addresses.typeArgs().clone()) }); + + this.addressSerializer = + new AddressHybridRowSerializer(resolver.resolve(this.addresses.typeArgs().get(1).typeArgs().schemaId().clone()), resolver); + this.addressSerializerWriter = (RowBuffer b, RowCursor scope, + HashMap context) -> addressSerializer.WriteBuffer(b, + scope, context); + } + + @Override + public Result ReadBuffer(Reference row, Reference root) { + java.util.UUID _; + Out tempOut__ = new Out(); + Result r = LayoutType.Guid.readFixed(row, root, this.guestId, tempOut__); + _ = tempOut__.get(); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + r = LayoutType.Utf8.ReadVariable(row, root, this.firstName, out _); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + r = LayoutType.Utf8.ReadVariable(row, root, this.lastName, out _); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + r = LayoutType.Utf8.ReadVariable(row, root, this.title, out _); + if (r != Result.SUCCESS) { + return r; + } + + root.get().Find(row, this.emailsToken.clone()); + RowCursor childScope; + Out tempOut_childScope = + new Out(); + r = LayoutType.TypedArray.ReadScope(row, root, tempOut_childScope); + childScope = tempOut_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + while (childScope.MoveNext(row)) { + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + r = LayoutType.Utf8.ReadSparse(row, ref childScope, out _); + if (r != Result.SUCCESS) { + return r; + } + } + + Reference tempReference_childScope = + new Reference(childScope); + RowCursors.skip(root.get().clone(), row, + tempReference_childScope); + childScope = tempReference_childScope.get(); + root.get().Find(row, this.phoneNumbersToken.clone()); + Out tempOut_childScope2 = + new Out(); + r = LayoutType.TypedArray.ReadScope(row, root, tempOut_childScope2); + childScope = tempOut_childScope2.get(); + if (r != Result.SUCCESS) { + return r; + } + + while (childScope.MoveNext(row)) { + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + r = LayoutType.Utf8.ReadSparse(row, ref childScope, out _); + if (r != Result.SUCCESS) { + return r; + } + } + + Reference tempReference_childScope2 = + new Reference(childScope); + RowCursors.skip(root.get().clone(), row, + tempReference_childScope2); + childScope = tempReference_childScope2.get(); + root.get().Find(row, this.addressesToken.clone()); + Out tempOut_childScope3 = + new Out(); + r = LayoutType.TypedMap.ReadScope(row, root, tempOut_childScope3); + childScope = tempOut_childScope3.get(); + if (r != Result.SUCCESS) { + return r; + } + + while (childScope.MoveNext(row)) { + Reference tempReference_childScope3 = + new Reference(childScope); + RowCursor tupleScope; + Out tempOut_tupleScope = + new Out(); + r = LayoutType.TypedTuple.ReadScope(row, tempReference_childScope3, tempOut_tupleScope); + tupleScope = tempOut_tupleScope.get(); + childScope = tempReference_childScope3.get(); + if (r != Result.SUCCESS) { + return r; + } + + if (!tupleScope.MoveNext(row)) { + return Result.INVALID_ROW; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + r = LayoutType.Utf8.ReadSparse(row, ref tupleScope, out _); + if (r != Result.SUCCESS) { + return r; + } + + if (!tupleScope.MoveNext(row)) { + return Result.INVALID_ROW; + } + + Reference tempReference_tupleScope = + new Reference(tupleScope); + RowCursor valueScope; + Out tempOut_valueScope = + new Out(); + r = LayoutType.ImmutableUDT.ReadScope(row, tempReference_tupleScope, tempOut_valueScope); + valueScope = tempOut_valueScope.get(); + tupleScope = tempReference_tupleScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_valueScope = + new Reference(valueScope); + r = this.addressSerializer.ReadBuffer(row, tempReference_valueScope); + valueScope = tempReference_valueScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + tupleScope.Skip(row, ref valueScope); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + childScope.Skip(row, ref tupleScope); + } + + Reference tempReference_childScope4 = + new Reference(childScope); + RowCursors.skip(root.get().clone(), row, + tempReference_childScope4); + childScope = tempReference_childScope4.get(); + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + return LayoutType.Utf8.ReadVariable(row, root, this.confirmNumber, out _); + } + + @Override + public Result WriteBuffer(Reference row, Reference root, + HashMap tableValue) { + for ((Utf8String key,Object value) :tableValue) + { + Result r; + switch (0) { + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.GuestIdName): + case 0 + if (value != null) { + r = LayoutType.Guid.writeFixed(row, root, this.guestId, (UUID)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.FirstNameName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.firstName, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.LastNameName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.lastName, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.TitleName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.title, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.EmailsName): + case 0 + if (value != null) { + root.get().Find(row, this.emailsToken.clone()); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' + // keyword - these are not converted by C# to Java Converter: + r = LayoutType.TypedArray.WriteScope(row, root, this.emails.typeArgs().clone(), + (ArrayList)value, (ref RowBuffer row2, ref RowCursor childScope, + ArrayList context) -> + { + for (Object item : context) { + ReferencetempRef_row2 = new Reference (row2); + ReferencetempRef_childScope = new Reference (childScope); + Result r2 = LayoutType.Utf8.WriteSparse(tempRef_row2, tempRef_childScope, + (Utf8String)item); + childScope = tempRef_childScope.argValue; + row2 = tempRef_row2.argValue; + if (r2 != Result.SUCCESS) { + return r2; + } + + ReferencetempRef_row22 = new Reference (row2); + childScope.MoveNext(tempRef_row22); + row2 = tempRef_row22.argValue; + } + + return Result.SUCCESS; + }); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.PhoneNumbersName): + case 0 + if (value != null) { + root.get().Find(row, this.phoneNumbersToken.clone()); + RowCursor childScope; + Out tempOut_childScope = new Out(); + r = LayoutType.TypedArray.WriteScope(row, root, this.phoneNumbers.typeArgs().clone(), + tempOut_childScope); + childScope = tempOut_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + for (Object item : (ArrayList)value) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved + // 'ref' keyword - these cannot be converted using the 'Ref' helper class + // unless the method is within the code being modified: + r = LayoutType.Utf8.WriteSparse(row, ref childScope, (Utf8String)item); + if (r != Result.SUCCESS) { + return r; + } + + childScope.MoveNext(row); + } + + Reference tempReference_childScope = new Reference(childScope); + RowCursors.skip(root.get().clone(), row, tempReference_childScope); + childScope = tempReference_childScope.get(); + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.AddressesName): + case 0 + if (value != null) { + root.get().Find(row, this.addressesToken.clone()); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' + // keyword - these are not converted by C# to Java Converter: + r = LayoutType.TypedMap.WriteScope(row, root, this.addresses.typeArgs().clone(), (this + , (ArrayList)value), (ref + RowBuffer row2, ref RowCursor childScope, (GuestsHybridRowSerializer + _this, ArrayList < Object > value)ctx) -> + { + for (Object item : ctx.value) { + Reference tempReference_row2 = new Reference(row2); + Reference tempReference_childScope = new Reference(childScope); + Result r2 = LayoutType.TypedTuple.WriteScope(tempReference_row2, + tempReference_childScope, + ctx._this.addresses.TypeArgs, (ctx._this, (ArrayList)item), + (ref RowBuffer row3, ref RowCursor tupleScope, (GuestsHybridRowSerializer + _this, ArrayList < Object > value)ctx2) -> + { + ReferencetempRef_row3 = new Reference (row3); + ReferencetempRef_tupleScope = new Reference (tupleScope); + Result r3 = LayoutType.Utf8.WriteSparse(tempRef_row3, tempRef_tupleScope, + (Utf8String)ctx2.value[0]); + tupleScope = tempRef_tupleScope.argValue; + row3 = tempRef_row3.argValue; + if (r3 != Result.SUCCESS) { + return r3; + } + + ReferencetempRef_row32 = new Reference (row3); + tupleScope.MoveNext(tempRef_row32); + row3 = tempRef_row32.argValue; + Reference tempReference_row33 = new Reference(row3); + Reference tempReference_tupleScope2 = new Reference(tupleScope); + Result tempVar = LayoutType.ImmutableUDT.WriteScope(tempReference_row33, + tempReference_tupleScope2, ctx2._this.addresses.TypeArgs[1].TypeArgs, + (HashMap)ctx2.value[1], + ctx2._this.addressSerializerWriter); + tupleScope = tempReference_tupleScope2.get(); + row3 = tempReference_row33.get(); + return tempVar; + }) + childScope = tempReference_childScope.get(); + row2 = tempReference_row2.get(); + if (r2 != Result.SUCCESS) { + return r2; + } + + ReferencetempRef_row22 = new Reference (row2); + childScope.MoveNext(tempRef_row22); + row2 = tempRef_row22.argValue; + } + + return Result.SUCCESS; + }) + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(GuestsHybridRowSerializer.ConfirmNumberName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.confirmNumber, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown property name: %s", key)); + break; + } + } + + return Result.SUCCESS; + } + } + + private final static class HotelsHybridRowSerializer extends HybridRowSerializer { + private static final Utf8String AddressName = Utf8String.TranscodeUtf16("address"); + private static final Utf8String HotelIdName = Utf8String.TranscodeUtf16("hotel_id"); + private static final Utf8String NameName = Utf8String.TranscodeUtf16("name"); + private static final Utf8String PhoneName = Utf8String.TranscodeUtf16("phone"); + private LayoutColumn address; + private AddressHybridRowSerializer addressSerializer; + private StringToken addressToken = new StringToken(); + private LayoutColumn hotelId; + private LayoutColumn name; + private LayoutColumn phone; + + public HotelsHybridRowSerializer(Layout layout, LayoutResolver resolver) { + Out tempOut_hotelId = + new Out(); + layout.TryFind(HotelsHybridRowSerializer.HotelIdName, tempOut_hotelId); + this.hotelId = tempOut_hotelId.get(); + Out tempOut_name = + new Out(); + layout.TryFind(HotelsHybridRowSerializer.NameName, tempOut_name); + this.name = tempOut_name.get(); + Out tempOut_phone = + new Out(); + layout.TryFind(HotelsHybridRowSerializer.PhoneName, tempOut_phone); + this.phone = tempOut_phone.get(); + Out tempOut_address = + new Out(); + layout.TryFind(HotelsHybridRowSerializer.AddressName, tempOut_address); + this.address = tempOut_address.get(); + Out tempOut_addressToken = new Out(); + layout.getTokenizer().TryFindToken(this.address.path(), tempOut_addressToken); + this.addressToken = tempOut_addressToken.get(); + this.addressSerializer = + new AddressHybridRowSerializer(resolver.resolve(this.address.typeArgs().schemaId().clone()), + resolver); + } + + @Override + public Result ReadBuffer(Reference row, Reference root) { + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + Result r = LayoutType.Utf8.ReadFixed(row, root, this.hotelId, out _); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + r = LayoutType.Utf8.ReadVariable(row, root, this.name, out _); + if (r != Result.SUCCESS) { + return r; + } + + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + r = LayoutType.Utf8.ReadVariable(row, root, this.phone, out _); + if (r != Result.SUCCESS) { + return r; + } + + root.get().Find(row, this.addressToken.clone()); + RowCursor childScope; + Out tempOut_childScope = + new Out(); + r = LayoutType.UDT.ReadScope(row, root, tempOut_childScope); + childScope = tempOut_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope = + new Reference(childScope); + r = this.addressSerializer.ReadBuffer(row, tempReference_childScope); + childScope = tempReference_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope2 = + new Reference(childScope); + RowCursors.skip(root.get().clone(), row, + tempReference_childScope2); + childScope = tempReference_childScope2.get(); + return Result.SUCCESS; + } + + @Override + public Result WriteBuffer(Reference row, Reference root, + HashMap tableValue) { + for ((Utf8String key,Object value) :tableValue) + { + Result r; + switch (0) { + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(HotelsHybridRowSerializer.HotelIdName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteFixed(row, root, this.hotelId, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(HotelsHybridRowSerializer.NameName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.name, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(HotelsHybridRowSerializer.PhoneName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteVariable(row, root, this.phone, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(HotelsHybridRowSerializer.AddressName): + case 0 + if (value != null) { + root.get().Find(row, this.addressToken.clone()); + RowCursor childScope; + Out tempOut_childScope = new Out(); + r = LayoutType.UDT.WriteScope(row, root, this.address.typeArgs().clone(), + tempOut_childScope); + childScope = tempOut_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope = new Reference(childScope); + r = this.addressSerializer.WriteBuffer(row, tempReference_childScope, (HashMap)value); + childScope = tempReference_childScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_childScope2 = new Reference(childScope); + RowCursors.skip(root.get().clone(), row, tempReference_childScope2); + childScope = tempReference_childScope2.get(); + } + + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown property name: %s", key)); + break; + } + } + + return Result.SUCCESS; + } + } + + private abstract static class HybridRowSerializer { + public abstract Result ReadBuffer(Reference row, Reference root); + + public abstract Result WriteBuffer(Reference row, Reference root, + HashMap tableValue); + } + + private final static class PostalCodeHybridRowSerializer extends HybridRowSerializer { + private static final Utf8String Plus4Name = Utf8String.TranscodeUtf16("plus4"); + private static final Utf8String ZipName = Utf8String.TranscodeUtf16("zip"); + private LayoutColumn plus4; + private StringToken plus4Token = new StringToken(); + private LayoutColumn zip; + + // ReSharper disable once UnusedParameter.Local + public PostalCodeHybridRowSerializer(Layout layout, LayoutResolver resolver) { + Out tempOut_zip = + new Out(); + layout.TryFind(PostalCodeHybridRowSerializer.ZipName, tempOut_zip); + this.zip = tempOut_zip.get(); + Out tempOut_plus4 = + new Out(); + layout.TryFind(PostalCodeHybridRowSerializer.Plus4Name, tempOut_plus4); + this.plus4 = tempOut_plus4.get(); + Out tempOut_plus4Token = new Out(); + layout.getTokenizer().TryFindToken(this.plus4.path(), tempOut_plus4Token); + this.plus4Token = tempOut_plus4Token.get(); + } + + @Override + public Result ReadBuffer(Reference row, Reference root) { + int _; + Out tempOut__ = new Out(); + Result r = LayoutType.Int32.readFixed(row, root, this.zip, tempOut__); + _ = tempOut__.get(); + if (r != Result.SUCCESS) { + return r; + } + + root.get().Find(row, this.plus4Token.clone()); + short _; + Out tempOut__2 = new Out(); + Result tempVar = LayoutType.Int16.readSparse(row, root, tempOut__2); + _ = tempOut__2.get(); + return tempVar; + } + + @Override + public Result WriteBuffer(Reference row, Reference root, + HashMap tableValue) { + for ((Utf8String key,Object value) :tableValue) + { + Result r; + switch (0) { + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(PostalCodeHybridRowSerializer.ZipName): + case 0 + if (value != null) { + r = LayoutType.Int32.WriteFixed(row, root, this.zip, (int)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(PostalCodeHybridRowSerializer.Plus4Name): + case 0 + if (value != null) { + root.get().Find(row, this.plus4Token.clone()); + r = LayoutType.Int16.WriteSparse(row, root, (short)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown property name: %s", key)); + break; + } + } + + return Result.SUCCESS; + } + } + + private final static class RoomsHybridRowSerializer extends HybridRowSerializer { + private static final Utf8String DateName = Utf8String.TranscodeUtf16("date"); + private static final Utf8String HotelIdName = Utf8String.TranscodeUtf16("hotel_id"); + private static final Utf8String IsAvailableName = Utf8String.TranscodeUtf16("is_available"); + private static final Utf8String RoomNumberName = Utf8String.TranscodeUtf16("room_number"); + private LayoutColumn date; + private LayoutColumn hotelId; + private LayoutColumn isAvailable; + private LayoutColumn roomNumber; + + // ReSharper disable once UnusedParameter.Local + public RoomsHybridRowSerializer(Layout layout, LayoutResolver resolver) { + Out tempOut_hotelId = + new Out(); + layout.TryFind(RoomsHybridRowSerializer.HotelIdName, tempOut_hotelId); + this.hotelId = tempOut_hotelId.get(); + Out tempOut_date = + new Out(); + layout.TryFind(RoomsHybridRowSerializer.DateName, tempOut_date); + this.date = tempOut_date.get(); + Out tempOut_roomNumber = new Out(); + layout.TryFind(RoomsHybridRowSerializer.RoomNumberName, tempOut_roomNumber); + this.roomNumber = tempOut_roomNumber.get(); + Out tempOut_isAvailable = new Out(); + layout.TryFind(RoomsHybridRowSerializer.IsAvailableName, tempOut_isAvailable); + this.isAvailable = tempOut_isAvailable.get(); + } + + @Override + public Result ReadBuffer(Reference row, Reference root) { + Utf8Span _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + Result r = LayoutType.Utf8.ReadFixed(row, root, this.hotelId, out _); + if (r != Result.SUCCESS) { + return r; + } + + java.time.LocalDateTime _; + Out tempOut__ = new Out(); + r = LayoutType.DateTime.ReadFixed(row, root, this.date, tempOut__); + _ = tempOut__.get(); + if (r != Result.SUCCESS) { + return r; + } + + byte _; + Out tempOut__2 = new Out(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: r = LayoutType.UInt8.ReadFixed(ref row, ref root, this.roomNumber, out byte _); + r = LayoutType.UInt8.readFixed(row, root, this.roomNumber, tempOut__2); + _ = tempOut__2.get(); + if (r != Result.SUCCESS) { + return r; + } + + boolean _; + Out tempOut__3 = new Out(); + Result tempVar = LayoutType.Boolean.readFixed(row, root, this.isAvailable, tempOut__3); + _ = tempOut__3.get(); + return tempVar; + } + + @Override + public Result WriteBuffer(Reference row, Reference root, + HashMap tableValue) { + for ((Utf8String key,Object value) :tableValue) + { + Result r; + switch (0) { + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(RoomsHybridRowSerializer.HotelIdName): + case 0 + if (value != null) { + r = LayoutType.Utf8.WriteFixed(row, root, this.hotelId, (Utf8String)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(RoomsHybridRowSerializer.DateName): + case 0 + if (value != null) { + r = LayoutType.DateTime.WriteFixed(row, root, this.date, (LocalDateTime)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(RoomsHybridRowSerializer.RoomNumberName): + case 0 + if (value != null) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: r = LayoutType.UInt8.WriteFixed(ref row, ref root, this.roomNumber, + // (byte)value); + r = LayoutType.UInt8.WriteFixed(row, root, this.roomNumber, (byte)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to the C# 'when' clause in 'case' + // statements: + //ORIGINAL LINE: case 0 when key.Equals(RoomsHybridRowSerializer.IsAvailableName): + case 0 + if (value != null) { + r = LayoutType.Boolean.WriteFixed(row, root, this.isAvailable, (boolean)value); + if (r != Result.SUCCESS) { + return r; + } + } + + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown property name: %s", key)); + break; + } + } + + return Result.SUCCESS; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/GenerateBenchmarkSuite.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/GenerateBenchmarkSuite.java new file mode 100644 index 0000000..7c4afdd --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/GenerateBenchmarkSuite.java @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import java.io.File; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(TestData.SchemaFile, TestData.Target)] public sealed class +// GenerateBenchmarkSuite : BenchmarkSuiteBase +public final class GenerateBenchmarkSuite extends BenchmarkSuiteBase { + private String sdl; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task GenerateGuestsBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task GenerateGuestsBenchmarkAsync() + public Task GenerateGuestsBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await this.GenerateBenchmarkAsync("Guests", 50, TestData.GuestsExpected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task GenerateHotelBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task GenerateHotelBenchmarkAsync() + public Task GenerateHotelBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await this.GenerateBenchmarkAsync("Hotels", 100, TestData.HotelExpected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task GenerateRoomsBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task GenerateRoomsBenchmarkAsync() + public Task GenerateRoomsBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await this.GenerateBenchmarkAsync("Available_Rooms_By_Hotel_Date", 100, TestData.RoomsExpected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + this.sdl = Files.readString(TestData.SchemaFile); + Namespace schema = Namespace.Parse(this.sdl); + this.DefaultResolver = new LayoutResolverNamespace(schema, SystemSchema.LayoutResolver); + } + + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: private async Task GenerateBenchmarkAsync(string schemaName, int outerLoopIterations, string + // expectedFile) + private Task GenerateBenchmarkAsync(String schemaName, int outerLoopIterations, String expectedFile) { + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + ArrayList> rows = GenerateBenchmarkSuite.GenerateBenchmarkInputs(resolver, + schemaName, outerLoopIterations); + + Schema tableSchema = resolver.Namespace.Schemas.Find(x = schemaName.equals( > x.Name)) + TypeArgument typeArg = new TypeArgument(LayoutType.UDT, + new TypeArgumentList(tableSchema.getSchemaId().clone())); + + boolean allMatch = rows.size() == expected.Count; + for (int i = 0; allMatch && i < rows.size(); i++) { + allMatch |= HybridRowValueGenerator.DynamicTypeArgumentEquals(resolver, expected[i], rows.get(i), + typeArg.clone()); + } + + if (!allMatch) { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await BenchmarkSuiteBase. + WriteAllRowsAsync(expectedFile, this.sdl, resolver, resolver.Resolve(tableSchema.getSchemaId().clone()), rows); + System.out.printf("Updated expected file at: %1$s" + "\r\n", (new File(expectedFile)).getAbsolutePath()); + Assert.IsTrue(allMatch, "Expected output does not match expected file."); + } + } + + private static ArrayList> GenerateBenchmarkInputs(LayoutResolverNamespace resolver, + String schemaName, + int outerLoopIterations) { + HybridRowGeneratorConfig generatorConfig = new HybridRowGeneratorConfig(); + final int seed = 42; + RandomGenerator rand = new RandomGenerator(new Random(seed)); + HybridRowValueGenerator valueGenerator = new HybridRowValueGenerator(rand, generatorConfig); + + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + ArrayList> rows = new ArrayList>(outerLoopIterations); + for (int iteration = 0; iteration != outerLoopIterations; iteration += outerLoopIterations < 0 ? 0 : 1) { + TypeArgument typeArg = new TypeArgument(LayoutType.UDT, new TypeArgumentList(layout.getSchemaId().clone())); + HashMap rowValue = + (HashMap)valueGenerator.GenerateLayoutType(resolver, typeArg.clone()); + rows.add(rowValue); + } + + return rows; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/JsonModelRowGenerator.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/JsonModelRowGenerator.java new file mode 100644 index 0000000..aa87d29 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/JsonModelRowGenerator.java @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.ISpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; + +import static com.google.common.base.Strings.lenientFormat; + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: public ref struct JsonModelRowGenerator +//C# TO JAVA CONVERTER WARNING: Java has no equivalent to the C# ref struct: +public final class JsonModelRowGenerator { + private RowBuffer row = new RowBuffer(); + + + public JsonModelRowGenerator(int capacity, Layout layout, LayoutResolver resolver) { + this(capacity, layout, resolver, null); + } + + public JsonModelRowGenerator() { + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public JsonModelRowGenerator(int capacity, Layout layout, LayoutResolver resolver, + // ISpanResizer resizer = default) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + public JsonModelRowGenerator(int capacity, Layout layout, LayoutResolver resolver, ISpanResizer resizer) { + this.row = new RowBuffer(capacity, resizer); + this.row.initLayout(HybridRowVersion.V1, layout, resolver); + } + + public int getLength() { + return this.row.length(); + } + + public RowReader GetReader() { + Reference tempReference_row = new Reference(this.row); + // TODO: C# TO JAVA CONVERTER: The following line could not be converted: + return new RowReader(ref this.row) + this.row = tempReference_row.get(); + return tempVar; + } + + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.Stream is input or + // output: + public boolean ReadFrom(InputStream stream, int length) { + return this.row.readFrom(stream, length, HybridRowVersion.V1, this.row.resolver()); + } + + public void Reset() { + Layout layout = this.row.resolver().resolve(this.row.header().schemaId().clone()); + this.row.initLayout(HybridRowVersion.V1, layout, this.row.resolver()); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ToArray() + public byte[] ToArray() { + return this.row.toArray(); + } + + public Result WriteBuffer(HashMap value) { + Reference tempReference_row = + new Reference(this.row); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + Result tempVar = RowWriter.writeBuffer(tempReference_row, value, (RowWriter RowWriter writer, TypeArgument typeArg, + HashMap dict) -> + { + for ((Utf8String propPath,Object propValue) :dict) + { + Reference tempReference_writer = + new Reference(writer); + Result result = JsonModelRowGenerator.JsonModelSwitch(tempReference_writer, propPath, propValue); + writer = tempReference_writer.get(); + return result; + } + + return Result.SUCCESS; + }); + this.row = tempReference_row.get(); + return tempVar; + } + + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.Stream is input or + // output: + public void WriteTo(OutputStream stream) { + this.row.writeTo(stream); + } + + public JsonModelRowGenerator clone() { + JsonModelRowGenerator varCopy = new JsonModelRowGenerator(); + varCopy.row = this.row.clone(); + return varCopy; + } + + private static Result JsonModelSwitch(Reference writer, Utf8String path, Object value) { + switch (value) { + case null: + return writer.get().writeNull(path); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case bool x: + case + boolean x: + return writer.get().writeBoolean(path, x); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case long x: + case + long x: + return writer.get().writeInt64(path, x); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case double x: + case + double x: + return writer.get().writeFloat64(path, x); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case string x: + case String + x: + return writer.get().WriteString(path, x); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case Utf8String x: + case Utf8String + x: + return writer.get().WriteString(path, x.Span); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case byte[] x: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + case + byte[] x: + return writer.get().WriteBinary(path, x); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case ReadOnlyMemory x: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + case ReadOnlyMemory < Byte > x: + return writer.get().WriteBinary(path, x.Span); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case Dictionary x: + case HashMap < Utf8String, Object > x: + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these + // are not converted by C# to Java Converter: + return writer.get().writeScope(path, new TypeArgument(LayoutType.Object), x, + (RowWriter RowWriter writer2, TypeArgument typeArg, HashMap dict) -> + { + for ((Utf8String propPath,Object propValue) :dict) + { + Reference tempReference_writer2 = new Reference(writer2); + Result result = JsonModelRowGenerator.JsonModelSwitch(tempReference_writer2, propPath, propValue); + writer2 = tempReference_writer2.get(); + return result; + } + + return Result.SUCCESS; + }); + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# pattern variables in 'case' statements: + //ORIGINAL LINE: case List x: + case ArrayList < Object > x: + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + return writer.get().writeScope(path, new TypeArgument(LayoutType.Array), x, (RowWriter RowWriter writer2, TypeArgument typeArg, ArrayList list) -> + { + for (Object elm : list) { + Reference tempReference_writer2 = new Reference(writer2); + Result result = JsonModelRowGenerator.JsonModelSwitch(tempReference_writer2, null, elm); + writer2 = tempReference_writer2.get(); + if (result != Result.SUCCESS) { + return result; + } + } + + return Result.SUCCESS; + }); + default: + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s", value.getClass().getSimpleName())); + return Result.FAILURE; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/Measurements.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/Measurements.java new file mode 100644 index 0000000..6455845 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/Measurements.java @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import java.io.Closeable; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.time.LocalDateTime; + +public class Measurements implements Closeable { + private static final long RunId = LocalDateTime.UtcNow.getTime(); + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.FileStream is + // input or output: + private FileStream file; + private TextWriter writer; + + public Measurements(String path) { + File info = new File(path); + if (info.exists()) { + this.file = new FileOutputStream(path, true); + this.writer = new OutputStreamWriter(this.file, java.nio.charset.StandardCharsets.US_ASCII); + } else { + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.FileStream + // is input or output: + this.file = new FileStream(path, FileMode.CreateNew); + this.writer = new OutputStreamWriter(this.file, java.nio.charset.StandardCharsets.US_ASCII); + this.writer.WriteLine("RunId,Model,Operation,Schema,API,Iterations,Size (bytes),Total (ms),Duration (ms)," + + "Allocated (bytes),ThreadId,Gen0,Gen1,Gen2,Total Allocated (bytes)"); + } + } + + public final void WriteMeasurement(String model, String operation, String schema, String api, + int outerLoopIterations, int innerLoopIterations, long totalSize, + double totalDurationMs, int threadId, int gen0, int gen1, int gen2, + long totalAllocatedBytes) { + System.out.printf("RunId: %1$s, \nModel: %2$s \nOperation: %3$s \nSchema: %4$s \nAPI: %5$s" + "\r\n", + Measurements.RunId, model, operation, schema, api); + + System.out.printf("\n\nIterations: %1$s \nSize (bytes): %1.0f \nTotal (ms): %2.4f \nDuration (ms): %3.4f " + + "\nAllocated (bytes): %4.4f" + "\r\n", outerLoopIterations, totalSize / outerLoopIterations, + totalDurationMs, totalDurationMs / (outerLoopIterations * innerLoopIterations), + totalAllocatedBytes / (outerLoopIterations * innerLoopIterations)); + + // TODO: C# TO JAVA CONVERTER: The '4:n0' format specifier is not converted to Java: + System.out.printf("\n\nThread: %1$s \nCollections: %2$s, %3$s, %4$s \nTotal Allocated: {4:n0} (bytes)" + "\r" + + "\n", threadId, gen0, gen1, gen2, totalAllocatedBytes); + + + this.writer.WriteLine("{0},{1},{2},{3},{4},{5},{6:F0},{7:F8},{8:F8},{9:F8},{10},{11},{12},{13},{14:0}", + Measurements.RunId, model, operation, schema, api, outerLoopIterations, totalSize / outerLoopIterations, + totalDurationMs, totalDurationMs / (outerLoopIterations * innerLoopIterations), totalAllocatedBytes / (outerLoopIterations * innerLoopIterations), threadId, gen0, gen1, gen2, totalAllocatedBytes); + } + + public final void close() throws IOException { + this.writer.Flush(); + this.writer.Dispose(); + this.file.Dispose(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/MicroBenchmarkSuiteBase.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/MicroBenchmarkSuiteBase.java new file mode 100644 index 0000000..cf5d8c5 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/MicroBenchmarkSuiteBase.java @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import JetBrains.Profiler.Api.*; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.core.Reference; + +import java.util.ArrayList; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [SuppressMessage("Microsoft.Reliability", "CA2001:Avoid calling problematic methods", Justification +// = "Perf Benchmark")] public class MicroBenchmarkSuiteBase : BenchmarkSuiteBase +public class MicroBenchmarkSuiteBase extends BenchmarkSuiteBase { + private static final String MetricsResultFile = "HybridRowPerf.csv"; + private static final int WarmCount = 5; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.Reliability", "CA2001:Avoid calling problematic methods", + // Justification = "Perf Benchmark")] private protected static void Benchmark(string model, string + // operation, string schema, string api, int innerLoopIterations, ref BenchmarkContext context, + // BenchmarkBody loopBody, BenchmarkMeasure measure, List expected) + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + //ORIGINAL LINE: [SuppressMessage("Microsoft.Reliability", "CA2001:Avoid calling problematic methods", + // Justification = "Perf Benchmark")] private protected static void Benchmark(string model, string + // operation, string schema, string api, int innerLoopIterations, ref BenchmarkContext context, + // BenchmarkBody loopBody, BenchmarkMeasure measure, List expected) + protected static void Benchmark(String model, String operation, String schema, String api, + int innerLoopIterations, Reference context, + BenchmarkBody loopBody, BenchmarkMeasure measure, + ArrayList expected) { + Stopwatch sw = new Stopwatch(); + double durationMs = 0; + long rowSize = 0; + + // Warm + int warm = Math.min(MicroBenchmarkSuiteBase.WarmCount, expected.size()); + for (int i = 0; i < warm; i++) { + for (int innerLoop = 0; innerLoop < innerLoopIterations; innerLoop++) { + loopBody.invoke(context, expected.get(i)); + } + } + + // Execute + System.gc(); + System.runFinalization(); + Thread.sleep(1000); + int gen0 = GC.CollectionCount(0); + int gen1 = GC.CollectionCount(1); + int gen2 = GC.CollectionCount(2); + long allocated = GC.GetAllocatedBytesForCurrentThread(); + int threadId = Thread.currentThread().ManagedThreadId; + ThreadPriority currentPriority = Thread.currentThread().Priority; + Thread.currentThread().Priority = ThreadPriority.Highest; + MemoryProfiler.CollectAllocations(true); + MemoryProfiler.GetSnapshot(); + try { + for (TValue tableValue : expected) { + sw.Restart(); + MicroBenchmarkSuiteBase.BenchmarkInnerLoop(innerLoopIterations, tableValue, context, loopBody); + sw.Stop(); + durationMs += sw.Elapsed.TotalMilliseconds; + rowSize += measure.invoke(context, tableValue); + } + } finally { + Thread.currentThread().Priority = currentPriority; + gen0 = GC.CollectionCount(0) - gen0; + gen1 = GC.CollectionCount(1) - gen1; + gen2 = GC.CollectionCount(2) - gen2; + allocated = GC.GetAllocatedBytesForCurrentThread() - allocated; + MemoryProfiler.GetSnapshot(); + MemoryProfiler.CollectAllocations(false); + } + + try (Measurements m = new Measurements(MicroBenchmarkSuiteBase.MetricsResultFile)) { + m.WriteMeasurement(model, operation, schema, api, expected.size(), innerLoopIterations, rowSize, + durationMs, threadId, gen0, gen1, gen2, allocated); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [MethodImpl(MethodImplOptions.NoInlining)] private static void BenchmarkInnerLoop(int + // innerLoopIterations, TValue tableValue, ref BenchmarkContext context, BenchmarkBody loopBody) + private static void BenchmarkInnerLoop(int innerLoopIterations, TValue tableValue, + Reference context, + BenchmarkBody loopBody) { + for (int innerLoop = 0; innerLoop < innerLoopIterations; innerLoop++) { + loopBody.invoke(context, tableValue); + } + } + + @FunctionalInterface + public interface BenchmarkBody { + void invoke(Reference context, TValue value); + } + + @FunctionalInterface + public interface BenchmarkMeasure { + long invoke(Reference context, TValue value); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: private protected ref struct BenchmarkContext + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to the C# ref struct: + //C# TO JAVA CONVERTER WARNING: Java has no equivalent to C# 'private protected' access: + protected final static class BenchmarkContext { + public CodeGenRowGenerator CodeGenWriter = new CodeGenRowGenerator(); + public JsonModelRowGenerator JsonModelWriter = new JsonModelRowGenerator(); + public WriteRowGenerator PatchWriter = new WriteRowGenerator(); + public ProtobufRowGenerator ProtobufWriter = new ProtobufRowGenerator(); + public StreamingRowGenerator StreamingWriter = new StreamingRowGenerator(); + + public BenchmarkContext clone() { + BenchmarkContext varCopy = new BenchmarkContext(); + + varCopy.CodeGenWriter = this.CodeGenWriter.clone(); + varCopy.ProtobufWriter = this.ProtobufWriter.clone(); + varCopy.PatchWriter = this.PatchWriter.clone(); + varCopy.StreamingWriter = this.StreamingWriter.clone(); + varCopy.JsonModelWriter = this.JsonModelWriter.clone(); + + return varCopy; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ProtobufRowGenerator.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ProtobufRowGenerator.java new file mode 100644 index 0000000..c97a39a --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ProtobufRowGenerator.java @@ -0,0 +1,338 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import Google.Protobuf.*; +import Google.Protobuf.Collections.*; +import com.azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Address; +import com.azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Available_Rooms_By_Hotel_Date; +import com.azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Guests; +import com.azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Hotels; +import com.azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.PostalCode; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.UUID; + +import static com.google.common.base.Strings.lenientFormat; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable DontUseNamespaceAliases // Namespace Aliases should be avoided + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning restore DontUseNamespaceAliases // Namespace Aliases should be avoided + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal ref struct ProtobufRowGenerator +//C# TO JAVA CONVERTER WARNING: Java has no equivalent to the C# ref struct: +public final class ProtobufRowGenerator { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private ReadOnlySpan active; + private ReadOnlySpan active; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private readonly byte[] buffer; + private byte[] buffer; + private String schemaName; + + public ProtobufRowGenerator() { + } + + public ProtobufRowGenerator(String schemaName, int capacity) { + this.schemaName = schemaName; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.buffer = new byte[capacity]; + this.buffer = new byte[capacity]; + this.active = this.buffer; + } + + public int getLength() { + return this.active.Length; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public void ReadBuffer(byte[] buffer) + public void ReadBuffer(byte[] buffer) { + switch (this.schemaName) { + case "Hotels": + ProtobufRowGenerator.ReadBufferHotel(buffer); + break; + + case "Guests": + ProtobufRowGenerator.ReadBufferGuest(buffer); + break; + + case "Available_Rooms_By_Hotel_Date": + ProtobufRowGenerator.ReadBufferRoom(buffer); + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown schema will be ignored: %s", this.schemaName)); + break; + } + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ToArray() + public byte[] ToArray() { + return this.active.ToArray(); + } + + public void WriteBuffer(HashMap tableValue) { + switch (this.schemaName) { + case "Hotels": + this.WriteBufferHotel(tableValue); + break; + + case "Guests": + this.WriteBufferGuest(tableValue); + break; + + case "Available_Rooms_By_Hotel_Date": + this.WriteBufferRoom(tableValue); + break; + + default: + throw new IllegalStateException(lenientFormat("Unknown schema will be ignored: %s", this.schemaName)); + break; + } + } + + public ProtobufRowGenerator clone() { + ProtobufRowGenerator varCopy = new ProtobufRowGenerator(); + + varCopy.schemaName = this.schemaName; + varCopy.buffer = this.buffer; + varCopy.active = this.active; + + return varCopy; + } + + private static Address MakeAddress(HashMap tableValue) { + Address address = new Address(); + for ((Utf8String key,Object value) :tableValue) + { + switch (key.toString()) { + case "street": + address.setStreet(value == null ? null : ((Utf8String)value).toString()); + break; + + case "city": + address.setCity(value == null ? null : ((Utf8String)value).toString()); + break; + + case "state": + address.setState(value == null ? null : ((Utf8String)value).toString()); + break; + + case "postal_code": + address.setPostalCode(value == null ? null : ProtobufRowGenerator.MakePostalCode((HashMap)value)); + break; + + default: + throw new IllegalStateException(); + break; + } + } + + return address; + } + + private static PostalCode MakePostalCode(HashMap tableValue) { + PostalCode postalCode = new PostalCode(); + for ((Utf8String key,Object value) :tableValue) + { + switch (key.toString()) { + case "zip": + postalCode.setZip((Integer)value); + break; + + case "plus4": + postalCode.setPlus4((Short)value); + break; + + default: + throw new IllegalStateException(); + break; + } + } + + return postalCode; + } + + private static void PopulateStringAddressMap(MapField field, + ArrayList list) { + for (Object item : list) { + ArrayList tuple = (ArrayList)item; + String key = ((Utf8String)tuple.get(0)).toString(); + Address value = + ProtobufRowGenerator.MakeAddress((HashMap)tuple.get(1)); + field.Add(key, value); + } + } + + private static void PopulateStringList(RepeatedField field, ArrayList list) { + for (Object item : list) { + field.Add(((Utf8String)item).toString()); + } + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static void ReadBufferGuest(byte[] buffer) + private static void ReadBufferGuest(byte[] buffer) { + Guests item = + new Guests(); + item.MergeFrom(buffer); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static void ReadBufferHotel(byte[] buffer) + private static void ReadBufferHotel(byte[] buffer) { + Hotels item = + new Hotels(); + item.MergeFrom(buffer); + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static void ReadBufferRoom(byte[] buffer) + private static void ReadBufferRoom(byte[] buffer) { + Available_Rooms_By_Hotel_Date item = new azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Available_Rooms_By_Hotel_Date(); + item.MergeFrom(buffer); + } + + private void WriteBufferGuest(HashMap tableValue) { + azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Guests room = + new azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Guests(); + try (CodedOutputStream stm = new CodedOutputStream(this.buffer)) { + for ((Utf8String key,Object value) :tableValue) + { + switch (key.toString()) { + case "guest_id": + room.setGuestId(value == null ? null : ((UUID)value).toString()); + break; + + case "first_name": + room.setFirstName(value == null ? null : ((Utf8String)value).toString()); + break; + + case "last_name": + room.setLastName(value == null ? null : ((Utf8String)value).toString()); + break; + + case "title": + room.setTitle(value == null ? null : ((Utf8String)value).toString()); + break; + + case "emails": + if (value != null) { + ProtobufRowGenerator.PopulateStringList(room.getEmails(), (ArrayList)value); + } + + break; + + case "phone_numbers": + if (value != null) { + ProtobufRowGenerator.PopulateStringList(room.getPhoneNumbers(), (ArrayList)value); + } + + break; + + case "addresses": + if (value != null) { + ProtobufRowGenerator.PopulateStringAddressMap(room.getAddresses(), + (ArrayList)value); + } + + break; + + case "confirm_number": + room.setConfirmNumber(value == null ? null : ((Utf8String)value).toString()); + break; + + default: + Assert.Fail("should never happen"); + break; + } + } + + room.WriteTo(stm); + stm.Flush(); + this.active = this.buffer.AsSpan(0, (int)stm.Position); + } + } + + private void WriteBufferHotel(HashMap tableValue) { + azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Hotels room = + new azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Hotels(); + try (CodedOutputStream stm = new CodedOutputStream(this.buffer)) { + for ((Utf8String key,Object value) :tableValue) + { + switch (key.toString()) { + case "hotel_id": + room.setHotelId(value == null ? null : ((Utf8String)value).toString()); + break; + + case "name": + room.setName(value == null ? null : ((Utf8String)value).toString()); + break; + + case "phone": + room.setPhone(value == null ? null : ((Utf8String)value).toString()); + break; + + case "address": + room.setAddress(value == null ? null : ProtobufRowGenerator.MakeAddress((HashMap)value)); + break; + + default: + Assert.Fail("should never happen"); + break; + } + } + + room.WriteTo(stm); + stm.Flush(); + this.active = this.buffer.AsSpan(0, (int)stm.Position); + } + } + + private void WriteBufferRoom(HashMap tableValue) { + azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Available_Rooms_By_Hotel_Date room = new azure.data.cosmos.serialization.hybridrow.perf.CassandraHotel.Protobuf.Available_Rooms_By_Hotel_Date(); + try (CodedOutputStream stm = new CodedOutputStream(this.buffer)) { + for ((Utf8String key,Object value) :tableValue) + { + switch (key.toString()) { + case "hotel_id": + room.setHotelId(value == null ? null : ((Utf8String)value).toString()); + break; + + case "date": + room.setDate(value == null ? null : ((LocalDateTime)value).getTime()); + break; + + case "room_number": + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: room.RoomNumber = (Nullable)value; + room.setRoomNumber((Byte)value); + break; + + case "is_available": + room.setIsAvailable((Boolean)value); + break; + + default: + Assert.Fail("should never happen"); + break; + } + } + + room.WriteTo(stm); + stm.Flush(); + this.active = this.buffer.AsSpan(0, (int)stm.Position); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ReaderBenchmark.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ReaderBenchmark.java new file mode 100644 index 0000000..cf1df3d --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/ReaderBenchmark.java @@ -0,0 +1,317 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.MemorySpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.recordio.RecordIOStream; +import com.azure.data.cosmos.serialization.hybridrow.io.Segment; + +import java.io.Closeable; +import java.io.File; +import java.io.IOException; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("Microsoft.Reliability", "CA2001:Avoid calling problematic methods", +// Justification = "Perf Benchmark")][DeploymentItem("TestData\\*.hr", "TestData")] public sealed class ReaderBenchmark +public final class ReaderBenchmark { + private static final String CombinedScriptsData = "TestData\\CombinedScriptsData.hr"; + private static final int InitialCapacity = 2 * 1024 * 1024; + private static final int MeasureCount = 10; + private static final int WarmCount = 5; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][Ignore] public async Task AllAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][Ignore] public async Task AllAsync() + public Task AllAsync() { + final String dir = "E:\\TestData\\HybridRow"; + for (File childFile : (new File(dir)).EnumerateFiles("*.hr")) { + try (BenchmarkContext context = new BenchmarkContext(childFile.getPath(), false, false)) { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await ReaderBenchmark. + BenchmarkAsync(context, (object arg) -> ReaderBenchmark.RowReaderBenchmarkAsync(arg)); + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(ReaderBenchmark.CombinedScriptsData, "TestData")] + // public async Task RowReaderAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(ReaderBenchmark.CombinedScriptsData, "TestData")] + // public async Task RowReaderAsync() + public Task RowReaderAsync() { + try (BenchmarkContext context = new BenchmarkContext(ReaderBenchmark.CombinedScriptsData, true, true)) { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await ReaderBenchmark.BenchmarkAsync(context, (object arg) -> ReaderBenchmark.RowReaderBenchmarkAsync(arg)); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][Ignore] public async Task SpecificFileAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][Ignore] public async Task SpecificFileAsync() + public Task SpecificFileAsync() { + final String filename = "E:\\TestData\\HybridRow\\Lastfm.hr"; + try (BenchmarkContext context = new BenchmarkContext(filename, true, true)) { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await ReaderBenchmark.BenchmarkAsync(context, (object arg) -> ReaderBenchmark.RowReaderBenchmarkAsync(arg)); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.Reliability", "CA2001:Avoid calling problematic methods", + // Justification = "Perf Benchmark")] private static async Task BenchmarkAsync(BenchmarkContext context, + // Func body) + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [SuppressMessage("Microsoft.Reliability", "CA2001:Avoid calling problematic methods", + // Justification = "Perf Benchmark")] private static async Task BenchmarkAsync(BenchmarkContext context, + // Func body) + private static Task BenchmarkAsync(BenchmarkContext context, tangible.Func1Param body) { + try (SingleThreadedTaskScheduler scheduler = new SingleThreadedTaskScheduler()) { + // Warm + System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); + for (int i = 0; i < ReaderBenchmark.WarmCount; i++) { + context.Reset(); + sw.Restart(); + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await Task. + Factory.StartNew(body, context, CancellationToken.None, TaskCreationOptions.None, scheduler).Unwrap(); + sw.Stop(); + if (context.getShowWarmSummary()) { + context.Summarize(sw.Elapsed); + } + } + + // Execute + double[] timing = new double[ReaderBenchmark.MeasureCount]; + for (int i = 0; i < ReaderBenchmark.MeasureCount; i++) { + System.gc(); + System.runFinalization(); + context.Reset(); + sw.Restart(); + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + await Task. + Factory.StartNew(body, context, CancellationToken.None, TaskCreationOptions.None, scheduler).Unwrap(); + sw.Stop(); + if (context.getShowSummary()) { + context.Summarize(sw.Elapsed); + } + + timing[i] = sw.Elapsed.TotalMilliseconds; + } + + Arrays.sort(timing); + System.out.println(String.format("File: %1$s, Mean: %1.4f", + Path.GetFileNameWithoutExtension(context.getInputFile()), timing[ReaderBenchmark.MeasureCount / 2])); + } + } + + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: private static async Task RowReaderBenchmarkAsync(object ctx) + private static Task RowReaderBenchmarkAsync(Object ctx) { + BenchmarkContext context = (BenchmarkContext)ctx; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MemorySpanResizer resizer = new MemorySpanResizer(ReaderBenchmark.InitialCapacity); + MemorySpanResizer resizer = new MemorySpanResizer(ReaderBenchmark.InitialCapacity); + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + Result r = await + RecordIOStream.ReadRecordIOAsync(context.getInput(), + record -> + { + context.IncrementRecordCount(); + r = ReaderBenchmark.VisitOneRow(record, context.getResolver()); + assert Result.SUCCESS == r; + return Result.SUCCESS; + }, segment -> + { + Segment _; + Out tempOut__ = + new Out(); + r = SegmentSerializer.Read(segment.Span, context.getResolver(), tempOut__); + _ = tempOut__.get(); + assert Result.SUCCESS == r; + + // TODO: do something with embedded schema. + return Result.SUCCESS; + }, resizer); + + assert Result.SUCCESS == r; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static Result VisitOneRow(Memory buffer, LayoutResolver resolver) + private static Result VisitOneRow(Memory buffer, LayoutResolver resolver) { + RowBuffer row = new RowBuffer(buffer.Span, HybridRowVersion.V1, resolver); + Reference tempReference_row = + new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + return RowReaderExtensions.VisitReader(reader.clone()); + } + + private final static class BenchmarkContext implements Closeable { + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.Stream is + // input or output: + private Stream input; + private String inputFile; + private long recordCount; + private LayoutResolver resolver; + private boolean showSummary; + private boolean showWarmSummary; + + + public BenchmarkContext(String inputFile, boolean showSummary) { + this(inputFile, showSummary, false); + } + + public BenchmarkContext(String inputFile) { + this(inputFile, true, false); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public BenchmarkContext(string inputFile, bool showSummary = true, bool showWarmSummary = + // false) + public BenchmarkContext(String inputFile, boolean showSummary, boolean showWarmSummary) { + this.inputFile = inputFile; + this.showSummary = showSummary; + this.showWarmSummary = showWarmSummary; + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.FileStream + // is input or output: + this.input = new FileStream(inputFile, FileMode.Open); + this.resolver = SystemSchema.LayoutResolver; + } + + // TODO: C# TO JAVA CONVERTER: C# to Java Converter cannot determine whether this System.IO.Stream is + // input or output: + public Stream getInput() { + return this.input; + } + + public String getInputFile() { + return this.inputFile; + } + + public LayoutResolver getResolver() { + return this.resolver; + } + + public boolean getShowSummary() { + return this.showSummary; + } + + public boolean getShowWarmSummary() { + return this.showWarmSummary; + } + + public void IncrementRecordCount() { + this.recordCount++; + } + + public void Reset() { + this.recordCount = 0; + this.input.Seek(0, SeekOrigin.Begin); + } + + public void Summarize(TimeSpan duration) { + System.out.print(String.format("Total Time: %0.4f, ", duration.TotalMilliseconds)); + System.out.println(String.format("Record Count: %1$s", this.recordCount)); + } + + public void close() throws IOException { + this.input.Dispose(); + } + } + + private final static class SingleThreadedTaskScheduler extends TaskScheduler implements Closeable { + private CancellationTokenSource cancel; + private EventWaitHandle ready; + private ConcurrentQueue tasks; + private Thread worker; + + // Creates a new instance with the specified degree of parallelism. + public SingleThreadedTaskScheduler() { + this.tasks = new ConcurrentQueue(); + this.ready = new ManualResetEvent(false); + this.worker = new Thread() { + void run() { + this.DoWork(); + } + }; + this.cancel = new CancellationTokenSource(); + this.worker.start(); + } + + // Gets the maximum concurrency level supported by this scheduler. + @Override + public int getMaximumConcurrencyLevel() { + return 1; + } + + public void close() throws IOException { + if (!this.cancel.IsCancellationRequested) { + this.cancel.Cancel(); + this.worker.join(); + this.ready == null ? null : this.ready.Dispose(); + this.cancel == null ? null : this.cancel.Dispose(); + } + } + + @Override + protected java.lang.Iterable GetScheduledTasks() { + return null; + } + + // Queues a task to the scheduler. + @Override + protected void QueueTask(Task task) { + synchronized (this.tasks) { + this.tasks.Enqueue(task); + if (Thread.currentThread() != this.worker) { + this.ready.Set(); + } + } + } + + @Override + protected boolean TryDequeue(Task task) { + return false; + } + + // Attempts to execute the specified task on the current thread. + @Override + protected boolean TryExecuteTaskInline(Task task, boolean taskWasPreviouslyQueued) { + // If this thread isn't already processing a task, we don't support inlining + if (Thread.currentThread() != this.worker) { + return false; + } + + // If the task was previously queued, then skip it. + if (taskWasPreviouslyQueued) { + return false; + } + + return this.TryExecuteTask(task); + } + + private void DoWork() { + while (!this.cancel.IsCancellationRequested) { + Task item; + Out tempOut_item = new Out(); + if (this.tasks.TryDequeue(tempOut_item)) { + item = tempOut_item.get(); + this.TryExecuteTask(item); + } else { + item = tempOut_item.get(); + this.ready.WaitOne(TimeSpan.FromSeconds(1)); + } + } + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/RowReaderExtensions.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/RowReaderExtensions.java new file mode 100644 index 0000000..4c3748f --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/RowReaderExtensions.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Result; + +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.IMMUTABLE_TAGGED2_SCOPE; + +public final class RowReaderExtensions { + public static Result VisitReader(Reference reader) { + while (reader.get().Read()) { + Utf8Span path = reader.get().getPathSpan(); + switch (reader.get().getType().LayoutCode) { + case Null: + case Boolean: + case Int8: + case Int16: + case Int32: + case Int64: + case UInt8: + case UInt16: + case UInt32: + case UInt64: + case VarInt: + case VarUInt: + case Float32: + case Float64: + case Float128: + case Decimal: + case DateTime: + case UnixDateTime: + case Guid: + case MongoDbObjectId: + case Utf8: + case Binary: + break; + + case NullableScope: + case ImmutableNullableScope: { + if (!reader.get().getHasValue()) { + break; + } + + // TODO: C# TO JAVA CONVERTER: There is no 'goto' in Java: + goto case LayoutCode.TypedTupleScope + } + + case ObjectScope: + case ImmutableObjectScope: + case Schema: + case ImmutableSchema: + case ArrayScope: + case ImmutableArrayScope: + case TypedArrayScope: + case ImmutableTypedArrayScope: + case TypedSetScope: + case ImmutableTypedSetScope: + case TypedMapScope: + case ImmutableTypedMapScope: + case TupleScope: + case ImmutableTupleScope: + case TypedTupleScope: + case ImmutableTypedTupleScope: + case TaggedScope: + case ImmutableTaggedScope: + case Tagged2Scope: + case IMMUTABLE_TAGGED2_SCOPE: { + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + Result r = reader.get().ReadScope(null, (ref RowReader child, Object _) -> child.VisitReader()); + if (r != Result.SUCCESS) { + return r; + } + + break; + } + + default: { + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s", reader.get().getType().LayoutCode)); + break; + } + } + } + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/SchematizedMicroBenchmarkSuite.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/SchematizedMicroBenchmarkSuite.java new file mode 100644 index 0000000..2ffddf7 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/SchematizedMicroBenchmarkSuite.java @@ -0,0 +1,639 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import MongoDB.Bson.IO.*; +import Newtonsoft.Json.*; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(TestData.SchemaFile, TestData.Target)] public sealed class +// SchematizedMicroBenchmarkSuite : MicroBenchmarkSuiteBase +public final class SchematizedMicroBenchmarkSuite extends MicroBenchmarkSuiteBase { + private static final JsonSerializerSettings JsonSettings = new JsonSerializerSettings + private String sdl; + + { + NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task BsonGuestsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task BsonGuestsReadBenchmarkAsync() + public Task BsonGuestsReadBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.BsonReadBenchmark(resolver, "Guests", "Guests", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task BsonGuestsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task BsonGuestsWriteBenchmarkAsync() + public Task BsonGuestsWriteBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.BsonWriteBenchmark(resolver, "Guests", "Guests", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task BsonHotelReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task BsonHotelReadBenchmarkAsync() + public Task BsonHotelReadBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.BsonReadBenchmark(resolver, "Hotels", "Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task BsonHotelWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task BsonHotelWriteBenchmarkAsync() + public Task BsonHotelWriteBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.BsonWriteBenchmark(resolver, "Hotels", "Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task BsonRoomsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task BsonRoomsReadBenchmarkAsync() + public Task BsonRoomsReadBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.BsonReadBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", 10000, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task BsonRoomsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task BsonRoomsWriteBenchmarkAsync() + public Task BsonRoomsWriteBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.BsonWriteBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", 10000, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task JsonGuestsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task JsonGuestsReadBenchmarkAsync() + public Task JsonGuestsReadBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.JsonReadBenchmark("Guests", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task JsonGuestsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task JsonGuestsWriteBenchmarkAsync() + public Task JsonGuestsWriteBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.JsonWriteBenchmark("Guests", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task JsonHotelReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task JsonHotelReadBenchmarkAsync() + public Task JsonHotelReadBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.JsonReadBenchmark("Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task JsonHotelWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task JsonHotelWriteBenchmarkAsync() + public Task JsonHotelWriteBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.JsonWriteBenchmark("Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task JsonRoomsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task JsonRoomsReadBenchmarkAsync() + public Task JsonRoomsReadBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.JsonReadBenchmark("Rooms", 10000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task JsonRoomsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task JsonRoomsWriteBenchmarkAsync() + public Task JsonRoomsWriteBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace _) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.JsonWriteBenchmark("Rooms", 10000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task LayoutGuestsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task LayoutGuestsReadBenchmarkAsync() + public Task LayoutGuestsReadBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 1000; + //#endif + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.LayoutReadBenchmark(resolver, "Guests", "Guests", innerLoopIterations, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task LayoutGuestsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task LayoutGuestsWriteBenchmarkAsync() + public Task LayoutGuestsWriteBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 1000; + //#endif + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.LayoutWriteBenchmark(resolver, "Guests", "Guests", innerLoopIterations, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task LayoutHotelReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task LayoutHotelReadBenchmarkAsync() + public Task LayoutHotelReadBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.LayoutReadBenchmark(resolver, "Hotels", "Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task LayoutHotelWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task LayoutHotelWriteBenchmarkAsync() + public Task LayoutHotelWriteBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.LayoutWriteBenchmark(resolver, "Hotels", "Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task LayoutRoomsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task LayoutRoomsReadBenchmarkAsync() + public Task LayoutRoomsReadBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.LayoutReadBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", 1000, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task LayoutRoomsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task LayoutRoomsWriteBenchmarkAsync() + public Task LayoutRoomsWriteBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.LayoutWriteBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", 1000, + expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + this.sdl = Files.readString(TestData.SchemaFile); + Namespace schema = Namespace.Parse(this.sdl); + this.DefaultResolver = new LayoutResolverNamespace(schema, SystemSchema.LayoutResolver); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task StreamingGuestsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task StreamingGuestsReadBenchmarkAsync() + public Task StreamingGuestsReadBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.StreamingReadBenchmark(resolver, "Guests", "Guests", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task StreamingGuestsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.GuestsExpected, TestData.Target)] public + // async Task StreamingGuestsWriteBenchmarkAsync() + public Task StreamingGuestsWriteBenchmarkAsync() { + String expectedFile = TestData.GuestsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.StreamingWriteBenchmark(resolver, "Guests", "Guests", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task StreamingHotelReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task StreamingHotelReadBenchmarkAsync() + public Task StreamingHotelReadBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.StreamingReadBenchmark(resolver, "Hotels", "Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task StreamingHotelWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.HotelExpected, TestData.Target)] public + // async Task StreamingHotelWriteBenchmarkAsync() + public Task StreamingHotelWriteBenchmarkAsync() { + String expectedFile = TestData.HotelExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.StreamingWriteBenchmark(resolver, "Hotels", "Hotels", 1000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task StreamingRoomsReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task StreamingRoomsReadBenchmarkAsync() + public Task StreamingRoomsReadBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.StreamingReadBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", + 10000, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task StreamingRoomsWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.RoomsExpected, TestData.Target)] public + // async Task StreamingRoomsWriteBenchmarkAsync() + public Task StreamingRoomsWriteBenchmarkAsync() { + String expectedFile = TestData.RoomsExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + SchematizedMicroBenchmarkSuite.StreamingWriteBenchmark(resolver, "Available_Rooms_By_Hotel_Date", "Rooms", + 10000, expected); + } + + private static void BsonReadBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName, + int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + try (BsonRowGenerator writer = new BsonRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver)) { + for (HashMap tableValue : expected) { + writer.Reset(); + writer.WriteBuffer(tableValue); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(writer.ToArray()); + expectedSerialized.add(writer.ToArray()); + } + } + + BenchmarkContext ignoredContext = null; + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "BSON", + // innerLoopIterations, ref ignoredContext, (ref BenchmarkContext _, byte[] tableValue) => + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "BSON", innerLoopIterations, + tempReference_ignoredContext, (ref BenchmarkContext _, byte[] tableValue) -> + { + try (MemoryStream stm = new MemoryStream(tableValue)) { + try (BsonBinaryReader bsonReader = new BsonBinaryReader(stm)) { + bsonReader.VisitBsonDocument(); + } + } + }, (ref BenchmarkContext _, byte[] tableValue) -> tableValue.length, expectedSerialized); + ignoredContext = tempReference_ignoredContext.get(); + } + + private static void BsonWriteBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName, + int innerLoopIterations, ArrayList> expected) { + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + try (BsonRowGenerator writer = new BsonRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver)) { + BenchmarkContext ignoredContext = null; + + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are + // not converted by C# to Java Converter: + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Write", dataSetName, "BSON", innerLoopIterations, + tempReference_ignoredContext, (ref BenchmarkContext _, HashMap tableValue) -> + { + writer.Reset(); + writer.WriteBuffer(tableValue); + }, (ref BenchmarkContext _, HashMap tableValue) -> writer.getLength(), expected); + ignoredContext = tempReference_ignoredContext.get(); + } + } + + private static void JsonReadBenchmark(String dataSetName, int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Encoding utf8Encoding = new UTF8Encoding(); + JsonSerializer jsonSerializer = JsonSerializer.Create(SchematizedMicroBenchmarkSuite.JsonSettings); + try (MemoryStream jsonStream = new MemoryStream(BenchmarkSuiteBase.InitialCapacity)) { + try (OutputStreamWriter textWriter = new OutputStreamWriter(jsonStream)) { + try (JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)) { + jsonSerializer.Converters.Add(new Utf8StringJsonConverter()); + + for (HashMap tableValue : expected) { + jsonSerializer.Serialize(jsonWriter, tableValue); + jsonWriter.Flush(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(jsonStream.ToArray()); + expectedSerialized.add((Byte)jsonStream.ToArray()); + jsonStream.SetLength(0); + } + } + } + } + + BenchmarkContext ignoredContext = null; + jsonSerializer.Converters.Add(new Utf8StringJsonConverter()); + + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "JSON", + // innerLoopIterations, ref ignoredContext, (ref BenchmarkContext _, byte[] tableValue) => + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "JSON", innerLoopIterations, + tempReference_ignoredContext, (ref BenchmarkContext _, byte[] tableValue) -> + { + try (MemoryStream jsonStream = new MemoryStream(tableValue)) { + try (InputStreamReader textReader = new InputStreamReader(jsonStream)) { + try (JsonTextReader jsonReader = new JsonTextReader(textReader)) { + while (jsonReader.Read()) { + // Just visit the entire structure without materializing any of the values. + } + } + } + } + }, (ref BenchmarkContext _, byte[] tableValue) -> tableValue.length, expectedSerialized); + ignoredContext = tempReference_ignoredContext.get(); + } + + private static void JsonWriteBenchmark(String dataSetName, int innerLoopIterations, ArrayList> expected) { + Encoding utf8Encoding = new UTF8Encoding(); + JsonSerializer jsonSerializer = JsonSerializer.Create(SchematizedMicroBenchmarkSuite.JsonSettings); + try (MemoryStream jsonStream = new MemoryStream(BenchmarkSuiteBase.InitialCapacity)) { + try (OutputStreamWriter textWriter = new OutputStreamWriter(jsonStream)) { + try (JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)) { + BenchmarkContext ignoredContext = null; + jsonSerializer.Converters.Add(new Utf8StringJsonConverter()); + + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - + // these are not converted by C# to Java Converter: + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Write", dataSetName, "JSON", + innerLoopIterations, tempReference_ignoredContext, (ref BenchmarkContext _, HashMap tableValue) -> + { + jsonStream.SetLength(0); + jsonSerializer.Serialize(jsonWriter, tableValue); + jsonWriter.Flush(); + }, (ref BenchmarkContext _, HashMap value) -> jsonStream.Length, expected); + ignoredContext = tempReference_ignoredContext.get(); + } + } + } + } + + private static void LayoutReadBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName, + int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.StreamingWriter = new StreamingRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver); + + for (HashMap tableValue : expected) { + context.StreamingWriter.Reset(); + + Result r = context.StreamingWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(context.StreamingWriter.ToArray()); + expectedSerialized.add((Byte)context.StreamingWriter.ToArray()); + } + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "Layout", + // innerLoopIterations, ref context, (ref BenchmarkContext ctx, byte[] tableValue) => + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "Layout", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, byte[] tableValue) -> + { + VisitRowGenerator visitor = new VisitRowGenerator(tableValue.AsSpan(), resolver); + Result r = visitor.DispatchLayout(layout); + ResultAssert.IsSuccess(r); + }, (ref BenchmarkContext ctx, byte[] tableValue) -> tableValue.length, expectedSerialized); + context = tempReference_context.get(); + } + + private static void LayoutWriteBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName, + int innerLoopIterations, ArrayList> expected) { + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.PatchWriter = new WriteRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver); + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Write", dataSetName, "Layout", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, HashMap dict) -> + { + ctx.PatchWriter.Reset(); + Result r = ctx.PatchWriter.DispatchLayout(layout, dict); + ResultAssert.IsSuccess(r); + }, (ref BenchmarkContext ctx, HashMap _) -> ctx.PatchWriter.Length, expected); + context = tempReference_context.get(); + } + + private static void StreamingReadBenchmark(LayoutResolverNamespace resolver, String schemaName, String dataSetName, int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.StreamingWriter = new StreamingRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver); + + for (HashMap tableValue : expected) { + context.StreamingWriter.Reset(); + + Result r = context.StreamingWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(context.StreamingWriter.ToArray()); + expectedSerialized.add((Byte)context.StreamingWriter.ToArray()); + } + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "HybridRow", innerLoopIterations, ref context, (ref BenchmarkContext ctx, byte[] tableValue) => + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Read", dataSetName, "HybridRow", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, byte[] tableValue) -> + { + RowBuffer row = new RowBuffer(tableValue.AsSpan(), HybridRowVersion.V1, resolver); + Reference tempReference_row = new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + RowReaderExtensions.VisitReader(reader.clone()); + }, (ref BenchmarkContext ctx, byte[] tableValue) -> tableValue.length, expectedSerialized); + context = tempReference_context.get(); + } + + private static void StreamingWriteBenchmark(LayoutResolverNamespace resolver, String schemaName, + String dataSetName, int innerLoopIterations, + ArrayList> expected) { + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.StreamingWriter = new StreamingRowGenerator(BenchmarkSuiteBase.InitialCapacity, layout, resolver); + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + MicroBenchmarkSuiteBase.Benchmark("Schematized", "Write", dataSetName, "HybridRow", innerLoopIterations, + tempReference_context, (ref BenchmarkContext ctx, HashMap tableValue) -> + { + ctx.StreamingWriter.Reset(); + + Result r = ctx.StreamingWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + }, (ref BenchmarkContext ctx, HashMap _) -> ctx.StreamingWriter.Length, expected); + context = tempReference_context.get(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/TestData.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/TestData.java new file mode 100644 index 0000000..7c68999 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/TestData.java @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +/** + * Names of assets in the TestData folder. + */ +public class TestData { + public static final String GuestsExpected = "TestData\\GuestsSchemaExpected.hr"; + public static final String HotelExpected = "TestData\\HotelSchemaExpected.hr"; + public static final String Messages1KExpected = "TestData\\Messages1KExpected.hr"; + public static final String RoomsExpected = "TestData\\RoomsSchemaExpected.hr"; + public static final String SchemaFile = "TestData\\CassandraHotelSchema.json"; + /** + * The folder to which TestData assets should be copied during deployment. + */ + public static final String Target = "TestData"; +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/UnschematizedMicroBenchmarkSuite.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/UnschematizedMicroBenchmarkSuite.java new file mode 100644 index 0000000..e303e0f --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/UnschematizedMicroBenchmarkSuite.java @@ -0,0 +1,339 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf; + +import MongoDB.Bson.IO.*; +import Newtonsoft.Json.*; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * Tests involving fully (or mostly) unschematized test data. + */ +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public sealed class UnschematizedMicroBenchmarkSuite : MicroBenchmarkSuiteBase +public final class UnschematizedMicroBenchmarkSuite extends MicroBenchmarkSuiteBase { + private static final JsonSerializerSettings JsonSettings = new JsonSerializerSettings + + { + NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.Indented + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task BsonMessages1KReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task BsonMessages1KReadBenchmarkAsync() + public Task BsonMessages1KReadBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 10; + //#endif + String expectedFile = TestData.Messages1KExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + UnschematizedMicroBenchmarkSuite.BsonReadBenchmark("Messages1K", innerLoopIterations, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task BsonMessages1KWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task BsonMessages1KWriteBenchmarkAsync() + public Task BsonMessages1KWriteBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 10; + //#endif + String expectedFile = TestData.Messages1KExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + UnschematizedMicroBenchmarkSuite.BsonWriteBenchmark("Messages1K", innerLoopIterations, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task JsonMessages1KReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task JsonMessages1KReadBenchmarkAsync() + public Task JsonMessages1KReadBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 10; + //#endif + String expectedFile = TestData.Messages1KExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + UnschematizedMicroBenchmarkSuite.JsonReadBenchmark("Messages1K", innerLoopIterations, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task JsonMessages1KWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task JsonMessages1KWriteBenchmarkAsync() + public Task JsonMessages1KWriteBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 10; + //#endif + String expectedFile = TestData.Messages1KExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + UnschematizedMicroBenchmarkSuite.JsonWriteBenchmark("Messages1K", innerLoopIterations, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task Messages1KReadBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task Messages1KReadBenchmarkAsync() + public Task Messages1KReadBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 10; + //#endif + String expectedFile = TestData.Messages1KExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + UnschematizedMicroBenchmarkSuite.JsonModelReadBenchmark(resolver, "TypedJsonHybridRowSchema", "Messages1K", + innerLoopIterations, expected); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task Messages1KWriteBenchmarkAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem(TestData.Messages1KExpected, TestData.Target)] + // public async Task Messages1KWriteBenchmarkAsync() + public Task Messages1KWriteBenchmarkAsync() { + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + //#if DEBUG + final int innerLoopIterations = 1; + //#else + final int innerLoopIterations = 10; + //#endif + String expectedFile = TestData.Messages1KExpected; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + (List < Dictionary < Utf8String, object >> expected, LayoutResolverNamespace resolver) =await + this.LoadExpectedAsync(expectedFile); + UnschematizedMicroBenchmarkSuite.JsonModelWriteBenchmark(resolver, "TypedJsonHybridRowSchema", "Messages1K", + innerLoopIterations, expected); + } + + private static void BsonReadBenchmark(String dataSetName, int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + try (BsonJsonModelRowGenerator writer = new BsonJsonModelRowGenerator(InitialCapacity)) { + for (HashMap tableValue : expected) { + writer.Reset(); + writer.WriteBuffer(tableValue); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(writer.ToArray()); + expectedSerialized.add(writer.ToArray()); + } + } + + BenchmarkContext ignoredContext = null; + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Unschematized", "Read", dataSetName, "BSON", innerLoopIterations, ref ignoredContext, (ref BenchmarkContext _, byte[] tableValue) => + Benchmark("Unschematized", "Read", dataSetName, "BSON", innerLoopIterations, tempReference_ignoredContext, (ref BenchmarkContext _, byte[] tableValue) -> + { + try (MemoryStream stm = new MemoryStream(tableValue)) { + try (BsonBinaryReader bsonReader = new BsonBinaryReader(stm)) { + bsonReader.VisitBsonDocument(); + } + } + }, (ref BenchmarkContext _, byte[] tableValue) -> tableValue.length, expectedSerialized); + ignoredContext = tempReference_ignoredContext.get(); + } + + private static void BsonWriteBenchmark(String dataSetName, int innerLoopIterations, ArrayList> expected) { + try (BsonJsonModelRowGenerator writer = new BsonJsonModelRowGenerator(InitialCapacity)) { + BenchmarkContext ignoredContext = null; + + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are + // not converted by C# to Java Converter: + Benchmark("Unschematized", "Write", dataSetName, "BSON", innerLoopIterations, + tempReference_ignoredContext, (ref BenchmarkContext _, HashMap tableValue) -> + { + writer.Reset(); + writer.WriteBuffer(tableValue); + }, (ref BenchmarkContext _, HashMap tableValue) -> writer.getLength(), expected); + ignoredContext = tempReference_ignoredContext.get(); + } + } + + private static void JsonModelReadBenchmark(LayoutResolverNamespace resolver, String schemaName, + String dataSetName, int innerLoopIterations, + ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.JsonModelWriter = new JsonModelRowGenerator(InitialCapacity, layout, resolver); + + for (HashMap tableValue : expected) { + context.JsonModelWriter.Reset(); + + Result r = context.JsonModelWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(context.JsonModelWriter.ToArray()); + expectedSerialized.add(context.JsonModelWriter.ToArray()); + } + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Unschematized", "Read", dataSetName, "HybridRowSparse", + // innerLoopIterations, ref context, (ref BenchmarkContext ctx, byte[] tableValue) => + Benchmark("Unschematized", "Read", dataSetName, "HybridRowSparse", + innerLoopIterations, tempReference_context, (ref BenchmarkContext ctx, byte[] tableValue) -> + { + RowBuffer row = new RowBuffer(tableValue.AsSpan(), HybridRowVersion.V1, resolver); + Reference tempReference_row = + new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + RowReaderExtensions.VisitReader(reader.clone()); + }, (ref BenchmarkContext ctx, byte[] tableValue) -> tableValue.length, expectedSerialized); + context = tempReference_context.get(); + } + + private static void JsonModelWriteBenchmark(LayoutResolverNamespace resolver, String schemaName, + String dataSetName, int innerLoopIterations, + ArrayList> expected) { + Layout layout = resolver.Resolve(tangible.ListHelper.find(resolver.getNamespace().getSchemas(), x = + schemaName.equals( > x.Name)).SchemaId) + BenchmarkContext context = new BenchmarkContext(); + context.JsonModelWriter = new JsonModelRowGenerator(InitialCapacity, layout, resolver); + + Reference tempReference_context = new Reference(context); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + Benchmark("Unschematized", "Write", dataSetName, "HybridRowSparse", + innerLoopIterations, tempReference_context, (ref BenchmarkContext ctx, HashMap tableValue) -> + { + ctx.JsonModelWriter.Reset(); + + Result r = ctx.JsonModelWriter.WriteBuffer(tableValue); + ResultAssert.IsSuccess(r); + }, (ref BenchmarkContext ctx, HashMap tableValue) -> ctx.JsonModelWriter.Length, expected); + context = tempReference_context.get(); + } + + private static void JsonReadBenchmark(String dataSetName, int innerLoopIterations, ArrayList> expected) { + // Serialize input data to sequence of byte buffers. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: List expectedSerialized = new List(expected.Count); + ArrayList expectedSerialized = new ArrayList(expected.size()); + Encoding utf8Encoding = new UTF8Encoding(); + JsonSerializer jsonSerializer = JsonSerializer.Create(UnschematizedMicroBenchmarkSuite.JsonSettings); + try (MemoryStream jsonStream = new MemoryStream(InitialCapacity)) { + try (OutputStreamWriter textWriter = new OutputStreamWriter(jsonStream)) { + try (JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)) { + jsonSerializer.Converters.Add(new Utf8StringJsonConverter()); + + for (HashMap tableValue : expected) { + jsonSerializer.Serialize(jsonWriter, tableValue); + jsonWriter.Flush(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: expectedSerialized.Add(jsonStream.ToArray()); + expectedSerialized.add((Byte)jsonStream.ToArray()); + jsonStream.SetLength(0); + } + } + } + } + + BenchmarkContext ignoredContext = null; + jsonSerializer.Converters.Add(new Utf8StringJsonConverter()); + + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MicroBenchmarkSuiteBase.Benchmark("Unschematized", "Read", dataSetName, "JSON", + // innerLoopIterations, ref ignoredContext, (ref BenchmarkContext _, byte[] tableValue) => + Benchmark("Unschematized", "Read", dataSetName, "JSON", innerLoopIterations, + tempReference_ignoredContext, (ref BenchmarkContext _, byte[] tableValue) -> + { + try (MemoryStream jsonStream = new MemoryStream(tableValue)) { + try (InputStreamReader textReader = new InputStreamReader(jsonStream)) { + try (JsonTextReader jsonReader = new JsonTextReader(textReader)) { + while (jsonReader.Read()) { + // Just visit the entire structure without materializing any of the values. + } + } + } + } + }, (ref BenchmarkContext _, byte[] tableValue) -> tableValue.length, expectedSerialized); + ignoredContext = tempReference_ignoredContext.get(); + } + + private static void JsonWriteBenchmark(String dataSetName, int innerLoopIterations, ArrayList> expected) { + Encoding utf8Encoding = new UTF8Encoding(); + JsonSerializer jsonSerializer = JsonSerializer.Create(UnschematizedMicroBenchmarkSuite.JsonSettings); + try (MemoryStream jsonStream = new MemoryStream(InitialCapacity)) { + try (OutputStreamWriter textWriter = new OutputStreamWriter(jsonStream)) { + try (JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)) { + BenchmarkContext ignoredContext = null; + jsonSerializer.Converters.Add(new Utf8StringJsonConverter()); + + Reference tempReference_ignoredContext = new Reference(ignoredContext); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - + // these are not converted by C# to Java Converter: + Benchmark("Unschematized", "Write", dataSetName, "JSON", + innerLoopIterations, tempReference_ignoredContext, (ref BenchmarkContext _, HashMap tableValue) -> + { + jsonStream.SetLength(0); + jsonSerializer.Serialize(jsonWriter, tableValue); + jsonWriter.Flush(); + }, (ref BenchmarkContext _, HashMap value) -> jsonStream.Length, expected); + ignoredContext = tempReference_ignoredContext.get(); + } + } + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Address.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Address.java new file mode 100644 index 0000000..325e49c --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Address.java @@ -0,0 +1,316 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf.cassandrahotel.protobuf; + +import com.azure.data.cosmos.serialization.hybridrow.perf.*; +import com.google.protobuf.Message; +import com.google.protobuf.Parser; + +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: TestData/CassandraHotelSchema.proto +// + +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pb = Google.Protobuf; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbc = Google.Protobuf.Collections; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbr = Google.Protobuf.Reflection; + +public final class Address implements Message
{ + /** + * Field number for the "city" field. + */ + public static final int CityFieldNumber = 2; + /** + * Field number for the "postal_code" field. + */ + public static final int PostalCodeFieldNumber = 4; + /** + * Field number for the "state" field. + */ + public static final int StateFieldNumber = 3; + /** + * Field number for the "street" field. + */ + public static final int StreetFieldNumber = 1; + private static final Parser _parser = new Address().getParserForType(); + private static final Google.Protobuf.FieldCodec _single_city_codec = Google.Protobuf.FieldCodec.ForClassWrapper(18); + + // TODO: C# TO JAVA CONVERTER: Java does not support 'partial' methods: + // partial void OnConstruction(); + private static final Google.Protobuf.FieldCodec _single_state_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(26); + private static final Google.Protobuf.FieldCodec _single_street_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(10); + private Google.Protobuf.UnknownFieldSet _unknownFields; + private String city_; + private PostalCode postalCode_; + private String state_; + private String street_; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Address() + public Address() { + OnConstruction(); + } + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Address(Address other) + public Address(Address other) { + this(); + setStreet(other.getStreet()); + setCity(other.getCity()); + setState(other.getState()); + setPostalCode(other.postalCode_ != null ? other.getPostalCode().Clone() : null); + _unknownFields = Google.Protobuf.UnknownFieldSet.Clone(other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string City + public String getCity() { + return city_; + } + + public void setCity(String value) { + city_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor + public Google.Protobuf.Reflection getDescriptor() { + return getDescriptor(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf.Reflection + // .MessageDescriptor Descriptor + public static Google.Protobuf.Reflection.MessageDescriptor getDescriptor() { + return CassandraHotelSchemaReflection.getDescriptor().MessageTypes[1]; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf + // .MessageParser
Parser + public static Google.Protobuf.MessageParser
getParser() { + return _parser; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Microsoft.Azure.Cosmos.Serialization + // .HybridRow.Tests.Perf.CassandraHotel.Protobuf.PostalCode PostalCode + public PostalCode getPostalCode() { + return postalCode_; + } + + public void setPostalCode(PostalCode value) { + postalCode_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string State + public String getState() { + return state_; + } + + public void setState(String value) { + state_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string Street + public String getStreet() { + return street_; + } + + public void setStreet(String value) { + street_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() + public int CalculateSize() { + int size = 0; + if (street_ != null) { + size += _single_street_codec.CalculateSizeWithTag(getStreet()); + } + if (city_ != null) { + size += _single_city_codec.CalculateSizeWithTag(getCity()); + } + if (state_ != null) { + size += _single_state_codec.CalculateSizeWithTag(getState()); + } + if (postalCode_ != null) { + size += 1 + Google.Protobuf.CodedOutputStream.ComputeMessageSize(getPostalCode()); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Address Clone() + public Address Clone() { + return new Address(this); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Address other) + public void MergeFrom(Address other) { + if (other == null) { + return; + } + if (other.street_ != null) { + if (street_ == null || !other.getStreet().equals("")) { + setStreet(other.getStreet()); + } + } + if (other.city_ != null) { + if (city_ == null || !other.getCity().equals("")) { + setCity(other.getCity()); + } + } + if (other.state_ != null) { + if (state_ == null || !other.getState().equals("")) { + setState(other.getState()); + } + } + if (other.postalCode_ != null) { + if (postalCode_ == null) { + postalCode_ = new PostalCode(); + } + getPostalCode().MergeFrom(other.getPostalCode()); + } + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Google.Protobuf + // .CodedInputStream input) + public void MergeFrom(Google.Protobuf.CodedInputStream input) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint tag; + int tag; + while ((tag = input.ReadTag()) != 0) { + switch (tag) { + default: + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + String value = _single_street_codec.Read(input); + if (street_ == null || !value.equals("")) { + setStreet(value); + } + break; + } + case 18: { + String value = _single_city_codec.Read(input); + if (city_ == null || !value.equals("")) { + setCity(value); + } + break; + } + case 26: { + String value = _single_state_codec.Read(input); + if (state_ == null || !value.equals("")) { + setState(value); + } + break; + } + case 34: { + if (postalCode_ == null) { + postalCode_ = new PostalCode(); + } + input.ReadMessage(postalCode_); + break; + } + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(Google.Protobuf + // .CodedOutputStream output) + public void WriteTo(Google.Protobuf.CodedOutputStream output) { + if (street_ != null) { + _single_street_codec.WriteTagAndValue(output, getStreet()); + } + if (city_ != null) { + _single_city_codec.WriteTagAndValue(output, getCity()); + } + if (state_ != null) { + _single_state_codec.WriteTagAndValue(output, getState()); + } + if (postalCode_ != null) { + output.WriteRawTag(34); + output.WriteMessage(getPostalCode()); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) + @Override + public boolean equals(Object other) { + return Equals(other instanceof Address ? (Address)other : null); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Address other) + public boolean equals(Address other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!getStreet().equals(other.getStreet())) { + return false; + } + if (!getCity().equals(other.getCity())) { + return false; + } + if (!getState().equals(other.getState())) { + return false; + } + if (!getPostalCode().equals(other.getPostalCode())) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() + @Override + public int hashCode() { + int hash = 1; + if (street_ != null) { + hash ^= getStreet().hashCode(); + } + if (city_ != null) { + hash ^= getCity().hashCode(); + } + if (state_ != null) { + hash ^= getState().hashCode(); + } + if (postalCode_ != null) { + hash ^= getPostalCode().hashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.hashCode(); + } + return hash; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() + @Override + public String toString() { + return Google.Protobuf.JsonFormatter.ToDiagnosticString(this); + } + +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Available_Rooms_By_Hotel_Date.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Available_Rooms_By_Hotel_Date.java new file mode 100644 index 0000000..842ea13 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Available_Rooms_By_Hotel_Date.java @@ -0,0 +1,320 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf.cassandrahotel.protobuf; + +import com.azure.data.cosmos.serialization.hybridrow.perf.*; + +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: TestData/CassandraHotelSchema.proto +// + +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pb = Google.Protobuf; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbc = Google.Protobuf.Collections; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbr = Google.Protobuf.Reflection; + +public final class Available_Rooms_By_Hotel_Date implements Google.Protobuf.IMessage { + /** + * Field number for the "date" field. + */ + public static final int DateFieldNumber = 2; + /** + * Field number for the "hotel_id" field. + */ + public static final int HotelIdFieldNumber = 1; + /** + * Field number for the "is_available" field. + */ + public static final int IsAvailableFieldNumber = 4; + /** + * Field number for the "room_number" field. + */ + public static final int RoomNumberFieldNumber = 3; + private static final Google.Protobuf.MessageParser _parser = + new Google.Protobuf.MessageParser(() -> new Available_Rooms_By_Hotel_Date()); + private static final Google.Protobuf.FieldCodec _single_date_codec = + Google.Protobuf.FieldCodec.ForStructWrapper(18); + + // TODO: C# TO JAVA CONVERTER: Java does not support 'partial' methods: + // partial void OnConstruction(); + private static final Google.Protobuf.FieldCodec _single_hotelId_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(10); + private static final Google.Protobuf.FieldCodec _single_isAvailable_codec = + Google.Protobuf.FieldCodec.ForStructWrapper(34); + private static final Google.Protobuf.FieldCodec _single_roomNumber_codec = + Google.Protobuf.FieldCodec.ForStructWrapper(26); + private Google.Protobuf.UnknownFieldSet _unknownFields; + private Long date_; + private String hotelId_; + private Boolean isAvailable_; + private Integer roomNumber_; + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Available_Rooms_By_Hotel_Date() + public Available_Rooms_By_Hotel_Date() { + OnConstruction(); + } + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Available_Rooms_By_Hotel_Date + // (Available_Rooms_By_Hotel_Date other) + public Available_Rooms_By_Hotel_Date(Available_Rooms_By_Hotel_Date other) { + this(); + setHotelId(other.getHotelId()); + setDate(other.getDate()); + setRoomNumber(other.getRoomNumber()); + setIsAvailable(other.getIsAvailable()); + _unknownFields = Google.Protobuf.UnknownFieldSet.Clone(other._unknownFields); + } + + /** + * datetime + */ + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Nullable Date + public Long getDate() { + return date_; + } + + public void setDate(Long value) { + date_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor + public Google.Protobuf.Reflection getDescriptor() { + return getDescriptor(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf.Reflection + // .MessageDescriptor Descriptor + public static Google.Protobuf.Reflection.MessageDescriptor getDescriptor() { + return CassandraHotelSchemaReflection.getDescriptor().MessageTypes[3]; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string HotelId + public String getHotelId() { + return hotelId_; + } + + public void setHotelId(String value) { + hotelId_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Nullable IsAvailable + public Boolean getIsAvailable() { + return isAvailable_; + } + + public void setIsAvailable(Boolean value) { + isAvailable_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf + // .MessageParser Parser + public static Google.Protobuf.MessageParser getParser() { + return _parser; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Nullable RoomNumber + public Integer getRoomNumber() { + return roomNumber_; + } + + public void setRoomNumber(Integer value) { + roomNumber_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() + public int CalculateSize() { + int size = 0; + if (hotelId_ != null) { + size += _single_hotelId_codec.CalculateSizeWithTag(getHotelId()); + } + if (date_ != null) { + size += _single_date_codec.CalculateSizeWithTag(getDate()); + } + if (roomNumber_ != null) { + size += _single_roomNumber_codec.CalculateSizeWithTag(getRoomNumber()); + } + if (isAvailable_ != null) { + size += _single_isAvailable_codec.CalculateSizeWithTag(getIsAvailable()); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Available_Rooms_By_Hotel_Date Clone() + public Available_Rooms_By_Hotel_Date Clone() { + return new Available_Rooms_By_Hotel_Date(this); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom + // (Available_Rooms_By_Hotel_Date other) + public void MergeFrom(Available_Rooms_By_Hotel_Date other) { + if (other == null) { + return; + } + if (other.hotelId_ != null) { + if (hotelId_ == null || !other.getHotelId().equals("")) { + setHotelId(other.getHotelId()); + } + } + if (other.date_ != null) { + if (date_ == null || other.getDate() != 0L) { + setDate(other.getDate()); + } + } + if (other.roomNumber_ != null) { + if (roomNumber_ == null || other.getRoomNumber() != 0) { + setRoomNumber(other.getRoomNumber()); + } + } + if (other.isAvailable_ != null) { + if (isAvailable_ == null || other.getIsAvailable() != false) { + setIsAvailable(other.getIsAvailable()); + } + } + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Google.Protobuf + // .CodedInputStream input) + public void MergeFrom(Google.Protobuf.CodedInputStream input) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint tag; + int tag; + while ((tag = input.ReadTag()) != 0) { + switch (tag) { + default: + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + String value = _single_hotelId_codec.Read(input); + if (hotelId_ == null || !value.equals("")) { + setHotelId(value); + } + break; + } + case 18: { + Long value = _single_date_codec.Read(input); + if (date_ == null || value != 0L) { + setDate(value); + } + break; + } + case 26: { + Integer value = _single_roomNumber_codec.Read(input); + if (roomNumber_ == null || value != 0) { + setRoomNumber(value); + } + break; + } + case 34: { + Boolean value = _single_isAvailable_codec.Read(input); + if (isAvailable_ == null || value != false) { + setIsAvailable(value); + } + break; + } + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(Google.Protobuf + // .CodedOutputStream output) + public void WriteTo(Google.Protobuf.CodedOutputStream output) { + if (hotelId_ != null) { + _single_hotelId_codec.WriteTagAndValue(output, getHotelId()); + } + if (date_ != null) { + _single_date_codec.WriteTagAndValue(output, getDate()); + } + if (roomNumber_ != null) { + _single_roomNumber_codec.WriteTagAndValue(output, getRoomNumber()); + } + if (isAvailable_ != null) { + _single_isAvailable_codec.WriteTagAndValue(output, getIsAvailable()); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) + @Override + public boolean equals(Object other) { + return Equals(other instanceof Available_Rooms_By_Hotel_Date ? (Available_Rooms_By_Hotel_Date)other : null); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals + // (Available_Rooms_By_Hotel_Date other) + public boolean equals(Available_Rooms_By_Hotel_Date other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!getHotelId().equals(other.getHotelId())) { + return false; + } + if (getDate() != other.getDate()) { + return false; + } + if (getRoomNumber() != other.getRoomNumber()) { + return false; + } + if (getIsAvailable() != other.getIsAvailable()) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() + @Override + public int hashCode() { + int hash = 1; + if (hotelId_ != null) { + hash ^= getHotelId().hashCode(); + } + if (date_ != null) { + hash ^= getDate().hashCode(); + } + if (roomNumber_ != null) { + hash ^= getRoomNumber().hashCode(); + } + if (isAvailable_ != null) { + hash ^= getIsAvailable().hashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.hashCode(); + } + return hash; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() + @Override + public String toString() { + return Google.Protobuf.JsonFormatter.ToDiagnosticString(this); + } + +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/CassandraHotelSchemaReflection.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/CassandraHotelSchemaReflection.java new file mode 100644 index 0000000..f877f02 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/CassandraHotelSchemaReflection.java @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf.cassandrahotel.protobuf; + +import com.azure.data.cosmos.serialization.hybridrow.perf.*; + +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: TestData/CassandraHotelSchema.proto +// + +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pb = Google.Protobuf; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbc = Google.Protobuf.Collections; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbr = Google.Protobuf.Reflection; + + +/** + * Holder for reflection information generated from TestData/CassandraHotelSchema.proto + */ +public final class CassandraHotelSchemaReflection { + + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + ///#region Descriptor + + private static Google.Protobuf.Reflection.FileDescriptor descriptor; + + static { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: byte[] descriptorData = System.Convert.FromBase64String(string.Concat + // ("CiNUZXN0RGF0YS9DYXNzYW5kcmFIb3RlbFNjaGVtYS5wcm90bxJITWljcm9z", + // "b2Z0LkF6dXJlLkNvc21vcy5TZXJpYWxpemF0aW9uLkh5YnJpZFJvdy5UZXN0", + // "cy5QZXJmLkNhc3NhbmRyYUhvdGVsGh5nb29nbGUvcHJvdG9idWYvd3JhcHBl", + // "cnMucHJvdG8iYgoKUG9zdGFsQ29kZRIoCgN6aXAYASABKAsyGy5nb29nbGUu", + // "cHJvdG9idWYuSW50MzJWYWx1ZRIqCgVwbHVzNBgCIAEoCzIbLmdvb2dsZS5w", + // "cm90b2J1Zi5JbnQzMlZhbHVlIvsBCgdBZGRyZXNzEiwKBnN0cmVldBgBIAEo", + // "CzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRIqCgRjaXR5GAIgASgL", + // "MhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEisKBXN0YXRlGAMgASgL", + // "MhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEmkKC3Bvc3RhbF9jb2Rl", + // "GAQgASgLMlQuTWljcm9zb2Z0LkF6dXJlLkNvc21vcy5TZXJpYWxpemF0aW9u", + // "Lkh5YnJpZFJvdy5UZXN0cy5QZXJmLkNhc3NhbmRyYUhvdGVsLlBvc3RhbENv", + // "ZGUi9QEKBkhvdGVscxIuCghob3RlbF9pZBgBIAEoCzIcLmdvb2dsZS5wcm90", + // "b2J1Zi5TdHJpbmdWYWx1ZRIqCgRuYW1lGAIgASgLMhwuZ29vZ2xlLnByb3Rv", + // "YnVmLlN0cmluZ1ZhbHVlEisKBXBob25lGAMgASgLMhwuZ29vZ2xlLnByb3Rv", + // "YnVmLlN0cmluZ1ZhbHVlEmIKB2FkZHJlc3MYBCABKAsyUS5NaWNyb3NvZnQu", + // "QXp1cmUuQ29zbW9zLlNlcmlhbGl6YXRpb24uSHlicmlkUm93LlRlc3RzLlBl", + // "cmYuQ2Fzc2FuZHJhSG90ZWwuQWRkcmVzcyLeAQodQXZhaWxhYmxlX1Jvb21z", + // "X0J5X0hvdGVsX0RhdGUSLgoIaG90ZWxfaWQYASABKAsyHC5nb29nbGUucHJv", + // "dG9idWYuU3RyaW5nVmFsdWUSKQoEZGF0ZRgCIAEoCzIbLmdvb2dsZS5wcm90", + // "b2J1Zi5JbnQ2NFZhbHVlEjAKC3Jvb21fbnVtYmVyGAMgASgLMhsuZ29vZ2xl", + // "LnByb3RvYnVmLkludDMyVmFsdWUSMAoMaXNfYXZhaWxhYmxlGAQgASgLMhou", + // "Z29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZSKfBAoGR3Vlc3RzEi4KCGd1ZXN0", + // "X2lkGAEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjAKCmZp", + // "cnN0X25hbWUYAiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS", + // "LwoJbGFzdF9uYW1lGAMgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1Zh", + // "bHVlEisKBXRpdGxlGAQgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1Zh", + // "bHVlEg4KBmVtYWlscxgFIAMoCRIVCg1waG9uZV9udW1iZXJzGAYgAygJEnIK", + // "CWFkZHJlc3NlcxgHIAMoCzJfLk1pY3Jvc29mdC5BenVyZS5Db3Ntb3MuU2Vy", + // "aWFsaXphdGlvbi5IeWJyaWRSb3cuVGVzdHMuUGVyZi5DYXNzYW5kcmFIb3Rl", + // "bC5HdWVzdHMuQWRkcmVzc2VzRW50cnkSNAoOY29uZmlybV9udW1iZXIYCCAB", + // "KAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUagwEKDkFkZHJlc3Nl", + // "c0VudHJ5EgsKA2tleRgBIAEoCRJgCgV2YWx1ZRgCIAEoCzJRLk1pY3Jvc29m", + // "dC5BenVyZS5Db3Ntb3MuU2VyaWFsaXphdGlvbi5IeWJyaWRSb3cuVGVzdHMu", + // "UGVyZi5DYXNzYW5kcmFIb3RlbC5BZGRyZXNzOgI4AUJUqgJRTWljcm9zb2Z0", + // "LkF6dXJlLkNvc21vcy5TZXJpYWxpemF0aW9uLkh5YnJpZFJvdy5UZXN0cy5Q", + // "ZXJmLkNhc3NhbmRyYUhvdGVsLlByb3RvYnVmYgZwcm90bzM=")); + byte[] descriptorData = System.Convert.FromBase64String(String.Concat( + "CiNUZXN0RGF0YS9DYXNzYW5kcmFIb3RlbFNjaGVtYS5wcm90bxJITWljcm9z", + "b2Z0LkF6dXJlLkNvc21vcy5TZXJpYWxpemF0aW9uLkh5YnJpZFJvdy5UZXN0", + "cy5QZXJmLkNhc3NhbmRyYUhvdGVsGh5nb29nbGUvcHJvdG9idWYvd3JhcHBl", + "cnMucHJvdG8iYgoKUG9zdGFsQ29kZRIoCgN6aXAYASABKAsyGy5nb29nbGUu", + "cHJvdG9idWYuSW50MzJWYWx1ZRIqCgVwbHVzNBgCIAEoCzIbLmdvb2dsZS5w", + "cm90b2J1Zi5JbnQzMlZhbHVlIvsBCgdBZGRyZXNzEiwKBnN0cmVldBgBIAEo", + "CzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRIqCgRjaXR5GAIgASgL", + "MhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEisKBXN0YXRlGAMgASgL", + "MhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEmkKC3Bvc3RhbF9jb2Rl", + "GAQgASgLMlQuTWljcm9zb2Z0LkF6dXJlLkNvc21vcy5TZXJpYWxpemF0aW9u", + "Lkh5YnJpZFJvdy5UZXN0cy5QZXJmLkNhc3NhbmRyYUhvdGVsLlBvc3RhbENv", + "ZGUi9QEKBkhvdGVscxIuCghob3RlbF9pZBgBIAEoCzIcLmdvb2dsZS5wcm90", + "b2J1Zi5TdHJpbmdWYWx1ZRIqCgRuYW1lGAIgASgLMhwuZ29vZ2xlLnByb3Rv", + "YnVmLlN0cmluZ1ZhbHVlEisKBXBob25lGAMgASgLMhwuZ29vZ2xlLnByb3Rv", + "YnVmLlN0cmluZ1ZhbHVlEmIKB2FkZHJlc3MYBCABKAsyUS5NaWNyb3NvZnQu", + "QXp1cmUuQ29zbW9zLlNlcmlhbGl6YXRpb24uSHlicmlkUm93LlRlc3RzLlBl", + "cmYuQ2Fzc2FuZHJhSG90ZWwuQWRkcmVzcyLeAQodQXZhaWxhYmxlX1Jvb21z", + "X0J5X0hvdGVsX0RhdGUSLgoIaG90ZWxfaWQYASABKAsyHC5nb29nbGUucHJv", + "dG9idWYuU3RyaW5nVmFsdWUSKQoEZGF0ZRgCIAEoCzIbLmdvb2dsZS5wcm90", + "b2J1Zi5JbnQ2NFZhbHVlEjAKC3Jvb21fbnVtYmVyGAMgASgLMhsuZ29vZ2xl", + "LnByb3RvYnVmLkludDMyVmFsdWUSMAoMaXNfYXZhaWxhYmxlGAQgASgLMhou", + "Z29vZ2xlLnByb3RvYnVmLkJvb2xWYWx1ZSKfBAoGR3Vlc3RzEi4KCGd1ZXN0", + "X2lkGAEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjAKCmZp", + "cnN0X25hbWUYAiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS", + "LwoJbGFzdF9uYW1lGAMgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1Zh", + "bHVlEisKBXRpdGxlGAQgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1Zh", + "bHVlEg4KBmVtYWlscxgFIAMoCRIVCg1waG9uZV9udW1iZXJzGAYgAygJEnIK", + "CWFkZHJlc3NlcxgHIAMoCzJfLk1pY3Jvc29mdC5BenVyZS5Db3Ntb3MuU2Vy", + "aWFsaXphdGlvbi5IeWJyaWRSb3cuVGVzdHMuUGVyZi5DYXNzYW5kcmFIb3Rl", + "bC5HdWVzdHMuQWRkcmVzc2VzRW50cnkSNAoOY29uZmlybV9udW1iZXIYCCAB", + "KAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUagwEKDkFkZHJlc3Nl", + "c0VudHJ5EgsKA2tleRgBIAEoCRJgCgV2YWx1ZRgCIAEoCzJRLk1pY3Jvc29m", + "dC5BenVyZS5Db3Ntb3MuU2VyaWFsaXphdGlvbi5IeWJyaWRSb3cuVGVzdHMu", + "UGVyZi5DYXNzYW5kcmFIb3RlbC5BZGRyZXNzOgI4AUJUqgJRTWljcm9zb2Z0", + "LkF6dXJlLkNvc21vcy5TZXJpYWxpemF0aW9uLkh5YnJpZFJvdy5UZXN0cy5Q", + "ZXJmLkNhc3NhbmRyYUhvdGVsLlByb3RvYnVmYgZwcm90bzM=")); + descriptor = Google.Protobuf.Reflection.FileDescriptor.FromGeneratedCode(descriptorData, + new Google.Protobuf.Reflection.FileDescriptor[] { Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor }, new Google.Protobuf.Reflection.GeneratedClrTypeInfo(null, new Google.Protobuf.Reflection.GeneratedClrTypeInfo[] { new Google.Protobuf.Reflection.GeneratedClrTypeInfo(PostalCode.class, PostalCode.getParser(), new String[] { "Zip", "Plus4" }, null, null, null), new Google.Protobuf.Reflection.GeneratedClrTypeInfo(Address.class, Address.getParser(), new String[] { "Street", "City", "State", "PostalCode" }, null, null, null), new Google.Protobuf.Reflection.GeneratedClrTypeInfo(Hotels.class, Hotels.getParser(), new String[] { "HotelId", "Name", "Phone", "Address" }, null, null, null), new Google.Protobuf.Reflection.GeneratedClrTypeInfo(Available_Rooms_By_Hotel_Date.class, Available_Rooms_By_Hotel_Date.getParser(), new String[] { "HotelId", "Date", "RoomNumber", "IsAvailable" }, null, null, null), new Google.Protobuf.Reflection.GeneratedClrTypeInfo(Guests.class, Guests.getParser(), new String[] { "GuestId", "FirstName", "LastName", "Title", "Emails", "PhoneNumbers", "Addresses", "ConfirmNumber" }, null, null, new Google.Protobuf.Reflection.GeneratedClrTypeInfo[] { null }) })); + } + + /** + * File descriptor for TestData/CassandraHotelSchema.proto + */ + public static Google.Protobuf.Reflection.FileDescriptor getDescriptor() { + return descriptor; + } + // TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: + ///#endregion + +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Guests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Guests.java new file mode 100644 index 0000000..b19c789 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Guests.java @@ -0,0 +1,445 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf.cassandrahotel.protobuf; + +import com.azure.data.cosmos.serialization.hybridrow.perf.*; + +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: TestData/CassandraHotelSchema.proto +// + +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pb = Google.Protobuf; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbc = Google.Protobuf.Collections; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbr = Google.Protobuf.Reflection; + +public final class Guests implements Google.Protobuf.IMessage { + /** + * Field number for the "addresses" field. + */ + public static final int AddressesFieldNumber = 7; + /** + * Field number for the "confirm_number" field. + */ + public static final int ConfirmNumberFieldNumber = 8; + /** + * Field number for the "emails" field. + */ + public static final int EmailsFieldNumber = 5; + /** + * Field number for the "first_name" field. + */ + public static final int FirstNameFieldNumber = 2; + /** + * Field number for the "guest_id" field. + */ + public static final int GuestIdFieldNumber = 1; + /** + * Field number for the "last_name" field. + */ + public static final int LastNameFieldNumber = 3; + + // TODO: C# TO JAVA CONVERTER: Java does not support 'partial' methods: + // partial void OnConstruction(); + /** + * Field number for the "phone_numbers" field. + */ + public static final int PhoneNumbersFieldNumber = 6; + /** + * Field number for the "title" field. + */ + public static final int TitleFieldNumber = 4; + private static final Google.Protobuf.Collections.MapField.Codec _map_addresses_codec = + new Google.Protobuf.Collections.MapField.Codec(Google.Protobuf.FieldCodec.ForString(10), + Google.Protobuf.FieldCodec.ForMessage(18, + Address.getParser()), 58); + private static final Google.Protobuf.MessageParser _parser = + new Google.Protobuf.MessageParser(() -> new Guests()); + private static final Google.Protobuf.FieldCodec _repeated_emails_codec = + Google.Protobuf.FieldCodec.ForString(42); + private static final Google.Protobuf.FieldCodec _repeated_phoneNumbers_codec = + Google.Protobuf.FieldCodec.ForString(50); + private static final Google.Protobuf.FieldCodec _single_confirmNumber_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(66); + private static final Google.Protobuf.FieldCodec _single_firstName_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(18); + private static final Google.Protobuf.FieldCodec _single_guestId_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(10); + private static final Google.Protobuf.FieldCodec _single_lastName_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(26); + private static final Google.Protobuf.FieldCodec _single_title_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(34); + private final Google.Protobuf.Collections.MapField addresses_ = + new Google.Protobuf.Collections.MapField(); + private final Google.Protobuf.Collections.RepeatedField emails_ = + new Google.Protobuf.Collections.RepeatedField(); + private final Google.Protobuf.Collections.RepeatedField phoneNumbers_ = + new Google.Protobuf.Collections.RepeatedField(); + private Google.Protobuf.UnknownFieldSet _unknownFields; + private String confirmNumber_; + private String firstName_; + private String guestId_; + private String lastName_; + private String title_; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Guests() + public Guests() { + OnConstruction(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Guests(Guests other) + public Guests(Guests other) { + this(); + setGuestId(other.getGuestId()); + setFirstName(other.getFirstName()); + setLastName(other.getLastName()); + setTitle(other.getTitle()); + emails_ = other.emails_.Clone(); + phoneNumbers_ = other.phoneNumbers_.Clone(); + addresses_ = other.addresses_.Clone(); + setConfirmNumber(other.getConfirmNumber()); + _unknownFields = Google.Protobuf.UnknownFieldSet.Clone(other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Google.Protobuf.Collections + // .MapField + // Addresses + public Google.Protobuf.Collections.MapField getAddresses() { + return addresses_; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string ConfirmNumber + public String getConfirmNumber() { + return confirmNumber_; + } + + public void setConfirmNumber(String value) { + confirmNumber_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf.Reflection + // .MessageDescriptor Descriptor + public static Google.Protobuf.Reflection.MessageDescriptor getDescriptor() { + return CassandraHotelSchemaReflection.getDescriptor().MessageTypes[4]; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor + public Google.Protobuf.Reflection getDescriptor() { + return getDescriptor(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Google.Protobuf.Collections + // .RepeatedField Emails + public Google.Protobuf.Collections.RepeatedField getEmails() { + return emails_; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string FirstName + public String getFirstName() { + return firstName_; + } + + public void setFirstName(String value) { + firstName_ = value; + } + + /** + * guid + */ + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string GuestId + public String getGuestId() { + return guestId_; + } + + public void setGuestId(String value) { + guestId_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string LastName + public String getLastName() { + return lastName_; + } + + public void setLastName(String value) { + lastName_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf + // .MessageParser Parser + public static Google.Protobuf.MessageParser getParser() { + return _parser; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Google.Protobuf.Collections + // .RepeatedField PhoneNumbers + public Google.Protobuf.Collections.RepeatedField getPhoneNumbers() { + return phoneNumbers_; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string Title + public String getTitle() { + return title_; + } + + public void setTitle(String value) { + title_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() + public int CalculateSize() { + int size = 0; + if (guestId_ != null) { + size += _single_guestId_codec.CalculateSizeWithTag(getGuestId()); + } + if (firstName_ != null) { + size += _single_firstName_codec.CalculateSizeWithTag(getFirstName()); + } + if (lastName_ != null) { + size += _single_lastName_codec.CalculateSizeWithTag(getLastName()); + } + if (title_ != null) { + size += _single_title_codec.CalculateSizeWithTag(getTitle()); + } + size += emails_.CalculateSize(_repeated_emails_codec); + size += phoneNumbers_.CalculateSize(_repeated_phoneNumbers_codec); + size += addresses_.CalculateSize(_map_addresses_codec); + if (confirmNumber_ != null) { + size += _single_confirmNumber_codec.CalculateSizeWithTag(getConfirmNumber()); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Guests Clone() + public Guests Clone() { + return new Guests(this); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Guests other) + public void MergeFrom(Guests other) { + if (other == null) { + return; + } + if (other.guestId_ != null) { + if (guestId_ == null || !other.getGuestId().equals("")) { + setGuestId(other.getGuestId()); + } + } + if (other.firstName_ != null) { + if (firstName_ == null || !other.getFirstName().equals("")) { + setFirstName(other.getFirstName()); + } + } + if (other.lastName_ != null) { + if (lastName_ == null || !other.getLastName().equals("")) { + setLastName(other.getLastName()); + } + } + if (other.title_ != null) { + if (title_ == null || !other.getTitle().equals("")) { + setTitle(other.getTitle()); + } + } + emails_.Add(other.emails_); + phoneNumbers_.Add(other.phoneNumbers_); + addresses_.Add(other.addresses_); + if (other.confirmNumber_ != null) { + if (confirmNumber_ == null || !other.getConfirmNumber().equals("")) { + setConfirmNumber(other.getConfirmNumber()); + } + } + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Google.Protobuf + // .CodedInputStream input) + public void MergeFrom(Google.Protobuf.CodedInputStream input) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint tag; + int tag; + while ((tag = input.ReadTag()) != 0) { + switch (tag) { + default: + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + String value = _single_guestId_codec.Read(input); + if (guestId_ == null || !value.equals("")) { + setGuestId(value); + } + break; + } + case 18: { + String value = _single_firstName_codec.Read(input); + if (firstName_ == null || !value.equals("")) { + setFirstName(value); + } + break; + } + case 26: { + String value = _single_lastName_codec.Read(input); + if (lastName_ == null || !value.equals("")) { + setLastName(value); + } + break; + } + case 34: { + String value = _single_title_codec.Read(input); + if (title_ == null || !value.equals("")) { + setTitle(value); + } + break; + } + case 42: { + emails_.AddEntriesFrom(input, _repeated_emails_codec); + break; + } + case 50: { + phoneNumbers_.AddEntriesFrom(input, _repeated_phoneNumbers_codec); + break; + } + case 58: { + addresses_.AddEntriesFrom(input, _map_addresses_codec); + break; + } + case 66: { + String value = _single_confirmNumber_codec.Read(input); + if (confirmNumber_ == null || !value.equals("")) { + setConfirmNumber(value); + } + break; + } + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(Google.Protobuf + // .CodedOutputStream output) + public void WriteTo(Google.Protobuf.CodedOutputStream output) { + if (guestId_ != null) { + _single_guestId_codec.WriteTagAndValue(output, getGuestId()); + } + if (firstName_ != null) { + _single_firstName_codec.WriteTagAndValue(output, getFirstName()); + } + if (lastName_ != null) { + _single_lastName_codec.WriteTagAndValue(output, getLastName()); + } + if (title_ != null) { + _single_title_codec.WriteTagAndValue(output, getTitle()); + } + emails_.WriteTo(output, _repeated_emails_codec); + phoneNumbers_.WriteTo(output, _repeated_phoneNumbers_codec); + addresses_.WriteTo(output, _map_addresses_codec); + if (confirmNumber_ != null) { + _single_confirmNumber_codec.WriteTagAndValue(output, getConfirmNumber()); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) + @Override + public boolean equals(Object other) { + return Equals(other instanceof Guests ? (Guests)other : null); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Guests other) + public boolean equals(Guests other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!getGuestId().equals(other.getGuestId())) { + return false; + } + if (!getFirstName().equals(other.getFirstName())) { + return false; + } + if (!getLastName().equals(other.getLastName())) { + return false; + } + if (!getTitle().equals(other.getTitle())) { + return false; + } + if (!emails_.equals(other.emails_)) { + return false; + } + if (!phoneNumbers_.equals(other.phoneNumbers_)) { + return false; + } + if (!getAddresses().equals(other.getAddresses())) { + return false; + } + if (!getConfirmNumber().equals(other.getConfirmNumber())) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() + @Override + public int hashCode() { + int hash = 1; + if (guestId_ != null) { + hash ^= getGuestId().hashCode(); + } + if (firstName_ != null) { + hash ^= getFirstName().hashCode(); + } + if (lastName_ != null) { + hash ^= getLastName().hashCode(); + } + if (title_ != null) { + hash ^= getTitle().hashCode(); + } + hash ^= emails_.hashCode(); + hash ^= phoneNumbers_.hashCode(); + hash ^= getAddresses().hashCode(); + if (confirmNumber_ != null) { + hash ^= getConfirmNumber().hashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.hashCode(); + } + return hash; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() + @Override + public String toString() { + return Google.Protobuf.JsonFormatter.ToDiagnosticString(this); + } + +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Hotels.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Hotels.java new file mode 100644 index 0000000..8444c67 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/Hotels.java @@ -0,0 +1,316 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf.cassandrahotel.protobuf; + +import com.azure.data.cosmos.serialization.hybridrow.perf.*; + +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: TestData/CassandraHotelSchema.proto +// + +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pb = Google.Protobuf; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbc = Google.Protobuf.Collections; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbr = Google.Protobuf.Reflection; + +public final class Hotels implements Google.Protobuf.IMessage { + /** + * Field number for the "address" field. + */ + public static final int AddressFieldNumber = 4; + /** + * Field number for the "hotel_id" field. + */ + public static final int HotelIdFieldNumber = 1; + /** + * Field number for the "name" field. + */ + public static final int NameFieldNumber = 2; + /** + * Field number for the "phone" field. + */ + public static final int PhoneFieldNumber = 3; + private static final Google.Protobuf.MessageParser _parser = + new Google.Protobuf.MessageParser(() -> new Hotels()); + private static final Google.Protobuf.FieldCodec _single_hotelId_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(10); + + // TODO: C# TO JAVA CONVERTER: Java does not support 'partial' methods: + // partial void OnConstruction(); + private static final Google.Protobuf.FieldCodec _single_name_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(18); + private static final Google.Protobuf.FieldCodec _single_phone_codec = + Google.Protobuf.FieldCodec.ForClassWrapper(26); + private Google.Protobuf.UnknownFieldSet _unknownFields; + private Address address_; + private String hotelId_; + private String name_; + private String phone_; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Hotels() + public Hotels() { + OnConstruction(); + } + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Hotels(Hotels other) + public Hotels(Hotels other) { + this(); + setHotelId(other.getHotelId()); + setName(other.getName()); + setPhone(other.getPhone()); + setAddress(other.address_ != null ? other.getAddress().Clone() : null); + _unknownFields = Google.Protobuf.UnknownFieldSet.Clone(other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Microsoft.Azure.Cosmos.Serialization + // .HybridRow.Tests.Perf.CassandraHotel.Protobuf.Address Address + public Address getAddress() { + return address_; + } + + public void setAddress(Address value) { + address_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor + public Google.Protobuf.Reflection getDescriptor() { + return getDescriptor(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf.Reflection + // .MessageDescriptor Descriptor + public static Google.Protobuf.Reflection.MessageDescriptor getDescriptor() { + return CassandraHotelSchemaReflection.getDescriptor().MessageTypes[2]; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string HotelId + public String getHotelId() { + return hotelId_; + } + + public void setHotelId(String value) { + hotelId_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string Name + public String getName() { + return name_; + } + + public void setName(String value) { + name_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf + // .MessageParser Parser + public static Google.Protobuf.MessageParser getParser() { + return _parser; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public string Phone + public String getPhone() { + return phone_; + } + + public void setPhone(String value) { + phone_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() + public int CalculateSize() { + int size = 0; + if (hotelId_ != null) { + size += _single_hotelId_codec.CalculateSizeWithTag(getHotelId()); + } + if (name_ != null) { + size += _single_name_codec.CalculateSizeWithTag(getName()); + } + if (phone_ != null) { + size += _single_phone_codec.CalculateSizeWithTag(getPhone()); + } + if (address_ != null) { + size += 1 + Google.Protobuf.CodedOutputStream.ComputeMessageSize(getAddress()); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Hotels Clone() + public Hotels Clone() { + return new Hotels(this); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Hotels other) + public void MergeFrom(Hotels other) { + if (other == null) { + return; + } + if (other.hotelId_ != null) { + if (hotelId_ == null || !other.getHotelId().equals("")) { + setHotelId(other.getHotelId()); + } + } + if (other.name_ != null) { + if (name_ == null || !other.getName().equals("")) { + setName(other.getName()); + } + } + if (other.phone_ != null) { + if (phone_ == null || !other.getPhone().equals("")) { + setPhone(other.getPhone()); + } + } + if (other.address_ != null) { + if (address_ == null) { + address_ = new Address(); + } + getAddress().MergeFrom(other.getAddress()); + } + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Google.Protobuf + // .CodedInputStream input) + public void MergeFrom(Google.Protobuf.CodedInputStream input) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint tag; + int tag; + while ((tag = input.ReadTag()) != 0) { + switch (tag) { + default: + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + String value = _single_hotelId_codec.Read(input); + if (hotelId_ == null || !value.equals("")) { + setHotelId(value); + } + break; + } + case 18: { + String value = _single_name_codec.Read(input); + if (name_ == null || !value.equals("")) { + setName(value); + } + break; + } + case 26: { + String value = _single_phone_codec.Read(input); + if (phone_ == null || !value.equals("")) { + setPhone(value); + } + break; + } + case 34: { + if (address_ == null) { + address_ = new Address(); + } + input.ReadMessage(address_); + break; + } + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(Google.Protobuf + // .CodedOutputStream output) + public void WriteTo(Google.Protobuf.CodedOutputStream output) { + if (hotelId_ != null) { + _single_hotelId_codec.WriteTagAndValue(output, getHotelId()); + } + if (name_ != null) { + _single_name_codec.WriteTagAndValue(output, getName()); + } + if (phone_ != null) { + _single_phone_codec.WriteTagAndValue(output, getPhone()); + } + if (address_ != null) { + output.WriteRawTag(34); + output.WriteMessage(getAddress()); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) + @Override + public boolean equals(Object other) { + return Equals(other instanceof Hotels ? (Hotels)other : null); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(Hotels other) + public boolean equals(Hotels other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!getHotelId().equals(other.getHotelId())) { + return false; + } + if (!getName().equals(other.getName())) { + return false; + } + if (!getPhone().equals(other.getPhone())) { + return false; + } + if (!getAddress().equals(other.getAddress())) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() + @Override + public int hashCode() { + int hash = 1; + if (hotelId_ != null) { + hash ^= getHotelId().hashCode(); + } + if (name_ != null) { + hash ^= getName().hashCode(); + } + if (phone_ != null) { + hash ^= getPhone().hashCode(); + } + if (address_ != null) { + hash ^= getAddress().hashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.hashCode(); + } + return hash; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() + @Override + public String toString() { + return Google.Protobuf.JsonFormatter.ToDiagnosticString(this); + } + +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/PostalCode.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/PostalCode.java new file mode 100644 index 0000000..b68b80d --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/perf/cassandrahotel/protobuf/PostalCode.java @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.perf.cassandrahotel.protobuf; + +import com.azure.data.cosmos.serialization.hybridrow.perf.*; +import com.google.protobuf.Message; +import com.google.protobuf.Parser; + +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: TestData/CassandraHotelSchema.proto +// + +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pb = Google.Protobuf; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbc = Google.Protobuf.Collections; +//C# TO JAVA CONVERTER NOTE: There is no Java equivalent to C# namespace aliases: +//using pbr = Google.Protobuf.Reflection; + +public final class PostalCode implements Message { + /** + * Field number for the "plus4" field. + */ + public static final int Plus4FieldNumber = 2; + /** + * Field number for the "zip" field. + */ + public static final int ZipFieldNumber = 1; + private static final Parser _parser = new Parser(() -> new PostalCode()); + private static final Google.Protobuf.FieldCodec _single_plus4_codec = + Google.Protobuf.FieldCodec.ForStructWrapper(18); + private static final Google.Protobuf.FieldCodec _single_zip_codec = + Google.Protobuf.FieldCodec.ForStructWrapper(10); + private Google.Protobuf.UnknownFieldSet _unknownFields; + + // TODO: C# TO JAVA CONVERTER: Java does not support 'partial' methods: + // partial void OnConstruction(); + private Integer plus4_; + private Integer zip_; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public PostalCode() + public PostalCode() { + OnConstruction(); + } + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public PostalCode(PostalCode other) + public PostalCode(PostalCode other) { + this(); + setZip(other.getZip()); + setPlus4(other.getPlus4()); + _unknownFields = Google.Protobuf.UnknownFieldSet.Clone(other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf.Reflection + // .MessageDescriptor Descriptor + public static Google.Protobuf.Reflection.MessageDescriptor getDescriptor() { + return CassandraHotelSchemaReflection.getDescriptor().MessageTypes[0]; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] pbr::MessageDescriptor pb::IMessage.Descriptor + public Google.Protobuf.Reflection getDescriptor() { + return getDescriptor(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public static Google.Protobuf + // .MessageParser Parser + public static Google.Protobuf.MessageParser getParser() { + return _parser; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Nullable Plus4 + public Integer getPlus4() { + return plus4_; + } + + public void setPlus4(Integer value) { + plus4_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public Nullable Zip + public Integer getZip() { + return zip_; + } + + public void setZip(Integer value) { + zip_ = value; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public int CalculateSize() + public int CalculateSize() { + int size = 0; + if (zip_ != null) { + size += _single_zip_codec.CalculateSizeWithTag(getZip()); + } + if (plus4_ != null) { + size += _single_plus4_codec.CalculateSizeWithTag(getPlus4()); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public PostalCode Clone() + public PostalCode Clone() { + return new PostalCode(this); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(PostalCode other) + public void MergeFrom(PostalCode other) { + if (other == null) { + return; + } + if (other.zip_ != null) { + if (zip_ == null || other.getZip() != 0) { + setZip(other.getZip()); + } + } + if (other.plus4_ != null) { + if (plus4_ == null || other.getPlus4() != 0) { + setPlus4(other.getPlus4()); + } + } + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void MergeFrom(Google.Protobuf + // .CodedInputStream input) + public void MergeFrom(Google.Protobuf.CodedInputStream input) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint tag; + int tag; + while ((tag = input.ReadTag()) != 0) { + switch (tag) { + default: + _unknownFields = Google.Protobuf.UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Integer value = _single_zip_codec.Read(input); + if (zip_ == null || value != 0) { + setZip(value); + } + break; + } + case 18: { + Integer value = _single_plus4_codec.Read(input); + if (plus4_ == null || value != 0) { + setPlus4(value); + } + break; + } + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public void WriteTo(Google.Protobuf + // .CodedOutputStream output) + public void WriteTo(Google.Protobuf.CodedOutputStream output) { + if (zip_ != null) { + _single_zip_codec.WriteTagAndValue(output, getZip()); + } + if (plus4_ != null) { + _single_plus4_codec.WriteTagAndValue(output, getPlus4()); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override bool Equals(object other) + @Override + public boolean equals(Object other) { + return Equals(other instanceof PostalCode ? (PostalCode)other : null); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public bool Equals(PostalCode other) + public boolean equals(PostalCode other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (getZip() != other.getZip()) { + return false; + } + if (getPlus4() != other.getPlus4()) { + return false; + } + return Equals(_unknownFields, other._unknownFields); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override int GetHashCode() + @Override + public int hashCode() { + int hash = 1; + if (zip_ != null) { + hash ^= getZip().hashCode(); + } + if (plus4_ != null) { + hash ^= getPlus4().hashCode(); + } + if (_unknownFields != null) { + hash ^= _unknownFields.hashCode(); + } + return hash; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [System.Diagnostics.DebuggerNonUserCodeAttribute] public override string ToString() + @Override + public String toString() { + return Google.Protobuf.JsonFormatter.ToDiagnosticString(this); + } + +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ArrayAssert.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ArrayAssert.java new file mode 100644 index 0000000..f41294d --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ArrayAssert.java @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +public final class ArrayAssert { + public static void AreEqual(T[] expected, T[] actual) { + if (expected == null) { + assert actual == null; + return; + } + + assert actual != null; + assert expected.length == actual.length; + for (int i = 0; i < expected.length; i++) { + assert expected[i] == actual[i]; + } + } + + public static void AreEqual(T[] expected, T[] actual, String message) { + if (expected == null) { + Assert.IsNull(actual, message); + return; + } + + Assert.IsNotNull(actual, message); + Assert.AreEqual(expected.length, actual.length, message); + for (int i = 0; i < expected.length; i++) { + Assert.AreEqual(expected[i], actual[i], message); + } + } + + public static void AreEqual(T[] expected, T[] actual, String message, Object... parameters) { + if (expected == null) { + Assert.IsNull(actual, message, parameters); + return; + } + + Assert.IsNotNull(actual, message, parameters); + Assert.AreEqual(expected.length, actual.length, message, parameters); + for (int i = 0; i < expected.length; i++) { + Assert.AreEqual(expected[i], actual[i], message, parameters); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/AssertThrowsException.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/AssertThrowsException.java new file mode 100644 index 0000000..0698ec2 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/AssertThrowsException.java @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +public final class AssertThrowsException { + /** + * Safely converts an object to a string, handling null values and null characters. Null + * values are converted to "(null)". Null characters are converted to "\\0". + * + * @param input The object to convert to a string. + * @return The converted string. + */ + public static String ReplaceNulls(Object input) { + String input1 = input == null ? null : input.toString(); + if (input1 == null) { + return "(null)"; + } + return Assert.ReplaceNullChars(input1); + } + + /** + * Tests whether the code specified by delegate throws exact given + * exception of type (and not of derived type) and throws + * AssertFailedException + * if code does not throws exception or throws exception of type other than + * . + * + * @param action Delegate to code to be tested and which is expected to throw exception. + * @param message The message to include in the exception when does + * not throws exception of type . + * + * Type of exception expected to be thrown. + * @return The exception that was thrown. + * @throws T:Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException Thrown if + * does + * not throws exception of type + * . + */ + public static T ThrowsException(tangible.Action0Param action, String message) { + return AssertThrowsException.ThrowsException(action, message, null); + } + + /** + * Tests whether the code specified by delegate throws exact given + * exception of type (and not of derived type) and throws + * AssertFailedException + * if code does not throws exception or throws exception of type other than + * . + * + * @param action Delegate to code to be tested and which is expected to throw exception. + * @param message The message to include in the exception when does + * not throws exception of type . + * @param parameters An array of parameters to use when formatting . + * Type of exception expected to be thrown. + * @return The exception that was thrown. + * @throws T:Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException Thrown if + * does + * not throws exception of type + * . + */ + public static T ThrowsException(tangible.Action0Param action, String message, + Object... parameters) { + if (action == null) { + throw new NullPointerException("action"); + } + + if (message == null) { + throw new NullPointerException("message"); + } + + try { + action.invoke(); + } catch (RuntimeException ex) { + if (T.class != ex.getClass()) { + Assert.Fail(String.format("Threw exception %3$s, but exception %2$s was expected. %1$s\nException " + + "Message: %4$s\nStack Trace: %5$s", AssertThrowsException.ReplaceNulls(message), + (Object)T.class.Name, ex.getClass().getSimpleName(), ex.getMessage(), + (Object)ex.StackTrace), parameters); + } + + return (T)ex; + } + + Assert.Fail(String.format("No exception thrown. %2$s exception was expected. %1$s", + AssertThrowsException.ReplaceNulls(message), T.class.Name), parameters); + + return null; + } + + /** + * Tests whether the code specified by delegate throws exact given + * exception of type (and not of derived type) and throws + * AssertFailedException + * if code does not throws exception or throws exception of type other than + * . + * + * @param action Delegate to code to be tested and which is expected to throw exception. + * Type of exception expected to be thrown. + * @return The exception that was thrown. + * @throws T:Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException Thrown if + * does + * not throws exception of type + * . + */ + public static T ThrowsException(tangible.Action0Param action) { + return AssertThrowsException.ThrowsException(action, "", null); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CrossVersioningUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CrossVersioningUnitTests.java new file mode 100644 index 0000000..f35ab8e --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CrossVersioningUnitTests.java @@ -0,0 +1,614 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import Newtonsoft.Json.*; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; + +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Public Fields + + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("Naming", "DontUseVarForVariableTypes", Justification = "The types here +// are anonymous.")][DeploymentItem(CrossVersioningUnitTests.SchemaFile, "TestData")][DeploymentItem +// (CrossVersioningUnitTests.ExpectedFile, "TestData")] public sealed class CrossVersioningUnitTests +public final class CrossVersioningUnitTests { + private static final String ExpectedFile = "TestData\\CrossVersioningExpected.json"; + private static final LocalDateTime SampleDateTime = LocalDateTime.parse("2018-08-14 02:05:00.0000000"); + private static final Float128 SampleFloat128 = new Float128(0, 42); + private static final UUID SampleGuid = UUID.fromString("{2A9C25B9-922E-4611-BB0A-244A9496503C}"); + private static final MongoDbObjectId SampleMongoDbObjectId = new MongoDbObjectId(704643072, 0); // 42 in big-endian + private static final UnixDateTime SampleUnixDateTime = new UnixDateTime(42); + private static final String SchemaFile = "TestData\\CrossVersioningSchema.json"; + private Expected expected; + private LayoutResolver resolver; + private Namespace schema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][SuppressMessage("StyleCop.CSharp.ReadabilityRules", + // "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Test code.")] public void CrossVersionDeleteSparse() + public void CrossVersionDeleteSparse() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Sparse")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.ReadFrom(this.resolver, + this.expected.getCrossVersionSparse()); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool", value:true) + d.LayoutCodeSwitch("int8", value:(byte)-86) + d.LayoutCodeSwitch("int16", value:(short)-21846) + d.LayoutCodeSwitch("int32", value:-1431655766) + d.LayoutCodeSwitch("int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("float128", value:CrossVersioningUnitTests.SampleFloat128) + d.LayoutCodeSwitch("decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("datetime", value:CrossVersioningUnitTests.SampleDateTime) + d.LayoutCodeSwitch("unixdatetime", value:CrossVersioningUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("guid", value:CrossVersioningUnitTests.SampleGuid) + d.LayoutCodeSwitch("mongodbobjectid", value:CrossVersioningUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + d.LayoutCodeSwitch("array_t", value:new byte[] { -86, -86, -86 }) + d.LayoutCodeSwitch("array_t>", value:new float[][] + { + new float[] { 1, 2, 3 }, + new float[] { 1, 2, 3 } + }) + d.LayoutCodeSwitch("array_t", value:new String[] { "abc", "def", "hij" }) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(-6148914691236517206L, -6148914691236517206L)) + d.LayoutCodeSwitch("tuple>", value: + Tuple.Create(NullValue.DEFAULT, Tuple.Create((byte)-86, (byte)-86))) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(false, new Point(1, 2))) + d.LayoutCodeSwitch("set_t", value:new String[] { "abc", "efg", "xzy" }) + d.LayoutCodeSwitch("set_t>", value:new byte[][] + { + new byte[] { 1, 2, 3 }, + new byte[] { 4, 5, 6 }, + new byte[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t>", value:new int[][] + { + new int[] { 1, 2, 3 }, + new int[] { 4, 5, 6 }, + new int[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t", value:new Point[] + { + new Point(1, 2), + new Point(3, 4), + new Point(5, 6) + }) + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create("Mark", "Luke"), Tuple.Create("Harrison", "Han") }) + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((byte)1, new byte[] { 1, 2, 3 }), Tuple.Create((byte)2, + new byte[] { 4, 5, 6 }) }) + + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((short)1, new System.Tuple[] { Tuple.Create(1, 2), + Tuple.Create(3, 4) }), Tuple.Create((short)2, new System.Tuple[] { Tuple.Create(5, 6), + Tuple.Create(7, 8) }) }) + + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create(1.0, new Point(1, 2)), Tuple.Create(2.0, new Point(3, 4)), + Tuple.Create(3.0, new Point(5, 6)) }) + + assert this.expected.getCrossVersionNullSparse() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionReadFixed() + public void CrossVersionReadFixed() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Fixed")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.ReadFrom(this.resolver, + this.expected.getCrossVersionFixed()); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool", value:true) + d.LayoutCodeSwitch("int8", value:(byte)-86) + d.LayoutCodeSwitch("int16", value:(short)-21846) + d.LayoutCodeSwitch("int32", value:-1431655766) + d.LayoutCodeSwitch("int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("float128", value:CrossVersioningUnitTests.SampleFloat128) + d.LayoutCodeSwitch("decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("datetime", value:CrossVersioningUnitTests.SampleDateTime) + d.LayoutCodeSwitch("unixdatetime", value:CrossVersioningUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("guid", value:CrossVersioningUnitTests.SampleGuid) + d.LayoutCodeSwitch("mongodbobjectid", value:CrossVersioningUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionReadNullFixed() + public void CrossVersionReadNullFixed() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Fixed")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool"); + d.LayoutCodeSwitch("int8"); + d.LayoutCodeSwitch("int16"); + d.LayoutCodeSwitch("int32"); + d.LayoutCodeSwitch("int64"); + d.LayoutCodeSwitch("uint8"); + d.LayoutCodeSwitch("uint16"); + d.LayoutCodeSwitch("uint32"); + d.LayoutCodeSwitch("uint64"); + d.LayoutCodeSwitch("float32"); + d.LayoutCodeSwitch("float64"); + d.LayoutCodeSwitch("float128"); + d.LayoutCodeSwitch("decimal"); + d.LayoutCodeSwitch("datetime"); + d.LayoutCodeSwitch("unixdatetime"); + d.LayoutCodeSwitch("guid"); + d.LayoutCodeSwitch("mongodbobjectid"); + d.LayoutCodeSwitch("utf8"); + d.LayoutCodeSwitch("binary"); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionReadNullSparse() + public void CrossVersionReadNullSparse() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Sparse")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.ReadFrom(this.resolver, + this.expected.getCrossVersionNullSparse()); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool"); + d.LayoutCodeSwitch("int8"); + d.LayoutCodeSwitch("int16"); + d.LayoutCodeSwitch("int32"); + d.LayoutCodeSwitch("int64"); + d.LayoutCodeSwitch("uint8"); + d.LayoutCodeSwitch("uint16"); + d.LayoutCodeSwitch("uint32"); + d.LayoutCodeSwitch("uint64"); + d.LayoutCodeSwitch("float32"); + d.LayoutCodeSwitch("float64"); + d.LayoutCodeSwitch("float128"); + d.LayoutCodeSwitch("decimal"); + d.LayoutCodeSwitch("datetime"); + d.LayoutCodeSwitch("unixdatetime"); + d.LayoutCodeSwitch("guid"); + d.LayoutCodeSwitch("mongodbobjectid"); + d.LayoutCodeSwitch("utf8"); + d.LayoutCodeSwitch("binary"); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionReadNullVariable() + public void CrossVersionReadNullVariable() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Variable")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + d.LayoutCodeSwitch("varint"); + d.LayoutCodeSwitch("varuint"); + d.LayoutCodeSwitch("utf8"); + d.LayoutCodeSwitch("binary"); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][SuppressMessage("StyleCop.CSharp.ReadabilityRules", + // "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Test code.")] public void CrossVersionReadSparse() + public void CrossVersionReadSparse() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Sparse")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.ReadFrom(this.resolver, + this.expected.getCrossVersionSparse()); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool", value:true) + d.LayoutCodeSwitch("int8", value:(byte)-86) + d.LayoutCodeSwitch("int16", value:(short)-21846) + d.LayoutCodeSwitch("int32", value:-1431655766) + d.LayoutCodeSwitch("int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("float128", value:CrossVersioningUnitTests.SampleFloat128) + d.LayoutCodeSwitch("decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("datetime", value:CrossVersioningUnitTests.SampleDateTime) + d.LayoutCodeSwitch("unixdatetime", value:CrossVersioningUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("guid", value:CrossVersioningUnitTests.SampleGuid) + d.LayoutCodeSwitch("mongodbobjectid", value:CrossVersioningUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + d.LayoutCodeSwitch("array_t", value:new byte[] { -86, -86, -86 }) + d.LayoutCodeSwitch("array_t>", value:new float[][] + { + new float[] { 1, 2, 3 }, + new float[] { 1, 2, 3 } + }) + d.LayoutCodeSwitch("array_t", value:new String[] { "abc", "def", "hij" }) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(-6148914691236517206L, -6148914691236517206L)) + d.LayoutCodeSwitch("tuple>", value: + Tuple.Create(NullValue.DEFAULT, Tuple.Create((byte)-86, (byte)-86))) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(false, new Point(1, 2))) + d.LayoutCodeSwitch("set_t", value:new String[] { "abc", "efg", "xzy" }) + d.LayoutCodeSwitch("set_t>", value:new byte[][] + { + new byte[] { 1, 2, 3 }, + new byte[] { 4, 5, 6 }, + new byte[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t>", value:new int[][] + { + new int[] { 1, 2, 3 }, + new int[] { 4, 5, 6 }, + new int[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t", value:new Point[] + { + new Point(1, 2), + new Point(3, 4), + new Point(5, 6) + }) + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create("Mark", "Luke"), Tuple.Create("Harrison", "Han") }) + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((byte)1, new byte[] { 1, 2, 3 }), Tuple.Create((byte)2, + new byte[] { 4, 5, 6 }) }) + + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((short)1, new System.Tuple[] { Tuple.Create(1, 2), + Tuple.Create(3, 4) }), Tuple.Create((short)2, new System.Tuple[] { Tuple.Create(5, 6), + Tuple.Create(7, 8) }) }) + + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create(2.0, new Point(3, 4)), Tuple.Create(3.0, new Point(5, 6)), + Tuple.Create(1.0, new Point(1, 2)) }) + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionReadVariable() + public void CrossVersionReadVariable() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Variable")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.ReadFrom(this.resolver, + this.expected.getCrossVersionVariable()); + d.LayoutCodeSwitch("varint", value:-6148914691236517206L) + d.LayoutCodeSwitch("varuint", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionWriteFixed() + public void CrossVersionWriteFixed() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Fixed")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool", value:true) + d.LayoutCodeSwitch("int8", value:(byte)-86) + d.LayoutCodeSwitch("int16", value:(short)-21846) + d.LayoutCodeSwitch("int32", value:-1431655766) + d.LayoutCodeSwitch("int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("float128", value:CrossVersioningUnitTests.SampleFloat128) + d.LayoutCodeSwitch("decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("datetime", value:CrossVersioningUnitTests.SampleDateTime) + d.LayoutCodeSwitch("unixdatetime", value:CrossVersioningUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("guid", value:CrossVersioningUnitTests.SampleGuid) + d.LayoutCodeSwitch("mongodbobjectid", value:CrossVersioningUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + + assert this.expected.getCrossVersionFixed() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionWriteNullFixed() + public void CrossVersionWriteNullFixed() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Fixed")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + assert this.expected.getCrossVersionNullFixed() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionWriteNullSparse() + public void CrossVersionWriteNullSparse() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Sparse")).SchemaId); + assert layout != null; + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + assert this.expected.getCrossVersionNullSparse() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionWriteNullVariable() + public void CrossVersionWriteNullVariable() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Variable")).SchemaId); + assert layout != null; + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + assert this.expected.getCrossVersionNullVariable() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][SuppressMessage("StyleCop.CSharp.ReadabilityRules", + // "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Test code.")] public void CrossVersionWriteSparse() + public void CrossVersionWriteSparse() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Sparse")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool", value:true) + d.LayoutCodeSwitch("int8", value:(byte)-86) + d.LayoutCodeSwitch("int16", value:(short)-21846) + d.LayoutCodeSwitch("int32", value:-1431655766) + d.LayoutCodeSwitch("int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("float128", value:CrossVersioningUnitTests.SampleFloat128) + d.LayoutCodeSwitch("decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("datetime", value:CrossVersioningUnitTests.SampleDateTime) + d.LayoutCodeSwitch("unixdatetime", value:CrossVersioningUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("guid", value:CrossVersioningUnitTests.SampleGuid) + d.LayoutCodeSwitch("mongodbobjectid", value:CrossVersioningUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + d.LayoutCodeSwitch("array_t", value:new byte[] { -86, -86, -86 }) + d.LayoutCodeSwitch("array_t>", value:new float[][] + { + new float[] { 1, 2, 3 }, + new float[] { 1, 2, 3 } + }) + d.LayoutCodeSwitch("array_t", value:new String[] { "abc", "def", "hij" }) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(-6148914691236517206L, -6148914691236517206L)) + d.LayoutCodeSwitch("tuple>", value: + Tuple.Create(NullValue.DEFAULT, Tuple.Create((byte)-86, (byte)-86))) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(false, new Point(1, 2))) + d.LayoutCodeSwitch("set_t", value:new String[] { "abc", "efg", "xzy" }) + d.LayoutCodeSwitch("set_t>", value:new byte[][] + { + new byte[] { 1, 2, 3 }, + new byte[] { 4, 5, 6 }, + new byte[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t>", value:new int[][] + { + new int[] { 1, 2, 3 }, + new int[] { 4, 5, 6 }, + new int[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t", value:new Point[] + { + new Point(1, 2), + new Point(3, 4), + new Point(5, 6) + }) + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create("Mark", "Luke"), Tuple.Create("Harrison", "Han") }) + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((byte)1, new byte[] { 1, 2, 3 }), Tuple.Create((byte)2, + new byte[] { 4, 5, 6 }) }) + + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((short)1, new System.Tuple[] { Tuple.Create(1, 2), + Tuple.Create(3, 4) }), Tuple.Create((short)2, new System.Tuple[] { Tuple.Create(5, 6), + Tuple.Create(7, 8) }) }) + + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create(1.0, new Point(1, 2)), Tuple.Create(2.0, new Point(3, 4)), + Tuple.Create(3.0, new Point(5, 6)) }) + + assert this.expected.getCrossVersionSparse() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CrossVersionWriteVariable() + public void CrossVersionWriteVariable() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Variable")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + d.LayoutCodeSwitch("varint", value:-6148914691236517206L) + d.LayoutCodeSwitch("varuint", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("utf8", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + + assert this.expected.getCrossVersionVariable() == d.RowToHex(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespace() + public void ParseNamespace() { + String json = Files.readString(CrossVersioningUnitTests.SchemaFile); + this.schema = Namespace.Parse(json); + json = Files.readString(CrossVersioningUnitTests.ExpectedFile); + this.expected = JsonConvert.DeserializeObject(json); + this.resolver = new LayoutResolverNamespace(this.schema); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses", Justification = "Instantiated through Reflection.")] private sealed class Expected + private final static class Expected { + private String CrossVersionFixed; + private String CrossVersionNullFixed; + private String CrossVersionNullSparse; + private String CrossVersionNullVariable; + private String CrossVersionSparse; + private String CrossVersionVariable; + + public String getCrossVersionFixed() { + return CrossVersionFixed; + } + + public void setCrossVersionFixed(String value) { + CrossVersionFixed = value; + } + + public String getCrossVersionNullFixed() { + return CrossVersionNullFixed; + } + + public void setCrossVersionNullFixed(String value) { + CrossVersionNullFixed = value; + } + + public String getCrossVersionNullSparse() { + return CrossVersionNullSparse; + } + + public void setCrossVersionNullSparse(String value) { + CrossVersionNullSparse = value; + } + + public String getCrossVersionNullVariable() { + return CrossVersionNullVariable; + } + + public void setCrossVersionNullVariable(String value) { + CrossVersionNullVariable = value; + } + + public String getCrossVersionSparse() { + return CrossVersionSparse; + } + + public void setCrossVersionSparse(String value) { + CrossVersionSparse = value; + } + + public String getCrossVersionVariable() { + return CrossVersionVariable; + } + + public void setCrossVersionVariable(String value) { + CrossVersionVariable = value; + } + } + + private final static class Point implements IDispatchable { + public int X; + public int Y; + + public Point(int x, int y) { + this.X = x; + this.Y = y; + } + + public void Dispatch(Reference dispatcher, Reference scope) { + dispatcher.get().LayoutCodeSwitch(scope, "x", value:this.X) + dispatcher.get().LayoutCodeSwitch(scope, "y", value:this.Y) + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof null) + { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Point; + Point point = tempVar ? (Point)obj : null; + return tempVar && this.equals(point); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + return ((new Integer(this.X)).hashCode() * 397) ^ (new Integer(this.Y)).hashCode(); + } + } + + private boolean equals(Point other) { + return this.X == other.X && this.Y == other.Y; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CustomerExampleUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CustomerExampleUnitTests.java new file mode 100644 index 0000000..df139bf --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/CustomerExampleUnitTests.java @@ -0,0 +1,892 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; +import com.azure.data.cosmos.serialization.hybridrow.unit.customerschema.Hotel; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.TreeSet; +import java.util.UUID; + +// ReSharper disable once StringLiteralTypo +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("Naming", "DontUseVarForVariableTypes", Justification = "The types here +// are anonymous.")][DeploymentItem("TestData\\CustomerSchema.json", "TestData")] public sealed class +// CustomerExampleUnitTests +public final class CustomerExampleUnitTests { + + private final Hotel hotelExample = new Hotel() { + Id = "The-Westin-St-John-Resort-Villas-1187", + Name ="The Westin St. John Resort Villas", + Phone ="+1 340-693-8000", + Address = new Address { + Street = "300B Chocolate Hole", City = "Great Cruz Bay", State = "VI", PostalCode = new PostalCode { + Zip = 00830, Plus4 = 0001 + } + } + }; + + private LayoutResolver customerResolver; + private Namespace customerSchema; + private Layout guestLayout; + private Layout hotelLayout; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateGuest() + public void CreateGuest() { + RowBuffer row = new RowBuffer(1024 * 1024); + row.initLayout(HybridRowVersion.V1, this.guestLayout, this.customerResolver); + + Guest g1 = new Guest(); + g1.Id = UUID.fromString("64d9d6d3-fd6b-4556-8c6e-d960a7ece7b9"); + g1.FirstName = "John"; + g1.LastName = "Adams"; + g1.Title = "President of the United States"; + g1.PhoneNumbers = new ArrayList(Arrays.asList("(202) 456-1111")); + g1.ConfirmNumber = "(202) 456-1111"; + g1.Emails = new TreeSet { + "president@whitehouse.gov" + } + Address tempVar = new Address(); + tempVar.setStreet("1600 Pennsylvania Avenue NW"); + tempVar.setCity("Washington, D.C."); + tempVar.setState("DC"); + PostalCode tempVar2 = new PostalCode(); + tempVar2.setZip(20500); + tempVar2.setPlus4(0001); + tempVar.setPostalCode(tempVar2); + g1.Addresses = new HashMap(Map.ofEntries(Map.entry("home", tempVar))); + + Reference tempReference_row = + new Reference(row); + RowCursor rc1 = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + Reference tempReference_row2 = + new Reference(row); + Reference tempReference_rc1 = + new Reference(rc1); + this.WriteGuest(tempReference_row2, tempReference_rc1, g1); + rc1 = tempReference_rc1.get(); + row = tempReference_row2.get(); + Reference tempReference_row3 = + new Reference(row); + RowCursor rc2 = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + Reference tempReference_rc2 = + new Reference(rc2); + Guest g2 = this.ReadGuest(tempReference_row4, tempReference_rc2); + rc2 = tempReference_rc2.get(); + row = tempReference_row4.get(); + assert g1 == g2; + + // Append an item to an existing list. + Reference tempReference_row5 = + new Reference(row); + RowCursor rc3 = RowCursor.create(tempReference_row5); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_rc3 = + new Reference(rc3); + int index = this.AppendGuestEmail(tempReference_row6, tempReference_rc3, "vice_president@whitehouse.gov"); + rc3 = tempReference_rc3.get(); + row = tempReference_row6.get(); + assert 1 == index; + g1.Emails.add("vice_president@whitehouse.gov"); + Reference tempReference_row7 = + new Reference(row); + RowCursor rc4 = RowCursor.create(tempReference_row7); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + Reference tempReference_rc4 = + new Reference(rc4); + g2 = this.ReadGuest(tempReference_row8, tempReference_rc4); + rc4 = tempReference_rc4.get(); + row = tempReference_row8.get(); + assert g1 == g2; + + // Prepend an item to an existing list. + Reference tempReference_row9 = + new Reference(row); + RowCursor rc5 = RowCursor.create(tempReference_row9); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + Reference tempReference_rc5 = + new Reference(rc5); + index = this.PrependGuestEmail(tempReference_row10, tempReference_rc5, "ex_president@whitehouse.gov"); + rc5 = tempReference_rc5.get(); + row = tempReference_row10.get(); + assert 0 == index; + g1.Emails = new TreeSet { + "ex_president@whitehouse.gov", "president@whitehouse.gov", "vice_president@whitehouse.gov" + } + Reference tempReference_row11 = + new Reference(row); + RowCursor rc6 = RowCursor.create(tempReference_row11); + row = tempReference_row11.get(); + Reference tempReference_row12 = + new Reference(row); + Reference tempReference_rc6 = + new Reference(rc6); + g2 = this.ReadGuest(tempReference_row12, tempReference_rc6); + rc6 = tempReference_rc6.get(); + row = tempReference_row12.get(); + assert g1 == g2; + + // InsertAt an item to an existing list. + Reference tempReference_row13 = + new Reference(row); + RowCursor rc7 = RowCursor.create(tempReference_row13); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + Reference tempReference_rc7 = + new Reference(rc7); + index = this.InsertAtGuestEmail(tempReference_row14, tempReference_rc7, 1, "future_president@whitehouse.gov"); + rc7 = tempReference_rc7.get(); + row = tempReference_row14.get(); + assert 1 == index; + g1.Emails = new TreeSet { + "ex_president@whitehouse.gov", "future_president@whitehouse.gov", "president@whitehouse.gov", + "vice_president@whitehouse.gov" + } + + Reference tempReference_row15 = + new Reference(row); + RowCursor rc8 = RowCursor.create(tempReference_row15); + row = tempReference_row15.get(); + Reference tempReference_row16 = + new Reference(row); + Reference tempReference_rc8 = + new Reference(rc8); + g2 = this.ReadGuest(tempReference_row16, tempReference_rc8); + rc8 = tempReference_rc8.get(); + row = tempReference_row16.get(); + assert g1 == g2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateHotel() + public void CreateHotel() { + RowBuffer row = new RowBuffer(0); + row.initLayout(HybridRowVersion.V1, this.hotelLayout, this.customerResolver); + + Hotel h1 = this.hotelExample; + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + Reference tempReference_row2 = + new Reference(row); + Reference tempReference_root = + new Reference(root); + this.WriteHotel(tempReference_row2, tempReference_root, h1); + root = tempReference_root.get(); + row = tempReference_row2.get(); + + Reference tempReference_row3 = + new Reference(row); + root = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + Reference tempReference_root2 = + new Reference(root); + Hotel h2 = this.ReadHotel(tempReference_row4, tempReference_root2); + root = tempReference_root2.get(); + row = tempReference_row4.get(); + + assert h1 == h2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void FrozenHotel() + public void FrozenHotel() { + RowBuffer row = new RowBuffer(0); + row.initLayout(HybridRowVersion.V1, this.hotelLayout, this.customerResolver); + + Hotel h1 = this.hotelExample; + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + Reference tempReference_row2 = + new Reference(row); + Reference tempReference_root = + new Reference(root); + this.WriteHotel(tempReference_row2, tempReference_root, h1); + root = tempReference_root.get(); + row = tempReference_row2.get(); + + Reference tempReference_row3 = + new Reference(row); + root = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + Address tempVar = new Address(); + tempVar.setStreet("300B Brownie Way"); + Reference tempReference_row4 = + new Reference(row); + Reference tempReference_root2 = + new Reference(root); + ResultAssert.InsufficientPermissions(this.PartialUpdateHotelAddress(tempReference_row4, tempReference_root2, tempVar)); + root = tempReference_root2.get(); + row = tempReference_row4.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString("TestData\\CustomerSchema.json"); + this.customerSchema = Namespace.Parse(json); + this.customerResolver = new LayoutResolverNamespace(this.customerSchema); + this.hotelLayout = this.customerResolver.Resolve(tangible.ListHelper.find(this.customerSchema.getSchemas(), + x -> x.Name.equals("Hotels")).SchemaId); + this.guestLayout = this.customerResolver.Resolve(tangible.ListHelper.find(this.customerSchema.getSchemas(), + x -> x.Name.equals("Guests")).SchemaId); + } + + private int AppendGuestEmail(Reference row, Reference root, String email) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("emails", out c); + root.get().Find(row, c.Path); + RowCursor emailScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().ReadScope(row, root, out emailScope)); + assert !emailScope.MoveTo(row, Integer.MAX_VALUE); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref emailScope, email)); + return emailScope.Index; + } + + private int InsertAtGuestEmail(Reference row, Reference root, int i, + String email) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("emails", out c); + root.get().Find(row, c.Path); + RowCursor emailScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().ReadScope(row, root, out emailScope)); + assert emailScope.MoveTo(row, i); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref emailScope, email, + UpdateOptions.InsertAt)); + return emailScope.Index; + } + + private Result PartialUpdateHotelAddress(Reference row, Reference root, + Address a) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("address", out c); + root.get().Find(row, c.Path); + RowCursor addressScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Result r = c.TypeAs().ReadScope(row, root, out addressScope); + if (r != Result.SUCCESS) { + return r; + } + + Layout addressLayout = addressScope.Layout; + if (a.Street != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert addressLayout.TryFind("street", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = c.TypeAs().WriteVariable(row, ref addressScope, c, a.Street); + if (r != Result.SUCCESS) { + return r; + } + } + + if (a.City != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert addressLayout.TryFind("city", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = c.TypeAs().WriteVariable(row, ref addressScope, c, a.City); + if (r != Result.SUCCESS) { + return r; + } + } + + if (a.State != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert addressLayout.TryFind("state", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = c.TypeAs().WriteFixed(row, ref addressScope, c, a.State); + if (r != Result.SUCCESS) { + return r; + } + } + + if (a.PostalCode != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert addressLayout.TryFind("postal_code", out c); + addressScope.Find(row, c.Path); + RowCursor postalCodeScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = c.TypeAs().WriteScope(row, ref addressScope, c.TypeArgs, out postalCodeScope); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_postalCodeScope = + new Reference(postalCodeScope); + this.WritePostalCode(row, tempReference_postalCodeScope, c.TypeArgs, a.PostalCode); + postalCodeScope = tempReference_postalCodeScope.get(); + } + + return Result.SUCCESS; + } + + private int PrependGuestEmail(Reference row, Reference root, String email) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("emails", out c); + root.get().Find(row, c.Path); + RowCursor emailScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().ReadScope(row, root, out emailScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref emailScope, email, + UpdateOptions.InsertAt)); + return emailScope.Index; + } + + private static Address ReadAddress(Reference row, Reference addressScope) { + Address a = new Address(); + Layout addressLayout = addressScope.get().getLayout(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("street", out c); + Out tempOut_Street = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, addressScope, c, tempOut_Street)); + a.Street = tempOut_Street.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("city", out c); + Out tempOut_City = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, addressScope, c, tempOut_City)); + a.City = tempOut_City.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("state", out c); + Out tempOut_State = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, addressScope, c, tempOut_State)); + a.State = tempOut_State.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("postal_code", out c); + addressScope.get().Find(row, c.Path); + RowCursor postalCodeScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().ReadScope(row, addressScope, out postalCodeScope)); + Reference tempReference_postalCodeScope = + new Reference(postalCodeScope); + a.PostalCode = CustomerExampleUnitTests.ReadPostalCode(row, tempReference_postalCodeScope); + postalCodeScope = tempReference_postalCodeScope.get(); + Reference tempReference_postalCodeScope2 = + new Reference(postalCodeScope); + RowCursors.skip(addressScope.get().clone(), row, + tempReference_postalCodeScope2); + postalCodeScope = tempReference_postalCodeScope2.get(); + return a; + } + + private Guest ReadGuest(Reference row, Reference root) { + Guest g = new Guest(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("guest_id", out c); + Out tempOut_Id = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, root, c, tempOut_Id)); + g.Id = tempOut_Id.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("first_name", out c); + Out tempOut_FirstName = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_FirstName)); + g.FirstName = tempOut_FirstName.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("last_name", out c); + Out tempOut_LastName = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_LastName)); + g.LastName = tempOut_LastName.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("title", out c); + Out tempOut_Title = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_Title)); + g.Title = tempOut_Title.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("confirm_number", out c); + Out tempOut_ConfirmNumber = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_ConfirmNumber)); + g.ConfirmNumber = tempOut_ConfirmNumber.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("emails", out c); + RowCursor emailScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out emailScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref emailScope, out emailScope) == Result.SUCCESS) { + g.Emails = new TreeSet(); + while (emailScope.MoveNext(row)) { + String item; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref emailScope, + out item)); + g.Emails.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("phone_numbers", out c); + RowCursor phoneNumbersScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out phoneNumbersScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref phoneNumbersScope, out phoneNumbersScope) == Result.SUCCESS) { + g.PhoneNumbers = new ArrayList(); + while (phoneNumbersScope.MoveNext(row)) { + String item; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref phoneNumbersScope, + out item)); + g.PhoneNumbers.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("addresses", out c); + RowCursor addressesScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out addressesScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref addressesScope, out addressesScope) == Result.SUCCESS) { + Reference tempReference_addressesScope = new Reference(addressesScope); + TypeArgument tupleType = LayoutType.TypedMap.FieldType(tempReference_addressesScope).clone(); + addressesScope = tempReference_addressesScope.get(); + TypeArgument t0 = tupleType.getTypeArgs().get(0).clone(); + TypeArgument t1 = tupleType.getTypeArgs().get(1).clone(); + g.Addresses = new HashMap(); + RowCursor pairScope = null; + Reference tempReference_pairScope = new Reference(pairScope); + while (addressesScope.MoveNext(row, tempReference_pairScope)) { + pairScope = tempReference_pairScope.get(); + Reference tempReference_addressesScope2 = new Reference(addressesScope); + Out tempOut_pairScope = new Out(); + ResultAssert.IsSuccess(tupleType.TypeAs().ReadScope(row, + tempReference_addressesScope2, tempOut_pairScope)); + pairScope = tempOut_pairScope.get(); + addressesScope = tempReference_addressesScope2.get(); + assert RowCursors.moveNext(pairScope.clone(), row); + Reference tempReference_pairScope2 = new Reference(pairScope); + String key; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(t0.TypeAs().ReadSparse(row, tempReference_pairScope2, out key)); + pairScope = tempReference_pairScope2.get(); + assert RowCursors.moveNext(pairScope.clone(), row); + Reference tempReference_pairScope3 = new Reference(pairScope); + RowCursor addressScope; + Out tempOut_addressScope = new Out(); + ResultAssert.IsSuccess(t1.TypeAs().ReadScope(row, tempReference_pairScope3, tempOut_addressScope)); + addressScope = tempOut_addressScope.get(); + pairScope = tempReference_pairScope3.get(); + Reference tempReference_addressScope = new Reference(addressScope); + Address value = CustomerExampleUnitTests.ReadAddress(row, tempReference_addressScope); + addressScope = tempReference_addressScope.get(); + g.Addresses.put(key, value); + Reference tempReference_addressScope2 = new Reference(addressScope); + assert !RowCursors.moveNext(pairScope.clone(), row, tempReference_addressScope2); + addressScope = tempReference_addressScope2.get(); + } + pairScope = tempReference_pairScope.get(); + } + + return g; + } + + private Hotel ReadHotel(Reference row, Reference root) { + Hotel h = new Hotel(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("hotel_id", out c); + Out tempOut_Id = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_Id)); + h.Id = tempOut_Id.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("name", out c); + Out tempOut_Name = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_Name)); + h.Name = tempOut_Name.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("phone", out c); + Out tempOut_Phone = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_Phone)); + h.Phone = tempOut_Phone.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("address", out c); + assert c.Type.Immutable; + root.get().Find(row, c.Path); + RowCursor addressScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().ReadScope(row, root, out addressScope)); + assert addressScope.Immutable; + Reference tempReference_addressScope = + new Reference(addressScope); + h.Address = CustomerExampleUnitTests.ReadAddress(row, tempReference_addressScope); + addressScope = tempReference_addressScope.get(); + Reference tempReference_addressScope2 = + new Reference(addressScope); + RowCursors.skip(root.get().clone(), row, + tempReference_addressScope2); + addressScope = tempReference_addressScope2.get(); + return h; + } + + private static PostalCode ReadPostalCode(Reference row, + Reference postalCodeScope) { + Layout postalCodeLayout = postalCodeScope.get().getLayout(); + PostalCode pc = new PostalCode(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert postalCodeLayout.TryFind("zip", out c); + Out tempOut_Zip = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, postalCodeScope, c, tempOut_Zip)); + pc.Zip = tempOut_Zip.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert postalCodeLayout.TryFind("plus4", out c); + postalCodeScope.get().Find(row, c.Path); + short plus4; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadSparse(row, postalCodeScope, out plus4) == Result.SUCCESS) { + pc.Plus4 = plus4; + } + + return pc; + } + + private void WriteAddress(Reference row, Reference addressScope, + TypeArgumentList typeArgs, Address a) { + Layout addressLayout = this.customerResolver.Resolve(typeArgs.getSchemaId().clone()); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("street", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, addressScope, c, a.Street)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("city", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, addressScope, c, a.City)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("state", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, addressScope, c, a.State)); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert addressLayout.TryFind("postal_code", out c); + addressScope.get().Find(row, c.Path); + RowCursor postalCodeScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, addressScope, c.TypeArgs, out postalCodeScope)); + Reference tempReference_postalCodeScope = + new Reference(postalCodeScope); + this.WritePostalCode(row, tempReference_postalCodeScope, c.TypeArgs, a.PostalCode); + postalCodeScope = tempReference_postalCodeScope.get(); + Reference tempReference_postalCodeScope2 = + new Reference(postalCodeScope); + RowCursors.skip(addressScope.get().clone(), row, + tempReference_postalCodeScope2); + postalCodeScope = tempReference_postalCodeScope2.get(); + } + + private void WriteGuest(Reference row, Reference root, Guest g) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("guest_id", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, root, c, g.Id)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("first_name", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, g.FirstName)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("last_name", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, g.LastName)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("title", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, g.Title)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.guestLayout.TryFind("confirm_number", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, g.ConfirmNumber)); + + if (g.Emails != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.guestLayout.TryFind("emails", out c); + root.get().Find(row, c.Path); + RowCursor emailScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, root, c.TypeArgs, out emailScope)); + for (String email : g.Emails) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref emailScope, email)); + assert !emailScope.MoveNext(row); + } + + Reference tempReference_emailScope = + new Reference(emailScope); + RowCursors.skip(root.get().clone(), row, + tempReference_emailScope); + emailScope = tempReference_emailScope.get(); + } + + if (g.PhoneNumbers != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.guestLayout.TryFind("phone_numbers", out c); + root.get().Find(row, c.Path); + RowCursor phoneNumbersScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, root, c.TypeArgs, + out phoneNumbersScope)); + for (String phone : g.PhoneNumbers) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref phoneNumbersScope + , phone)); + assert !phoneNumbersScope.MoveNext(row); + } + + Reference tempReference_phoneNumbersScope = + new Reference(phoneNumbersScope); + RowCursors.skip(root.get().clone(), row, + tempReference_phoneNumbersScope); + phoneNumbersScope = tempReference_phoneNumbersScope.get(); + } + + if (g.Addresses != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.guestLayout.TryFind("addresses", out c); + root.get().Find(row, c.Path); + RowCursor addressesScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, root, c.TypeArgs, out addressesScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + TypeArgument tupleType = c.TypeAs().FieldType(ref addressesScope); + TypeArgument t0 = tupleType.getTypeArgs().get(0).clone(); + TypeArgument t1 = tupleType.getTypeArgs().get(1).clone(); + for (Map.Entry pair : g.Addresses.entrySet()) { + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(tupleType.TypeAs().WriteScope(row, ref tempCursor, + c.TypeArgs, out tupleScope)); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(t0.TypeAs().WriteSparse(row, ref tupleScope, pair.getKey())); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope = + new Reference(tupleScope); + RowCursor addressScope; + Out tempOut_addressScope = + new Out(); + ResultAssert.IsSuccess(t1.TypeAs().WriteScope(row, tempReference_tupleScope, + t1.getTypeArgs().clone(), tempOut_addressScope)); + addressScope = tempOut_addressScope.get(); + tupleScope = tempReference_tupleScope.get(); + Reference tempReference_addressScope = + new Reference(addressScope); + this.WriteAddress(row, tempReference_addressScope, t1.getTypeArgs().clone(), pair.getValue()); + addressScope = tempReference_addressScope.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !tupleScope.MoveNext(row, ref addressScope); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeAs().MoveField(row, ref addressesScope, + ref tempCursor)); + } + + Reference tempReference_addressesScope = + new Reference(addressesScope); + RowCursors.skip(root.get().clone(), row, + tempReference_addressesScope); + addressesScope = tempReference_addressesScope.get(); + } + } + + private void WriteHotel(Reference row, Reference root, Hotel h) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("hotel_id", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, h.Id)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("name", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, h.Name)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("phone", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, h.Phone)); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.hotelLayout.TryFind("address", out c); + root.get().Find(row, c.Path); + RowCursor addressScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, root, c.TypeArgs, out addressScope)); + Reference tempReference_addressScope = + new Reference(addressScope); + this.WriteAddress(row, tempReference_addressScope, c.TypeArgs, h.Address); + addressScope = tempReference_addressScope.get(); + Reference tempReference_addressScope2 = + new Reference(addressScope); + RowCursors.skip(root.get().clone(), row, + tempReference_addressScope2); + addressScope = tempReference_addressScope2.get(); + } + + private void WritePostalCode(Reference row, Reference postalCodeScope, + TypeArgumentList typeArgs, PostalCode pc) { + Layout postalCodeLayout = this.customerResolver.Resolve(typeArgs.getSchemaId().clone()); + assert postalCodeLayout != null; + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert postalCodeLayout.TryFind("zip", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, postalCodeScope, c, pc.Zip)); + if (pc.Plus4.HasValue) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert postalCodeLayout.TryFind("plus4", out c); + postalCodeScope.get().Find(row, c.Path); + ResultAssert.IsSuccess(c.TypeAs().WriteSparse(row, postalCodeScope, pc.Plus4.Value)); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/DeleteRowDispatcher.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/DeleteRowDispatcher.java new file mode 100644 index 0000000..2b4371c --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/DeleteRowDispatcher.java @@ -0,0 +1,167 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutIndexedScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedSet; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; + +import java.util.List; + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal struct DeleteRowDispatcher : IDispatcher +public final class DeleteRowDispatcher implements IDispatcher { + + public , TValue> void Dispatch(Reference dispatcher, Reference root, LayoutColumn col, LayoutType t) { + Dispatch(dispatcher, root, col, t, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public void Dispatch(ref RowOperationDispatcher dispatcher, ref RowCursor root, + // LayoutColumn col, LayoutType t, TValue value = default) where TLayout : LayoutType + public , TValue> void Dispatch(Reference dispatcher, Reference root, LayoutColumn col, LayoutType t, TValue value) { + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().deleteSparse(tempReference_Row, root)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + } + + public void DispatchArray(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor arrayScope; + Out tempOut_arrayScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_arrayScope)); + arrayScope = tempOut_arrayScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + if (!arrayScope.Immutable) { + List items = (List)value; + for (Object item : items) { + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + assert arrayScope.MoveNext(tempReference_Row2); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + dispatcher.get().LayoutCodeSwitch(ref arrayScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), item); + } + } + + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().DeleteScope(tempReference_Row3, scope)); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + } + + public void DispatchMap(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 2); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor mapScope; + Out tempOut_mapScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_mapScope)); + mapScope = tempOut_mapScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + if (!mapScope.Immutable) { + List items = (List)value; + for (Object item : items) { + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + assert mapScope.MoveNext(tempReference_Row2); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + dispatcher.get().LayoutCodeSwitch(ref mapScope, null, LayoutType.TypedTuple, typeArgs.clone(), item); + } + } + + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().DeleteScope(tempReference_Row3, scope)); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + } + + public void DispatchNullable(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().DeleteScope(tempReference_Row, scope)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + } + + public void DispatchObject(Reference dispatcher, + Reference scope) { + } + + public void DispatchSet(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor setScope; + Out tempOut_setScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_setScope)); + setScope = tempOut_setScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + if (!setScope.Immutable) { + List items = (List)value; + for (Object item : items) { + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + assert setScope.MoveNext(tempReference_Row2); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + dispatcher.get().LayoutCodeSwitch(ref setScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), item); + } + } + + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().DeleteScope(tempReference_Row3, scope)); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + } + + public void DispatchTuple(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() >= 2); + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().DeleteScope(tempReference_Row, scope)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + } + + public void DispatchUDT(Reference dispatcher, Reference scope, LayoutType t, TypeArgumentList typeArgs, Object value) { + Reference tempReference_Row = new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().DeleteScope(tempReference_Row, scope)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatchable.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatchable.java new file mode 100644 index 0000000..7591ddc --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatchable.java @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +public interface IDispatchable { + void Dispatch(Reference dispatcher, Reference scope); +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatcher.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatcher.java new file mode 100644 index 0000000..c9fdc9f --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/IDispatcher.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +public interface IDispatcher { + + , TValue> void Dispatch(Reference dispatcher, + Reference scope, LayoutColumn col, + LayoutType t); + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: void Dispatch(ref RowOperationDispatcher dispatcher, ref RowCursor scope, + // LayoutColumn col, LayoutType t, TValue value = default) where TLayout : LayoutType; + , TValue> void Dispatch(Reference dispatcher, + Reference scope, LayoutColumn col, + LayoutType t, TValue value); + + void DispatchArray(Reference dispatcher, Reference scope, + LayoutType t, TypeArgumentList typeArgs, Object value); + + void DispatchMap(Reference dispatcher, Reference scope, + LayoutType t, TypeArgumentList typeArgs, Object value); + + void DispatchNullable(Reference dispatcher, Reference scope, + LayoutType t, TypeArgumentList typeArgs, Object value); + + void DispatchObject(Reference dispatcher, Reference scope); + + void DispatchSet(Reference dispatcher, Reference scope, + LayoutType t, TypeArgumentList typeArgs, Object value); + + void DispatchTuple(Reference dispatcher, Reference scope, + LayoutType t, TypeArgumentList typeArgs, Object value); + + void DispatchUDT(Reference dispatcher, Reference scope, + LayoutType type, TypeArgumentList typeArgs, Object value); +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutCompilerUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutCompilerUnitTests.java new file mode 100644 index 0000000..fd90ef4 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutCompilerUnitTests.java @@ -0,0 +1,3238 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBit; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.UUID; + +// ReSharper disable CommentTypo +// ReSharper disable StringLiteralTypo +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1201 // Elements should appear in the correct order +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable IDE0008 // Use explicit type + + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("Naming", "DontUseVarForVariableTypes", Justification = "The types here +// are anonymous.")] public class LayoutCompilerUnitTests +public class LayoutCompilerUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void PackNullAndBoolBits() + public final void PackNullAndBoolBits() { + // Test that null bits and bool bits are packed tightly in the layout. + Schema s = new Schema(); + s.setName("TestSchema"); + s.setSchemaId(new SchemaId(1)); + s.setType(TypeKind.Schema); + for (int i = 0; i < 32; i++) { + Property tempVar = new Property(); + tempVar.setPath(String.valueOf(i)); + PrimitivePropertyType tempVar2 = new PrimitivePropertyType(); + tempVar2.setType(TypeKind.Boolean); + tempVar2.setStorage(StorageKind.Fixed); + tempVar.setPropertyType(tempVar2); + s.getProperties().add(tempVar); + + Namespace tempVar3 = new Namespace(); + tempVar3.setSchemas(new ArrayList(Arrays.asList(s))); + Layout layout = s.Compile(tempVar3); + Assert.IsTrue(layout.getSize() == LayoutBit.divCeiling((i + 1) * 2, LayoutType.BitsPerByte), "Size: {0}, " + + "i: {1}", layout.getSize(), i); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaFixed() + public final void ParseSchemaFixed() { + // Test all fixed column types. + RoundTripFixed.Expected tempVar = new RoundTripFixed.Expected(); + tempVar.TypeName = "null"; + tempVar.Default = new NullValue(); + tempVar.Value = NullValue.DEFAULT; + RoundTripFixed.Expected tempVar2 = new RoundTripFixed.Expected(); + tempVar2.TypeName = "bool"; + tempVar2.Default = false; + tempVar2.Value = false; + RoundTripFixed.Expected tempVar3 = new RoundTripFixed.Expected(); + tempVar3.TypeName = "int8"; + tempVar3.Default = 0; + tempVar3.Value = (byte)42; + RoundTripFixed.Expected tempVar4 = new RoundTripFixed.Expected(); + tempVar4.TypeName = "int16"; + tempVar4.Default = 0; + tempVar4.Value = (short)42; + RoundTripFixed.Expected tempVar5 = new RoundTripFixed.Expected(); + tempVar5.TypeName = "int32"; + tempVar5.Default = 0; + tempVar5.Value = 42; + RoundTripFixed.Expected tempVar6 = new RoundTripFixed.Expected(); + tempVar6.TypeName = "int64"; + tempVar6.Default = 0; + tempVar6.Value = 42L; + RoundTripFixed.Expected tempVar7 = new RoundTripFixed.Expected(); + tempVar7.TypeName = "uint8"; + tempVar7.Default = 0; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar7.Value = (byte)42; + tempVar7.Value = (byte)42; + RoundTripFixed.Expected tempVar8 = new RoundTripFixed.Expected(); + tempVar8.TypeName = "uint16"; + tempVar8.Default = 0; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar8.Value = (ushort)42; + tempVar8.Value = (short)42; + RoundTripFixed.Expected tempVar9 = new RoundTripFixed.Expected(); + tempVar9.TypeName = "uint32"; + tempVar9.Default = 0; + tempVar9.Value = 42; + RoundTripFixed.Expected tempVar10 = new RoundTripFixed.Expected(); + tempVar10.TypeName = "uint64"; + tempVar10.Default = 0; + tempVar10.Value = 42; + RoundTripFixed.Expected tempVar11 = new RoundTripFixed.Expected(); + tempVar11.TypeName = "float32"; + tempVar11.Default = 0; + tempVar11.Value = 4.2F; + RoundTripFixed.Expected tempVar12 = new RoundTripFixed.Expected(); + tempVar12.TypeName = "float64"; + tempVar12.Default = 0; + tempVar12.Value = 4.2; + RoundTripFixed.Expected tempVar13 = new RoundTripFixed.Expected(); + tempVar13.TypeName = "float128"; + tempVar13.Default = new Float128(); + tempVar13.Value = new Float128(0, 42); + RoundTripFixed.Expected tempVar14 = new RoundTripFixed.Expected(); + tempVar14.TypeName = "decimal"; + tempVar14.Default = new BigDecimal(0); + tempVar14.Value = 4.2; + RoundTripFixed.Expected tempVar15 = new RoundTripFixed.Expected(); + tempVar15.TypeName = "datetime"; + tempVar15.Default = LocalDateTime.MIN; + tempVar15.Value = LocalDateTime.UtcNow; + RoundTripFixed.Expected tempVar16 = new RoundTripFixed.Expected(); + tempVar16.TypeName = "unixdatetime"; + tempVar16.Default = new UnixDateTime(); + tempVar16.Value = new UnixDateTime(42); + RoundTripFixed.Expected tempVar17 = new RoundTripFixed.Expected(); + tempVar17.TypeName = "guid"; + tempVar17.Default = null; + tempVar17.Value = UUID.NewGuid(); + RoundTripFixed.Expected tempVar18 = new RoundTripFixed.Expected(); + tempVar18.TypeName = "mongodbobjectid"; + tempVar18.Default = new MongoDbObjectId(); + tempVar18.Value = new MongoDbObjectId(0, 42); + RoundTripFixed.Expected tempVar19 = new RoundTripFixed.Expected(); + tempVar19.TypeName = "utf8"; + tempVar19.Default = "\0\0"; + tempVar19.Value = "AB"; + tempVar19.Length = 2; + RoundTripFixed.Expected tempVar20 = new RoundTripFixed.Expected(); + tempVar20.TypeName = "binary"; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar20.Default = new byte[] { 0x00, 0x00 }; + tempVar20.Default = new byte[] { 0x00, 0x00 }; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar20.Value = new byte[] { 0x01, 0x02 }; + tempVar20.Value = new byte[] { 0x01, 0x02 }; + tempVar20.Length = 2; + RoundTripFixed.Expected[] expectedSchemas = + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripFixed.Expected[] { tempVar, tempVar2, tempVar3, tempVar4, tempVar5, tempVar6, tempVar7, tempVar8, tempVar9, tempVar10, tempVar11, tempVar12, tempVar13, tempVar14, tempVar15, tempVar16, tempVar17, tempVar18, tempVar19, tempVar20 }; + + RowBuffer row = new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for (String nullable : new String[] { "true", "false" }) { + for (RoundTripFixed.Expected exp : expectedSchemas) { + RoundTripFixed.Expected expected = exp.clone(); + String typeSchema = String.format("{'type': '%1$s', 'storage': 'fixed', 'length': %2$s, 'nullable': " + + "%3$s", expected.TypeName, expected.Length, nullable + } + }) + expected.Json = typeSchema; + String propSchema = String.format("{'path': 'a', 'type': %1$s", typeSchema + } +}); + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }",propSchema); + try + { + Schema s=Schema.Parse(tableSchema); + Namespace tempVar21=new Namespace(); + tempVar21.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar21); + Layout layout=resolver.Resolve(new SchemaId(-1)); + Assert.AreEqual(1,layout.getColumns().Length,"Json: {0}",expected.Json); + Assert.AreEqual(s.getName(),layout.getName(),"Json: {0}",expected.Json); + Assert.IsTrue(layout.toString().length()>0,"Json: {0}",expected.Json); + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out col); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Fixed,col.Storage,"Json: {0}",expected.Json); + Assert.AreEqual(expected.Length==0,col.Type.IsFixed,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripFixed.Closure tempVar22=new RoundTripFixed.Closure(); + tempVar22.Col=col; + tempVar22.Expected=expected.clone(); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(col.Type.LayoutCode,tempRef_row2,tempRef_root, + tempVar22.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + catch(LayoutCompilationException e) + { + assert expected.TypeName.equals("null"); + assert"false"==nullable; + } + } + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaVariable() +public final void ParseSchemaVariable() + { + // Helper functions to create sample arrays. + // TODO: C# TO JAVA CONVERTER: Local functions are not converted by C# to Java Converter: + // string MakeS(int size) + // { + // StringBuilder ret = new StringBuilder(size); + // for (int i = 0; i < size; i++) + // { + // ret.Append(unchecked((char)('a' + (i % 26)))); // allow wrapping (this also allows \0 chars) + // } + // + // return ret.ToString(); + // } + + // TODO: C# TO JAVA CONVERTER: Local functions are not converted by C# to Java Converter: + // byte[] MakeB(int size) + // { + // byte[] ret = new byte[size]; + // for (int i = 0; i < size; i++) + // { + // ret[i] = unchecked((byte)(i + 1)); // allow wrapping + // } + // + // return ret; + // } + + // Test all variable column types. + RoundTripVariable.Expected tempVar=new RoundTripVariable.Expected(); + tempVar.Json="{'type': 'utf8', 'storage': 'variable', 'length': 100}"; + tempVar.Short=MakeS(2); + tempVar.Value=MakeS(20); + tempVar.Long=MakeS(100); + tempVar.TooBig=MakeS(200); + RoundTripVariable.Expected tempVar2=new RoundTripVariable.Expected(); + tempVar2.Json="{'type': 'binary', 'storage': 'variable', 'length': 100}"; + tempVar2.Short=MakeB(2); + tempVar2.Value=MakeB(20); + tempVar2.Long=MakeB(100); + tempVar2.TooBig=MakeB(200); + RoundTripVariable.Expected tempVar3=new RoundTripVariable.Expected(); + tempVar3.Json="{'type': 'varint', 'storage': 'variable'}"; + tempVar3.Short=1L; + tempVar3.Value=255L; + tempVar3.Long=Long.MAX_VALUE; + RoundTripVariable.Expected tempVar4=new RoundTripVariable.Expected(); + tempVar4.Json="{'type': 'varuint', 'storage': 'variable'}"; + tempVar4.Short=1; + tempVar4.Value=255; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar4.Long = ulong.MaxValue; + tempVar4.Long=Long.MAX_VALUE; + RoundTripVariable.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripVariable.Expected[]{tempVar,tempVar2,tempVar3,tempVar4}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripVariable.Expected expected:expectedSchemas) + { + String propSchema=String.format("{'path': 'a', 'type': %1$s, ",expected.Json}})+"\r\n"+ + " {{'path': 'b', 'type': {expected.Json}}}, "+"\r\n"+ + " {{'path': 'c', 'type': {expected.Json}}}"; + + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }",propSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar5=new Namespace(); + tempVar5.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar5); + Layout layout=resolver.Resolve(new SchemaId(-1)); + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out col); + Assert.IsTrue(found,"Json: {0}",expected.Json); + assert col.Type.AllowVariable; + Assert.AreEqual(StorageKind.Variable,col.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripVariable.Closure tempVar6=new RoundTripVariable.Closure(); + tempVar6.Layout=layout; + tempVar6.Col=col; + tempVar6.Expected=expected.clone(); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(col.Type.LayoutCode,tempRef_row2, + tempRef_root,tempVar6.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void SparseOrdering() +public final void SparseOrdering() + { + // Test various orderings of multiple sparse column types. + RoundTripSparseOrdering.Expected tempVar=new RoundTripSparseOrdering.Expected(); + tempVar.Path="a"; + tempVar.Type=LayoutType.Utf8; + tempVar.Value="aa"; + RoundTripSparseOrdering.Expected tempVar2=new RoundTripSparseOrdering.Expected(); + tempVar2.Path="b"; + tempVar2.Type=LayoutType.Utf8; + tempVar2.Value="bb"; + RoundTripSparseOrdering.Expected tempVar3=new RoundTripSparseOrdering.Expected(); + tempVar3.Path="a"; + tempVar3.Type=LayoutType.VarInt; + tempVar3.Value=42L; + RoundTripSparseOrdering.Expected tempVar4=new RoundTripSparseOrdering.Expected(); + tempVar4.Path="b"; + tempVar4.Type=LayoutType.Int64; + tempVar4.Value=43L; + RoundTripSparseOrdering.Expected tempVar5=new RoundTripSparseOrdering.Expected(); + tempVar5.Path="a"; + tempVar5.Type=LayoutType.VarInt; + tempVar5.Value=42L; + RoundTripSparseOrdering.Expected tempVar6=new RoundTripSparseOrdering.Expected(); + tempVar6.Path="b"; + tempVar6.Type=LayoutType.Utf8; + tempVar6.Value="aa"; + RoundTripSparseOrdering.Expected tempVar7=new RoundTripSparseOrdering.Expected(); + tempVar7.Path="c"; + tempVar7.Type=LayoutType.Null; + tempVar7.Value=NullValue.Default; + RoundTripSparseOrdering.Expected tempVar8=new RoundTripSparseOrdering.Expected(); + tempVar8.Path="d"; + tempVar8.Type=LayoutType.Boolean; + tempVar8.Value=true; + RoundTripSparseOrdering.Expected[][]expectedOrders= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseOrdering.Expected[][] + { + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseOrdering.Expected[]{tempVar,tempVar2}, + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseOrdering.Expected[]{tempVar3,tempVar4}, + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseOrdering.Expected[]{tempVar5,tempVar6,tempVar7,tempVar8} + }; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseOrdering.Expected[]expectedSet:expectedOrders) + { + for(java.lang.Iterablepermutation:expectedSet.Permute()) + { + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to LINQ query syntax: + String json=tangible.StringHelper.join(", ",from p in permutation select p.Path+": "+p.Type.Name); + System.out.printf("%1$s"+"\r\n",json); + + row.Reset(); + row.InitLayout(HybridRowVersion.V1,Layout.Empty,SystemSchema.LayoutResolver); + for(RoundTripSparseOrdering.Expected field:permutation) + { + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripSparseOrdering.Closure tempVar9=new RoundTripSparseOrdering.Closure(); + tempVar9.Expected=field.clone(); + tempVar9.Json=json; + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(field.Type.LayoutCode, + tempRef_row2,tempRef_root,tempVar9.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + } + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaSparseSimple() +public final void ParseSchemaSparseSimple() + { + // Test all sparse column types. + RoundTripSparseSimple.Expected tempVar=new RoundTripSparseSimple.Expected(); + tempVar.Json="{'type': 'null', 'storage': 'sparse'}"; + tempVar.Value=NullValue.Default; + RoundTripSparseSimple.Expected tempVar2=new RoundTripSparseSimple.Expected(); + tempVar2.Json="{'type': 'bool', 'storage': 'sparse'}"; + tempVar2.Value=true; + RoundTripSparseSimple.Expected tempVar3=new RoundTripSparseSimple.Expected(); + tempVar3.Json="{'type': 'bool', 'storage': 'sparse'}"; + tempVar3.Value=false; + RoundTripSparseSimple.Expected tempVar4=new RoundTripSparseSimple.Expected(); + tempVar4.Json="{'type': 'int8', 'storage': 'sparse'}"; + tempVar4.Value=(byte)42; + RoundTripSparseSimple.Expected tempVar5=new RoundTripSparseSimple.Expected(); + tempVar5.Json="{'type': 'int16', 'storage': 'sparse'}"; + tempVar5.Value=(short)42; + RoundTripSparseSimple.Expected tempVar6=new RoundTripSparseSimple.Expected(); + tempVar6.Json="{'type': 'int32', 'storage': 'sparse'}"; + tempVar6.Value=42; + RoundTripSparseSimple.Expected tempVar7=new RoundTripSparseSimple.Expected(); + tempVar7.Json="{'type': 'int64', 'storage': 'sparse'}"; + tempVar7.Value=42L; + RoundTripSparseSimple.Expected tempVar8=new RoundTripSparseSimple.Expected(); + tempVar8.Json="{'type': 'uint8', 'storage': 'sparse'}"; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar8.Value = (byte)42; + tempVar8.Value=(byte)42; + RoundTripSparseSimple.Expected tempVar9=new RoundTripSparseSimple.Expected(); + tempVar9.Json="{'type': 'uint16', 'storage': 'sparse'}"; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar9.Value = (ushort)42; + tempVar9.Value=(short)42; + RoundTripSparseSimple.Expected tempVar10=new RoundTripSparseSimple.Expected(); + tempVar10.Json="{'type': 'uint32', 'storage': 'sparse'}"; + tempVar10.Value=42; + RoundTripSparseSimple.Expected tempVar11=new RoundTripSparseSimple.Expected(); + tempVar11.Json="{'type': 'uint64', 'storage': 'sparse'}"; + tempVar11.Value=42; + RoundTripSparseSimple.Expected tempVar12=new RoundTripSparseSimple.Expected(); + tempVar12.Json="{'type': 'varint', 'storage': 'sparse'}"; + tempVar12.Value=42L; + RoundTripSparseSimple.Expected tempVar13=new RoundTripSparseSimple.Expected(); + tempVar13.Json="{'type': 'varuint', 'storage': 'sparse'}"; + tempVar13.Value=42; + RoundTripSparseSimple.Expected tempVar14=new RoundTripSparseSimple.Expected(); + tempVar14.Json="{'type': 'float32', 'storage': 'sparse'}"; + tempVar14.Value=4.2F; + RoundTripSparseSimple.Expected tempVar15=new RoundTripSparseSimple.Expected(); + tempVar15.Json="{'type': 'float64', 'storage': 'sparse'}"; + tempVar15.Value=4.2; + RoundTripSparseSimple.Expected tempVar16=new RoundTripSparseSimple.Expected(); + tempVar16.Json="{'type': 'float128', 'storage': 'sparse'}"; + tempVar16.Value=new Float128(0,42); + RoundTripSparseSimple.Expected tempVar17=new RoundTripSparseSimple.Expected(); + tempVar17.Json="{'type': 'decimal', 'storage': 'sparse'}"; + tempVar17.Value=4.2; + RoundTripSparseSimple.Expected tempVar18=new RoundTripSparseSimple.Expected(); + tempVar18.Json="{'type': 'datetime', 'storage': 'sparse'}"; + tempVar18.Value=LocalDateTime.UtcNow; + RoundTripSparseSimple.Expected tempVar19=new RoundTripSparseSimple.Expected(); + tempVar19.Json="{'type': 'unixdatetime', 'storage': 'sparse'}"; + tempVar19.Value=new UnixDateTime(42); + RoundTripSparseSimple.Expected tempVar20=new RoundTripSparseSimple.Expected(); + tempVar20.Json="{'type': 'guid', 'storage': 'sparse'}"; + tempVar20.Value=UUID.NewGuid(); + RoundTripSparseSimple.Expected tempVar21=new RoundTripSparseSimple.Expected(); + tempVar21.Json="{'type': 'mongodbobjectid', 'storage': 'sparse'}"; + tempVar21.Value=new MongoDbObjectId(0,42); + RoundTripSparseSimple.Expected tempVar22=new RoundTripSparseSimple.Expected(); + tempVar22.Json="{'type': 'utf8', 'storage': 'sparse'}"; + tempVar22.Value="AB"; + RoundTripSparseSimple.Expected tempVar23=new RoundTripSparseSimple.Expected(); + tempVar23.Json="{'type': 'binary', 'storage': 'sparse'}"; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar23.Value = new byte[] { 0x01, 0x02 }; + tempVar23.Value=new byte[]{0x01,0x02}; + RoundTripSparseSimple.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseSimple.Expected[]{tempVar,tempVar2,tempVar3,tempVar4,tempVar5,tempVar6,tempVar7,tempVar8,tempVar9,tempVar10,tempVar11,tempVar12,tempVar13,tempVar14,tempVar15,tempVar16,tempVar17,tempVar18,tempVar19,tempVar20,tempVar21,tempVar22,tempVar23}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseSimple.Expected expected:expectedSchemas) + { + String propSchema=String.format("{'path': 'a', 'type': %1$s",expected.Json}}); + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }",propSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar24=new Namespace(); + tempVar24.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar24); + Layout layout=resolver.Resolve(new SchemaId(-1)); + Assert.AreEqual(1,layout.getColumns().Length,"Json: {0}",expected.Json); + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out col); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,col.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripSparseSimple.Closure tempVar25=new RoundTripSparseSimple.Closure(); + tempVar25.Col=col; + tempVar25.Expected=expected.clone(); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(col.Type.LayoutCode,tempRef_row2, + tempRef_root,tempVar25.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaUDT() +public final void ParseSchemaUDT() + { + String namespaceJson=""+"\r\n"+ + " {'name': 'myNamespace', "+"\r\n"+ + " 'schemas': ["+"\r\n"+ + " {'name': 'udtA', 'id': 1, 'type': 'schema', 'options': { 'disallowUnschematized': false }, " + +"\r\n"+ + " 'properties': [ "+"\r\n"+ + " { 'path': 'a', 'type': { 'type': 'int8', 'storage': 'fixed' }}, "+"\r\n"+ + " { 'path': 'b', 'type': { 'type': 'utf8', 'storage': 'variable', 'length': 100 }} "+"\r\n"+ + " ]"+"\r\n"+ + " },"+"\r\n"+ + " {'name': 'udtB', 'id': 2, 'type': 'schema'},"+"\r\n"+ + " {'name': 'udtB', 'id': 3, 'type': 'schema'},"+"\r\n"+ + " {'name': 'udtB', 'id': 4, 'type': 'schema'},"+"\r\n"+ + " {'name': 'table', 'id': -1, 'type': 'schema', "+"\r\n"+ + " 'properties': ["+"\r\n"+ + " { 'path': 'u', 'type': { 'type': 'schema', 'name': 'udtA' }}, "+"\r\n"+ + " { 'path': 'v', 'type': { 'type': 'schema', 'name': 'udtB', 'id': 3 }}, "+"\r\n"+ + " ] "+"\r\n"+ + " }"+"\r\n"+ + " ]"+"\r\n"+ + " }"; + + Namespace n1=Namespace.Parse(namespaceJson); + + String tag=String.format("Json: %1$s",namespaceJson); + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + Schema s=tangible.ListHelper.find(n1.getSchemas(),x->x.Name.equals("table")); + assert s!=null; + assert"table"==s.getName(); + Layout layout=s.Compile(n1); + LayoutColumn udtACol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("u",out udtACol); + Assert.IsTrue(found,tag); + Assert.AreEqual(StorageKind.Sparse,udtACol.Storage,tag); + + Schema udtASchema=tangible.ListHelper.find(n1.getSchemas(),x->x.SchemaId==udtACol.TypeArgs.SchemaId); + assert udtASchema!=null; + assert"udtA"==udtASchema.getName(); + + // Verify that UDT versioning works through schema references. + LayoutColumn udtBCol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + found=layout.TryFind("v",out udtBCol); + Assert.IsTrue(found,tag); + Assert.AreEqual(StorageKind.Sparse,udtBCol.Storage,tag); + Schema udtBSchema=tangible.ListHelper.find(n1.getSchemas(),x->x.SchemaId==udtBCol.TypeArgs.SchemaId); + assert udtBSchema!=null; + assert"udtB"==udtBSchema.getName(); + assert new SchemaId(3)==udtBSchema.getSchemaId().clone(); + + LayoutResolver resolver=new LayoutResolverNamespace(n1); + Layout udtLayout=resolver.Resolve(udtASchema.getSchemaId().clone()); + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + // Verify the udt doesn't yet exist. + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + RowCursor scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.Create(tempRef_row,out scope).Find(tempRef_row2,udtACol.Path); + row=tempRef_row2.argValue; + row=tempRef_row.argValue; + tangible.RefObjecttempRef_row3=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope=new tangible.RefObject(scope); + tangible.OutObjecttempOut__=new tangible.OutObject(); + Result r=LayoutType.UDT.ReadScope(tempRef_row3,tempRef_scope,tempOut__); + _=tempOut__.argValue; + scope=tempRef_scope.argValue; + row=tempRef_row3.argValue; + ResultAssert.NotFound(r,tag); + tangible.RefObjecttempRef_row4=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope2=new tangible.RefObject(scope); + RowCursor udtScope1; + tangible.OutObjecttempOut_udtScope1= + new tangible.OutObject(); + r=LayoutType.UDT.WriteScope(tempRef_row4,tempRef_scope2,udtACol.TypeArgs,tempOut_udtScope1); + udtScope1=tempOut_udtScope1.argValue; + scope=tempRef_scope2.argValue; + row=tempRef_row4.argValue; + ResultAssert.IsSuccess(r,tag); + tangible.RefObjecttempRef_row5=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope3=new tangible.RefObject(scope); + RowCursor udtScope2; + tangible.OutObjecttempOut_udtScope2= + new tangible.OutObject(); + r=LayoutType.UDT.ReadScope(tempRef_row5,tempRef_scope3,tempOut_udtScope2); + udtScope2=tempOut_udtScope2.argValue; + scope=tempRef_scope3.argValue; + row=tempRef_row5.argValue; + ResultAssert.IsSuccess(r,tag); + Assert.AreSame(udtLayout,udtScope2.Layout,tag); + Assert.AreEqual(udtScope1.ScopeType,udtScope2.ScopeType,tag); + Assert.AreEqual(udtScope1.start,udtScope2.start,tag); + Assert.AreEqual(udtScope1.Immutable,udtScope2.Immutable,tag); + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to implicit typing in Java unless the Java 10 inferred + // typing option is selected: + var expectedSchemas=new[]{new{Storage=StorageKind.Fixed,Path="a",FixedExpected=new RoundTripFixed.Expected(); + FixedExpected.Json="{ 'type': 'int8', 'storage': 'fixed' }"; + FixedExpected.Value=(byte)42; + + // TODO: C# TO JAVA CONVERTER: There is no equivalent to implicit typing in Java unless the Java 10 inferred + // typing option is selected: + for(var expected:expectedSchemas) + { + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + found=udtLayout.TryFind(expected.Path,out col); + Assert.IsTrue(found,"Path: {0}",expected.Path); + StorageKind storage=expected.Storage; + switch(storage) + { + case Fixed: + RoundTripFixed.Closure tempVar=new RoundTripFixed.Closure(); + tempVar.Col=col; + tempVar.Expected=expected.FixedExpected; + tangible.RefObjecttempRef_row6=new tangible.RefObject(row); + tangible.RefObjecttempRef_udtScope1= + new tangible.RefObject(udtScope1); + this.LayoutCodeSwitch(col.Type.LayoutCode,tempRef_row6,tempRef_udtScope1, + tempVar.clone()); + udtScope1=tempRef_udtScope1.argValue; + row=tempRef_row6.argValue; + break; + case Variable: + RoundTripVariable.Closure tempVar2=new RoundTripVariable.Closure(); + tempVar2.Col=col; + tempVar2.Layout=layout; + tempVar2.Expected=expected.VariableExpected; + tangible.RefObjecttempRef_row7=new tangible.RefObject(row); + tangible.RefObjecttempRef_udtScope12= + new tangible.RefObject(udtScope1); + this.LayoutCodeSwitch(col.Type.LayoutCode,tempRef_row7, + tempRef_udtScope12,tempVar2.clone()); + udtScope1=tempRef_udtScope12.argValue; + row=tempRef_row7.argValue; + break; + } + } + + tangible.RefObjecttempRef_row8=new tangible.RefObject(row); + tangible.RefObjecttempRef_row9=new tangible.RefObject(row); + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.Create(tempRef_row8).AsReadOnly(out roRoot).Find(tempRef_row9,udtACol.Path); + row=tempRef_row9.argValue; + row=tempRef_row8.argValue; + tangible.RefObjecttempRef_row10=new tangible.RefObject(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot + // be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(udtACol.TypeAs().DeleteScope(tempRef_row10,ref roRoot)); + row=tempRef_row10.argValue; + tangible.RefObjecttempRef_row11=new tangible.RefObject(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot + // be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(udtACol.TypeAs().WriteScope(tempRef_row11,ref roRoot, + udtACol.TypeArgs,out udtScope2)); + row=tempRef_row11.argValue; + + // Overwrite the whole scope. + tangible.RefObjecttempRef_row12=new tangible.RefObject(row); + tangible.RefObjecttempRef_row13=new tangible.RefObject(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.Create(tempRef_row12,out scope).Find(tempRef_row13,udtACol.Path); + row=tempRef_row13.argValue; + row=tempRef_row12.argValue; + tangible.RefObjecttempRef_row14=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope4=new tangible.RefObject(scope); + r=LayoutType.Null.WriteSparse(tempRef_row14,tempRef_scope4,NullValue.Default); + scope=tempRef_scope4.argValue; + row=tempRef_row14.argValue; + ResultAssert.IsSuccess(r,tag); + tangible.RefObjecttempRef_row15=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope5=new tangible.RefObject(scope); + RowCursor _; + tangible.OutObjecttempOut__2=new tangible.OutObject(); + r=LayoutType.UDT.ReadScope(tempRef_row15,tempRef_scope5,tempOut__2); + _=tempOut__2.argValue; + scope=tempRef_scope5.argValue; + row=tempRef_row15.argValue; + ResultAssert.TypeMismatch(r,tag); + tangible.RefObjecttempRef_row16=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope6=new tangible.RefObject(scope); + r=LayoutType.UDT.DeleteScope(tempRef_row16,tempRef_scope6); + scope=tempRef_scope6.argValue; + row=tempRef_row16.argValue; + ResultAssert.TypeMismatch(r,tag); + + // Overwrite it again, then delete it. + tangible.RefObjecttempRef_row17=new tangible.RefObject(row); + tangible.RefObjecttempRef_row18=new tangible.RefObject(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.Create(tempRef_row17,out scope).Find(tempRef_row18,udtACol.Path); + row=tempRef_row18.argValue; + row=tempRef_row17.argValue; + tangible.RefObjecttempRef_row19=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope7=new tangible.RefObject(scope); + RowCursor _; + tangible.OutObjecttempOut__3=new tangible.OutObject(); + r=LayoutType.UDT.WriteScope(tempRef_row19,tempRef_scope7,udtACol.TypeArgs,tempOut__3); + _=tempOut__3.argValue; + scope=tempRef_scope7.argValue; + row=tempRef_row19.argValue; + ResultAssert.IsSuccess(r,tag); + tangible.RefObjecttempRef_row20=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope8=new tangible.RefObject(scope); + r=LayoutType.UDT.DeleteScope(tempRef_row20,tempRef_scope8); + scope=tempRef_scope8.argValue; + row=tempRef_row20.argValue; + ResultAssert.IsSuccess(r,tag); + tangible.RefObjecttempRef_row21=new tangible.RefObject(row); + tangible.RefObjecttempRef_row22=new tangible.RefObject(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.Create(tempRef_row21,out scope).Find(tempRef_row22,udtACol.Path); + row=tempRef_row22.argValue; + row=tempRef_row21.argValue; + tangible.RefObjecttempRef_row23=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope9=new tangible.RefObject(scope); + RowCursor _; + tangible.OutObjecttempOut__4=new tangible.OutObject(); + r=LayoutType.UDT.ReadScope(tempRef_row23,tempRef_scope9,tempOut__4); + _=tempOut__4.argValue; + scope=tempRef_scope9.argValue; + row=tempRef_row23.argValue; + ResultAssert.NotFound(r,tag); + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaSparseObject() +public final void ParseSchemaSparseObject() + { + // Test all fixed column types. + RoundTripSparseObject.Expected tempVar=new RoundTripSparseObject.Expected(); + tempVar.Json="{'path': 'b', 'type': {'type': 'int8'}}"; + tempVar.Value=(byte)42; + RoundTripSparseObject.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObject.Expected[]{tempVar}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseObject.Expected expected:expectedSchemas) + { + String objectColumnSchema=String.format("{'path': 'a', 'type': {'type': 'object', 'properties': [%1$s] } }", + expected.Json); + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }", + objectColumnSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar2=new Namespace(); + tempVar2.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar2); + Layout layout=resolver.Resolve(new SchemaId(-1)); + Assert.AreEqual(1,layout.getColumns().Length,"Json: {0}",expected.Json); + LayoutColumn objCol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out objCol); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,objCol.Storage,"Json: {0}",expected.Json); + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + found=layout.TryFind("a.b",out col); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,col.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripSparseObject.Closure tempVar3=new RoundTripSparseObject.Closure(); + tempVar3.ObjCol=objCol; + tempVar3.Col=col; + tempVar3.Expected=expected.clone(); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(col.Type.LayoutCode,tempRef_row2, + tempRef_root,tempVar3.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaSparseObjectMulti() +public final void ParseSchemaSparseObjectMulti() + { + // Test sparse object columns with various kinds of sparse column fields. + RoundTripSparseObjectMulti.Expected tempVar=new RoundTripSparseObjectMulti.Expected(); + tempVar.Json="{'path': 'b', 'type': {'type': 'int8'}}"; + RoundTripSparseObjectMulti.Property tempVar2=new RoundTripSparseObjectMulti.Property(); + tempVar2.setPath("a.b"); + tempVar2.Value=(byte)42; + tempVar.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectMulti.Property[]{tempVar2}; + RoundTripSparseObjectMulti.Expected tempVar3=new RoundTripSparseObjectMulti.Expected(); + tempVar3.Json="{'path': 'b', 'type': {'type': 'int8'}}, {'path': 'c', 'type': {'type': 'utf8'}}"; + RoundTripSparseObjectMulti.Property tempVar4=new RoundTripSparseObjectMulti.Property(); + tempVar4.setPath("a.b"); + tempVar4.Value=(byte)42; + RoundTripSparseObjectMulti.Property tempVar5=new RoundTripSparseObjectMulti.Property(); + tempVar5.setPath("a.c"); + tempVar5.Value="abc"; + tempVar3.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectMulti.Property[]{tempVar4,tempVar5}; + RoundTripSparseObjectMulti.Expected tempVar6=new RoundTripSparseObjectMulti.Expected(); + tempVar6.Json="{'path': 'b', 'type': {'type': 'int8'}}, {'path': 'c', 'type': {'type': 'bool'}}, {'path': 'd', " + + "'type': {'type': 'binary'}}, {'path': 'e', 'type': {'type': 'null'}}"; + RoundTripSparseObjectMulti.Property tempVar7=new RoundTripSparseObjectMulti.Property(); + tempVar7.setPath("a.b"); + tempVar7.Value=(byte)42; + RoundTripSparseObjectMulti.Property tempVar8=new RoundTripSparseObjectMulti.Property(); + tempVar8.setPath("a.c"); + tempVar8.Value=true; + RoundTripSparseObjectMulti.Property tempVar9=new RoundTripSparseObjectMulti.Property(); + tempVar9.setPath("a.d"); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar9.Value = new byte[] { 0x01, 0x02, 0x03 }; + tempVar9.Value=new byte[]{0x01,0x02,0x03}; + RoundTripSparseObjectMulti.Property tempVar10=new RoundTripSparseObjectMulti.Property(); + tempVar10.setPath("a.e"); + tempVar10.Value=NullValue.Default; + tempVar6.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectMulti.Property[]{tempVar7,tempVar8,tempVar9,tempVar10}; + RoundTripSparseObjectMulti.Expected tempVar11=new RoundTripSparseObjectMulti.Expected(); + tempVar11.Json="{'path': 'b', 'type': {'type': 'object'}}"; + RoundTripSparseObjectMulti.Property tempVar12=new RoundTripSparseObjectMulti.Property(); + tempVar12.setPath("a.b"); + tempVar11.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectMulti.Property[]{tempVar12}; + RoundTripSparseObjectMulti.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectMulti.Expected[]{tempVar,tempVar3,tempVar6,tempVar11}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseObjectMulti.Expected expected:expectedSchemas) + { + String objectColumnSchema=String.format("{'path': 'a', 'type': {'type': 'object', 'properties': [%1$s] } }", + expected.Json); + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }", + objectColumnSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar13=new Namespace(); + tempVar13.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar13); + Layout layout=resolver.Resolve(new SchemaId(-1)); + Assert.AreEqual(1,layout.getColumns().Length,"Json: {0}",expected.Json); + LayoutColumn objCol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out objCol); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,objCol.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + // Verify the object doesn't exist. + LayoutObject objT=objCol.Type instanceof LayoutObject?(LayoutObject)objCol.Type:null; + assert objT!=null; + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.Create(tempRef_row,out field).Find(tempRef_row2,objCol.Path); + row=tempRef_row2.argValue; + row=tempRef_row.argValue; + tangible.RefObjecttempRef_row3=new tangible.RefObject(row); + tangible.RefObjecttempRef_field=new tangible.RefObject(field); + RowCursor scope; + tangible.OutObjecttempOut_scope=new tangible.OutObject(); + Result r=objT.ReadScope(tempRef_row3,tempRef_field,tempOut_scope); + scope=tempOut_scope.argValue; + field=tempRef_field.argValue; + row=tempRef_row3.argValue; + ResultAssert.NotFound(r,"Json: {0}",expected.Json); + + // Write the object and the nested column. + tangible.RefObjecttempRef_row4=new tangible.RefObject(row); + tangible.RefObjecttempRef_field2=new tangible.RefObject(field); + tangible.OutObjecttempOut_scope2=new tangible.OutObject(); + r=objT.WriteScope(tempRef_row4,tempRef_field2,objCol.TypeArgs,tempOut_scope2); + scope=tempOut_scope2.argValue; + field=tempRef_field2.argValue; + row=tempRef_row4.argValue; + ResultAssert.IsSuccess(r,"Json: {0}",expected.Json); + + for(java.lang.Iterablepermutation:expected.Props.Permute()) + { + for(RoundTripSparseObjectMulti.Property prop:permutation) + { + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + found=layout.TryFind(prop.Path,out col); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,col.Storage,"Json: {0}",expected.Json); + + RoundTripSparseObjectMulti.Closure tempVar14=new RoundTripSparseObjectMulti.Closure(); + tempVar14.Col=col; + tempVar14.Prop=prop.clone(); + tempVar14.Expected=expected.clone(); + tangible.RefObjecttempRef_row5=new tangible.RefObject(row); + tangible.RefObjecttempRef_scope=new tangible.RefObject(scope); + this.LayoutCodeSwitch(col.Type.LayoutCode, + tempRef_row5,tempRef_scope,tempVar14.clone()); + scope=tempRef_scope.argValue; + row=tempRef_row5.argValue; + } + } + + // Write something after the scope. + UtfAnyString otherColumnPath="not-"+objCol.Path; + tangible.RefObjecttempRef_row6=new tangible.RefObject(row); + RowCursor otherColumn; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + field.Clone(out otherColumn).Find(tempRef_row6,otherColumnPath); + row=tempRef_row6.argValue; + tangible.RefObjecttempRef_row7=new tangible.RefObject(row); + tangible.RefObjecttempRef_otherColumn= + new tangible.RefObject(otherColumn); + r=LayoutType.Boolean.WriteSparse(tempRef_row7,tempRef_otherColumn,true); + otherColumn=tempRef_otherColumn.argValue; + row=tempRef_row7.argValue; + ResultAssert.IsSuccess(r,"Json: {0}",expected.Json); + + // Overwrite the whole scope. + tangible.RefObjecttempRef_row8=new tangible.RefObject(row); + tangible.RefObjecttempRef_field3=new tangible.RefObject(field); + r=LayoutType.Null.WriteSparse(tempRef_row8,tempRef_field3,NullValue.Default); + field=tempRef_field3.argValue; + row=tempRef_row8.argValue; + ResultAssert.IsSuccess(r,"Json: {0}",expected.Json); + tangible.RefObjecttempRef_row9=new tangible.RefObject(row); + tangible.RefObjecttempRef_field4=new tangible.RefObject(field); + RowCursor _; + tangible.OutObjecttempOut__=new tangible.OutObject(); + r=objT.ReadScope(tempRef_row9,tempRef_field4,tempOut__); + _=tempOut__.argValue; + field=tempRef_field4.argValue; + row=tempRef_row9.argValue; + ResultAssert.TypeMismatch(r,"Json: {0}",expected.Json); + + // Read the thing after the scope and verify it is still there. + tangible.RefObjecttempRef_row10=new tangible.RefObject(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + field.Clone(out otherColumn).Find(tempRef_row10,otherColumnPath); + row=tempRef_row10.argValue; + tangible.RefObjecttempRef_row11=new tangible.RefObject(row); + tangible.RefObjecttempRef_otherColumn2= + new tangible.RefObject(otherColumn); + boolean notScope; + tangible.OutObject tempOut_notScope=new tangible.OutObject(); + r=LayoutType.Boolean.ReadSparse(tempRef_row11,tempRef_otherColumn2,tempOut_notScope); + notScope=tempOut_notScope.argValue; + otherColumn=tempRef_otherColumn2.argValue; + row=tempRef_row11.argValue; + ResultAssert.IsSuccess(r,"Json: {0}",expected.Json); + assert notScope; + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaSparseObjectNested() +public final void ParseSchemaSparseObjectNested() + { + // Test nested sparse object columns with various kinds of sparse column fields. + RoundTripSparseObjectNested.Expected tempVar=new RoundTripSparseObjectNested.Expected(); + tempVar.Json="{'path': 'c', 'type': {'type': 'int8'}}"; + RoundTripSparseObjectNested.Property tempVar2=new RoundTripSparseObjectNested.Property(); + tempVar2.setPath("a.b.c"); + tempVar2.Value=(byte)42; + tempVar.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectNested.Property[]{tempVar2}; + RoundTripSparseObjectNested.Expected tempVar3=new RoundTripSparseObjectNested.Expected(); + tempVar3.Json="{'path': 'b', 'type': {'type': 'int8'}}, {'path': 'c', 'type': {'type': 'utf8'}}"; + RoundTripSparseObjectNested.Property tempVar4=new RoundTripSparseObjectNested.Property(); + tempVar4.setPath("a.b.b"); + tempVar4.Value=(byte)42; + RoundTripSparseObjectNested.Property tempVar5=new RoundTripSparseObjectNested.Property(); + tempVar5.setPath("a.b.c"); + tempVar5.Value="abc"; + tempVar3.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectNested.Property[]{tempVar4,tempVar5}; + RoundTripSparseObjectNested.Expected tempVar6=new RoundTripSparseObjectNested.Expected(); + tempVar6.Json="{'path': 'b', 'type': {'type': 'int8'}}, {'path': 'c', 'type': {'type': 'bool'}}, {'path': 'd', " + + "'type': {'type': 'binary'}}, {'path': 'e', 'type': {'type': 'null'}}"; + RoundTripSparseObjectNested.Property tempVar7=new RoundTripSparseObjectNested.Property(); + tempVar7.setPath("a.b.b"); + tempVar7.Value=(byte)42; + RoundTripSparseObjectNested.Property tempVar8=new RoundTripSparseObjectNested.Property(); + tempVar8.setPath("a.b.c"); + tempVar8.Value=true; + RoundTripSparseObjectNested.Property tempVar9=new RoundTripSparseObjectNested.Property(); + tempVar9.setPath("a.b.d"); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar9.Value = new byte[] { 0x01, 0x02, 0x03 }; + tempVar9.Value=new byte[]{0x01,0x02,0x03}; + RoundTripSparseObjectNested.Property tempVar10=new RoundTripSparseObjectNested.Property(); + tempVar10.setPath("a.b.e"); + tempVar10.Value=NullValue.Default; + tempVar6.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectNested.Property[]{tempVar7,tempVar8,tempVar9,tempVar10}; + RoundTripSparseObjectNested.Expected tempVar11=new RoundTripSparseObjectNested.Expected(); + tempVar11.Json="{'path': 'b', 'type': {'type': 'object'}}"; + RoundTripSparseObjectNested.Property tempVar12=new RoundTripSparseObjectNested.Property(); + tempVar12.setPath("a.b.b"); + tempVar11.Props= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectNested.Property[]{tempVar12}; + RoundTripSparseObjectNested.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseObjectNested.Expected[]{tempVar,tempVar3,tempVar6,tempVar11}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseObjectNested.Expected expected:expectedSchemas) + { + String nestedColumnSchema=String.format("{'path': 'b', 'type': {'type': 'object', 'properties': [%1$s] } }", + expected.Json); + String objectColumnSchema=String.format("{'path': 'a', 'type': {'type': 'object', 'properties': [%1$s] } }", + nestedColumnSchema); + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }", + objectColumnSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar13=new Namespace(); + tempVar13.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar13); + Layout layout=resolver.Resolve(new SchemaId(-1)); + LayoutColumn objCol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out objCol); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,objCol.Storage,"Json: {0}",expected.Json); + LayoutColumn objCol2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + found=layout.TryFind("a.b",out objCol2); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,objCol2.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + // Write the object. + LayoutObject objT=objCol.Type instanceof LayoutObject?(LayoutObject)objCol.Type:null; + assert objT!=null; + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out field).Find(tempRef_row2,objCol.Path); + row=tempRef_row2.argValue; + tangible.RefObjecttempRef_row3=new tangible.RefObject(row); + tangible.RefObjecttempRef_field=new tangible.RefObject(field); + RowCursor _; + tangible.OutObjecttempOut__=new tangible.OutObject(); + Result r=objT.WriteScope(tempRef_row3,tempRef_field,objCol.TypeArgs,tempOut__); + _=tempOut__.argValue; + field=tempRef_field.argValue; + row=tempRef_row3.argValue; + ResultAssert.IsSuccess(r,"Json: {0}",expected.Json); + + for(java.lang.Iterablepermutation:expected.Props.Permute()) + { + for(RoundTripSparseObjectNested.Property prop:permutation) + { + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + found=layout.TryFind(prop.Path,out col); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,col.Storage,"Json: {0}",expected.Json); + + RoundTripSparseObjectNested.Closure tempVar14=new RoundTripSparseObjectNested.Closure(); + tempVar14.Col=col; + tempVar14.Prop=prop.clone(); + tempVar14.Expected=expected.clone(); + tangible.RefObjecttempRef_row4=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(col.Type.LayoutCode, + tempRef_row4,tempRef_root,tempVar14.clone()); + root=tempRef_root.argValue; + row=tempRef_row4.argValue; + } + } + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaSparseArray() +public final void ParseSchemaSparseArray() + { + // Test all fixed column types. + RoundTripSparseArray.Expected tempVar=new RoundTripSparseArray.Expected(); + tempVar.Json="array[null]"; + tempVar.Type=LayoutType.Null; + tempVar.Value=new ArrayList(Arrays.asList(NullValue.Default,NullValue.Default,NullValue.Default)); + RoundTripSparseArray.Expected tempVar2=new RoundTripSparseArray.Expected(); + tempVar2.Json="array[bool]"; + tempVar2.Type=LayoutType.Boolean; + tempVar2.Value=new ArrayList(Arrays.asList(true,false,true)); + RoundTripSparseArray.Expected tempVar3=new RoundTripSparseArray.Expected(); + tempVar3.Json="array[int8]"; + tempVar3.Type=LayoutType.Int8; + tempVar3.Value=new ArrayList(Arrays.asList((byte)42,(byte)43,(byte)44)); + RoundTripSparseArray.Expected tempVar4=new RoundTripSparseArray.Expected(); + tempVar4.Json="array[int16]"; + tempVar4.Type=LayoutType.Int16; + tempVar4.Value=new ArrayList(Arrays.asList((short)42,(short)43,(short)44)); + RoundTripSparseArray.Expected tempVar5=new RoundTripSparseArray.Expected(); + tempVar5.Json="array[int32]"; + tempVar5.Type=LayoutType.Int32; + tempVar5.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseArray.Expected tempVar6=new RoundTripSparseArray.Expected(); + tempVar6.Json="array[int64]"; + tempVar6.Type=LayoutType.Int64; + tempVar6.Value=new ArrayList(Arrays.asList(42L,43L,44L)); + RoundTripSparseArray.Expected tempVar7=new RoundTripSparseArray.Expected(); + tempVar7.Json="array[uint8]"; + tempVar7.Type=LayoutType.UInt8; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar7.Value = new List { (byte)42, (byte)43, (byte)44 }; + tempVar7.Value=new ArrayList(Arrays.asList((byte)42,(byte)43,(byte)44)); + RoundTripSparseArray.Expected tempVar8=new RoundTripSparseArray.Expected(); + tempVar8.Json="array[uint16]"; + tempVar8.Type=LayoutType.UInt16; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar8.Value = new List { (ushort)42, (ushort)43, (ushort)44 }; + tempVar8.Value=new ArrayList(Arrays.asList((short)42,(short)43,(short)44)); + RoundTripSparseArray.Expected tempVar9=new RoundTripSparseArray.Expected(); + tempVar9.Json="array[uint32]"; + tempVar9.Type=LayoutType.UInt32; + tempVar9.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseArray.Expected tempVar10=new RoundTripSparseArray.Expected(); + tempVar10.Json="array[uint64]"; + tempVar10.Type=LayoutType.UInt64; + tempVar10.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseArray.Expected tempVar11=new RoundTripSparseArray.Expected(); + tempVar11.Json="array[varint]"; + tempVar11.Type=LayoutType.VarInt; + tempVar11.Value=new ArrayList(Arrays.asList(42L,43L,44L)); + RoundTripSparseArray.Expected tempVar12=new RoundTripSparseArray.Expected(); + tempVar12.Json="array[varuint]"; + tempVar12.Type=LayoutType.VarUInt; + tempVar12.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseArray.Expected tempVar13=new RoundTripSparseArray.Expected(); + tempVar13.Json="array[float32]"; + tempVar13.Type=LayoutType.Float32; + tempVar13.Value=new ArrayList(Arrays.asList(4.2F,4.3F,4.4F)); + RoundTripSparseArray.Expected tempVar14=new RoundTripSparseArray.Expected(); + tempVar14.Json="array[float64]"; + tempVar14.Type=LayoutType.Float64; + tempVar14.Value=new ArrayList(Arrays.asList(4.2,4.3,4.4)); + RoundTripSparseArray.Expected tempVar15=new RoundTripSparseArray.Expected(); + tempVar15.Json="array[float128]"; + tempVar15.Type=LayoutType.Float128; + tempVar15.Value=new ArrayList(Arrays.asList(new Float128(0,42),new Float128(0,43),new Float128(0,44))); + RoundTripSparseArray.Expected tempVar16=new RoundTripSparseArray.Expected(); + tempVar16.Json="array[decimal]"; + tempVar16.Type=LayoutType.Decimal; + tempVar16.Value=new ArrayList(Arrays.asList(4.2,4.3,4.4)); + RoundTripSparseArray.Expected tempVar17=new RoundTripSparseArray.Expected(); + tempVar17.Json="array[datetime]"; + tempVar17.Type=LayoutType.DateTime; + tempVar17.Value=new ArrayList(Arrays.asList(LocalDateTime.UtcNow,LocalDateTime.UtcNow.AddTicks(1), + LocalDateTime.UtcNow.AddTicks(2))); + RoundTripSparseArray.Expected tempVar18=new RoundTripSparseArray.Expected(); + tempVar18.Json="array[unixdatetime]"; + tempVar18.Type=LayoutType.UnixDateTime; + tempVar18.Value=new ArrayList(Arrays.asList(new UnixDateTime(1),new UnixDateTime(2),new UnixDateTime(3))); + RoundTripSparseArray.Expected tempVar19=new RoundTripSparseArray.Expected(); + tempVar19.Json="array[guid]"; + tempVar19.Type=LayoutType.Guid; + tempVar19.Value=new ArrayList(Arrays.asList(UUID.NewGuid(),UUID.NewGuid(),UUID.NewGuid())); + RoundTripSparseArray.Expected tempVar20=new RoundTripSparseArray.Expected(); + tempVar20.Json="array[mongodbobjectid]"; + tempVar20.Type=LayoutType.MongoDbObjectId; + tempVar20.Value=new ArrayList(Arrays.asList(new MongoDbObjectId(0,1),new MongoDbObjectId(0,2), + new MongoDbObjectId(0,3))); + RoundTripSparseArray.Expected tempVar21=new RoundTripSparseArray.Expected(); + tempVar21.Json="array[utf8]"; + tempVar21.Type=LayoutType.Utf8; + tempVar21.Value=new ArrayList(Arrays.asList("abc","def","xyz")); + RoundTripSparseArray.Expected tempVar22=new RoundTripSparseArray.Expected(); + tempVar22.Json="array[binary]"; + tempVar22.Type=LayoutType.Binary; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar22.Value = new List { new byte[] { 0x01, 0x02 }, new byte[] { 0x03, 0x04 }, new + // byte[] { 0x05, 0x06 } }; + tempVar22.Value=new ArrayList(Arrays.asList(new Byte[]{0x01,0x02},new byte[]{0x03,0x04},new byte[]{0x05, + 0x06})); + RoundTripSparseArray.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseArray.Expected[]{tempVar,tempVar2,tempVar3,tempVar4,tempVar5,tempVar6,tempVar7,tempVar8,tempVar9,tempVar10,tempVar11,tempVar12,tempVar13,tempVar14,tempVar15,tempVar16,tempVar17,tempVar18,tempVar19,tempVar20,tempVar21,tempVar22}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseArray.Expected expected:expectedSchemas) + { + for(java.lang.Class arrT:new java.lang.Class[]{LayoutTypedArray.class,LayoutArray.class}) + { + String arrayColumnSchema="{'path': 'a', 'type': {'type': 'array', 'items': {'type': 'any'}} }"; + if(arrT==LayoutTypedArray.class) + { + arrayColumnSchema=String.format("{'path': 'a', 'type': {'type': 'array',"+"\r\n"+ + " 'items': {'type': '%1$s', 'nullable': " + + "false }} }",expected.Type.getName()); + } + + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }", + arrayColumnSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar23=new Namespace(); + tempVar23.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar23); + Layout layout=resolver.Resolve(new SchemaId(-1)); + LayoutColumn arrCol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out arrCol); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,arrCol.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripSparseArray.Closure tempVar24=new RoundTripSparseArray.Closure(); + tempVar24.ArrCol=arrCol; + tempVar24.Expected=expected.clone(); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(expected.Type.LayoutCode,tempRef_row2, + tempRef_root,tempVar24.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")][SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1139", +// Justification = "Need to control the binary ordering.")] public void ParseSchemaSparseSet() +public final void ParseSchemaSparseSet() + { + // Test all fixed column types. + RoundTripSparseSet.Expected tempVar=new RoundTripSparseSet.Expected(); + tempVar.Json="set[null]"; + tempVar.Type=LayoutType.Null; + tempVar.Value=new ArrayList(Arrays.asList(NullValue.Default)); + RoundTripSparseSet.Expected tempVar2=new RoundTripSparseSet.Expected(); + tempVar2.Json="set[bool]"; + tempVar2.Type=LayoutType.Boolean; + tempVar2.Value=new ArrayList(Arrays.asList(false,true)); + RoundTripSparseSet.Expected tempVar3=new RoundTripSparseSet.Expected(); + tempVar3.Json="set[int8]"; + tempVar3.Type=LayoutType.Int8; + tempVar3.Value=new ArrayList(Arrays.asList((byte)42,(byte)43,(byte)44)); + RoundTripSparseSet.Expected tempVar4=new RoundTripSparseSet.Expected(); + tempVar4.Json="set[int16]"; + tempVar4.Type=LayoutType.Int16; + tempVar4.Value=new ArrayList(Arrays.asList((short)42,(short)43,(short)44)); + RoundTripSparseSet.Expected tempVar5=new RoundTripSparseSet.Expected(); + tempVar5.Json="set[int32]"; + tempVar5.Type=LayoutType.Int32; + tempVar5.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseSet.Expected tempVar6=new RoundTripSparseSet.Expected(); + tempVar6.Json="set[int64]"; + tempVar6.Type=LayoutType.Int64; + tempVar6.Value=new ArrayList(Arrays.asList(42L,43L,44L)); + RoundTripSparseSet.Expected tempVar7=new RoundTripSparseSet.Expected(); + tempVar7.Json="set[uint8]"; + tempVar7.Type=LayoutType.UInt8; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar7.Value = new List { (byte)42, (byte)43, (byte)44 }; + tempVar7.Value=new ArrayList(Arrays.asList((byte)42,(byte)43,(byte)44)); + RoundTripSparseSet.Expected tempVar8=new RoundTripSparseSet.Expected(); + tempVar8.Json="set[uint16]"; + tempVar8.Type=LayoutType.UInt16; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar8.Value = new List { (ushort)42, (ushort)43, (ushort)44 }; + tempVar8.Value=new ArrayList(Arrays.asList((short)42,(short)43,(short)44)); + RoundTripSparseSet.Expected tempVar9=new RoundTripSparseSet.Expected(); + tempVar9.Json="set[uint32]"; + tempVar9.Type=LayoutType.UInt32; + tempVar9.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseSet.Expected tempVar10=new RoundTripSparseSet.Expected(); + tempVar10.Json="set[uint64]"; + tempVar10.Type=LayoutType.UInt64; + tempVar10.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseSet.Expected tempVar11=new RoundTripSparseSet.Expected(); + tempVar11.Json="set[varint]"; + tempVar11.Type=LayoutType.VarInt; + tempVar11.Value=new ArrayList(Arrays.asList(42L,43L,44L)); + RoundTripSparseSet.Expected tempVar12=new RoundTripSparseSet.Expected(); + tempVar12.Json="set[varuint]"; + tempVar12.Type=LayoutType.VarUInt; + tempVar12.Value=new ArrayList(Arrays.asList(42,43,44)); + RoundTripSparseSet.Expected tempVar13=new RoundTripSparseSet.Expected(); + tempVar13.Json="set[float32]"; + tempVar13.Type=LayoutType.Float32; + tempVar13.Value=new ArrayList(Arrays.asList(4.2F,4.3F,4.4F)); + RoundTripSparseSet.Expected tempVar14=new RoundTripSparseSet.Expected(); + tempVar14.Json="set[float64]"; + tempVar14.Type=LayoutType.Float64; + tempVar14.Value=new ArrayList(Arrays.asList((double)0xAAAAAAAAAAAAAAAA,(double)0xBBBBBBBBBBBBBBBB, + (double)0xCCCCCCCCCCCCCCCC)); + RoundTripSparseSet.Expected tempVar15=new RoundTripSparseSet.Expected(); + tempVar15.Json="set[decimal]"; + tempVar15.Type=LayoutType.Decimal; + tempVar15.Value=new ArrayList(Arrays.asList(4.2,4.3,4.4)); + RoundTripSparseSet.Expected tempVar16=new RoundTripSparseSet.Expected(); + tempVar16.Json="set[datetime]"; + tempVar16.Type=LayoutType.DateTime; + tempVar16.Value=new ArrayList(Arrays.asList(LocalDateTime.of(1,DateTimeKind.Unspecified), + LocalDateTime.of(2,DateTimeKind.Unspecified),LocalDateTime.of(3,DateTimeKind.Unspecified))); + RoundTripSparseSet.Expected tempVar17=new RoundTripSparseSet.Expected(); + tempVar17.Json="set[guid]"; + tempVar17.Type=LayoutType.Guid; + tempVar17.Value=new ArrayList(Arrays.asList(UUID.fromString("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"), + UUID.fromString("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB"),UUID.fromString("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC"))); + RoundTripSparseSet.Expected tempVar18=new RoundTripSparseSet.Expected(); + tempVar18.Json="set[utf8]"; + tempVar18.Type=LayoutType.Utf8; + tempVar18.Value=new ArrayList(Arrays.asList("abc","def","xyz")); + RoundTripSparseSet.Expected tempVar19=new RoundTripSparseSet.Expected(); + tempVar19.Json="set[binary]"; + tempVar19.Type=LayoutType.Binary; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar19.Value = new List { new byte[] { 0x01, 0x02 }, new byte[] { 0x03, 0x04 }, new + // byte[] { 0x05, 0x06 } }; + tempVar19.Value=new ArrayList(Arrays.asList(new Byte[]{0x01,0x02},new byte[]{0x03,0x04},new byte[]{0x05, + 0x06})); + RoundTripSparseSet.Expected[]expectedSchemas= + new azure.data.cosmos.serialization.hybridrow.unit.layoutcompilerunittests.RoundTripSparseSet.Expected[]{tempVar,tempVar2,tempVar3,tempVar4,tempVar5,tempVar6,tempVar7,tempVar8,tempVar9,tempVar10,tempVar11,tempVar12,tempVar13,tempVar14,tempVar15,tempVar16,tempVar17,tempVar18,tempVar19}; + + RowBuffer row=new RowBuffer(LayoutCompilerUnitTests.InitialRowSize); + for(RoundTripSparseSet.Expected expected:expectedSchemas) + { + for(java.lang.Class setT:new java.lang.Class[]{LayoutTypedSet.class}) + { + String setColumnSchema="{'path': 'a', 'type': {'type': 'set', 'items': {'type': 'any'}} }"; + if(setT==LayoutTypedSet.class) + { + setColumnSchema=String.format("{'path': 'a', 'type': {'type': 'set', "+"\r\n"+ + " 'items': {'type': '%1$s', 'nullable': " + + "false }} }",expected.Type.getName()); + } + + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }", + setColumnSchema); + Schema s=Schema.Parse(tableSchema); + Namespace tempVar20=new Namespace(); + tempVar20.setSchemas(new ArrayList(Arrays.asList(s))); + LayoutResolverNamespace resolver=new LayoutResolverNamespace(tempVar20); + Layout layout=resolver.Resolve(new SchemaId(-1)); + LayoutColumn setCol; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found=layout.TryFind("a",out setCol); + Assert.IsTrue(found,"Json: {0}",expected.Json); + Assert.AreEqual(StorageKind.Sparse,setCol.Storage,"Json: {0}",expected.Json); + + // Try writing a row using the layout. + row.Reset(); + row.InitLayout(HybridRowVersion.V1,layout,resolver); + + HybridRowHeader header=row.getHeader().clone(); + assert HybridRowVersion.V1==header.getVersion(); + assert layout.getSchemaId().clone()==header.getSchemaId().clone(); + + tangible.RefObjecttempRef_row=new tangible.RefObject(row); + RowCursor root=RowCursor.Create(tempRef_row); + row=tempRef_row.argValue; + RoundTripSparseSet.Closure tempVar21=new RoundTripSparseSet.Closure(); + tempVar21.SetCol=setCol; + tempVar21.Expected=expected.clone(); + tangible.RefObjecttempRef_row2=new tangible.RefObject(row); + tangible.RefObjecttempRef_root=new tangible.RefObject(root); + this.LayoutCodeSwitch(expected.Type.LayoutCode,tempRef_row2, + tempRef_root,tempVar21.clone()); + root=tempRef_root.argValue; + row=tempRef_row2.argValue; + } + } + } + +/** + * Ensure that a parent scope exists in the row. + * + * @param row The row to create the desired scope. + * @param root The root scope. + * @param col The scope to create. + * @param tag A string to tag errors with. + * @return The enclosing scope. + */ +private static RowCursor EnsureScope(tangible.RefObject row,tangible.RefObject root, + LayoutColumn col,String tag) + { + if(col==null) + { + return root.argValue.clone(); + } + + RowCursor parentScope=LayoutCompilerUnitTests.EnsureScope(row,root,col.getParent(),tag); + + azure.data.cosmos.serialization.hybridrow.layouts.LayoutType tempVar=col.getType(); + LayoutObject pT=tempVar instanceof LayoutObject?(LayoutObject)tempVar:null; + assert pT!=null; + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot + // be converted using the 'Out' helper class unless the method is within the code being modified: + parentScope.Clone(out field).Find(row,col.getPath()); + tangible.RefObjecttempRef_field=new tangible.RefObject(field); + RowCursor scope; + tangible.OutObjecttempOut_scope=new tangible.OutObject(); + Result r=pT.ReadScope(row,tempRef_field,tempOut_scope); + scope=tempOut_scope.argValue; + field=tempRef_field.argValue; + if(r==Result.NotFound) + { + tangible.RefObjecttempRef_field2=new tangible.RefObject(field); + tangible.OutObjecttempOut_scope2=new tangible.OutObject(); + r=pT.WriteScope(row,tempRef_field2,col.getTypeArgs().clone(),tempOut_scope2); + scope=tempOut_scope2.argValue; + field=tempRef_field2.argValue; + } + + ResultAssert.IsSuccess(r,tag); + return scope; + } + +// TODO: C# TO JAVA CONVERTER: The C# 'new()' constraint has no equivalent in Java: +//ORIGINAL LINE: private void LayoutCodeSwitch(LayoutCode code, ref RowBuffer row, ref +// RowCursor scope, TClosure closure) where TDispatcher : TestActionDispatcher, new() +private, TClosure> void LayoutCodeSwitch(LayoutCode code, + tangible.RefObject row,tangible.RefObject scope,TClosure closure) + { + TDispatcher dispatcher=new TDispatcher(); + switch(code) + { + case Null: + dispatcher.Dispatch(row,scope,closure); + break; + case Boolean: + dispatcher.Dispatch(row,scope,closure); + break; + case Int8: + dispatcher.Dispatch(row,scope,closure); + break; + case Int16: + dispatcher.Dispatch(row,scope,closure); + break; + case Int32: + dispatcher.Dispatch(row,scope,closure); + break; + case Int64: + dispatcher.Dispatch(row,scope,closure); + break; + case UInt8: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: dispatcher.Dispatch(ref row, ref scope, closure); + dispatcher.Dispatch(row,scope,closure); + break; + case UInt16: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: dispatcher.Dispatch(ref row, ref scope, closure); + dispatcher.Dispatch(row,scope,closure); + break; + case UInt32: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: dispatcher.Dispatch(ref row, ref scope, closure); + dispatcher.Dispatch(row,scope,closure); + break; + case UInt64: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: dispatcher.Dispatch(ref row, ref scope, closure); + dispatcher.Dispatch(row,scope,closure); + break; + case VarInt: + dispatcher.Dispatch(row,scope,closure); + break; + case VarUInt: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: dispatcher.Dispatch(ref row, ref scope, closure); + dispatcher.Dispatch(row,scope,closure); + break; + case Float32: + dispatcher.Dispatch(row,scope,closure); + break; + case Float64: + dispatcher.Dispatch(row,scope,closure); + break; + case Float128: + dispatcher.Dispatch(row,scope,closure); + break; + case Decimal: + dispatcher.Dispatch(row,scope,closure); + break; + case DateTime: + dispatcher.Dispatch(row,scope,closure); + break; + case UnixDateTime: + dispatcher.Dispatch(row,scope,closure); + break; + case Guid: + dispatcher.Dispatch(row,scope,closure); + break; + case MongoDbObjectId: + dispatcher.Dispatch(row,scope,closure); + break; + case Utf8: + dispatcher.Dispatch(row,scope,closure); + break; + case Binary: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: dispatcher.Dispatch(ref row, ref scope, closure); + dispatcher.Dispatch(row,scope,closure); + break; + case ObjectScope: + dispatcher.DispatchObject(row,scope,closure); + break; +default: + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s",code)); + break; + } + } + +private final static class RoundTripFixed extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn col = closure.Col; + Expected expected = closure.Expected.clone(); + Result r; + TValue value; + + System.out.printf("%1$s" + "\r\n", expected.Json); + TLayout t = (TLayout)col.type(); + if (LayoutBit.opNotEquals(col.getNullBit().clone(), + LayoutBit.INVALID)) { + Out tempOut_value = new Out(); + r = t.ReadFixed(row, root, col, tempOut_value); + value = tempOut_value.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + } else { + Out tempOut_value2 = new Out(); + r = t.ReadFixed(row, root, col, tempOut_value2); + value = tempOut_value2.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + boolean tempVar = expected.Default instanceof Array; + Array defaultArray = tempVar ? (Array)expected.Default : null; + if (tempVar) { + CollectionAssert.AreEqual(defaultArray, (Collection)value, "Json: {0}", expected.Json); + } else { + Assert.AreEqual(expected.Default, value, "Json: {0}", expected.Json); + } + } + + r = t.WriteFixed(row, root, col, (TValue)expected.Value); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Out tempOut_value3 = new Out(); + r = t.ReadFixed(row, root, col, tempOut_value3); + value = tempOut_value3.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + boolean tempVar2 = expected.Value instanceof Array; + Array array = tempVar2 ? (Array)expected.Value : null; + if (tempVar2) { + CollectionAssert.AreEqual(array, (Collection)value, "Json: {0}", expected.Json); + } else { + Assert.AreEqual(expected.Value, value, "Json: {0}", expected.Json); + } + + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(t.WriteFixed(row, ref roRoot, col, (TValue)expected.Value)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(t.DeleteFixed(row, ref roRoot, col)); + + if (LayoutBit.opNotEquals(col.getNullBit().clone(), + LayoutBit.INVALID)) { + ResultAssert.IsSuccess(t.DeleteFixed(row, root, col)); + } else { + ResultAssert.TypeMismatch(t.DeleteFixed(row, root, col)); + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn Col; + public Expected Expected = new Expected(); + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.Col = this.Col; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public Object Default; + public String Json; + public int Length; + public String TypeName; + public Object Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.TypeName = this.TypeName; + varCopy.Json = this.Json; + varCopy.Value = this.Value; + varCopy.Default = this.Default; + varCopy.Length = this.Length; + + return varCopy; + } + } +} + +private final static class RoundTripSparseArray extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn arrCol = closure.ArrCol; + LayoutType tempVar = arrCol.type(); + LayoutIndexedScope arrT = tempVar instanceof LayoutIndexedScope ? (LayoutIndexedScope)tempVar : null; + Expected expected = closure.Expected.clone(); + String tag = String.format("Json: %1$s, Array: %2$s", expected.Json, arrCol.type().getName()); + + System.out.println(tag); + Assert.IsNotNull(arrT, tag); + + TLayout t = (TLayout)expected.Type; + + // Verify the array doesn't yet exist. + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out field).Find(row, arrCol.path()); + Reference tempReference_field = + new Reference(field); + RowCursor scope; + Out tempOut_scope = + new Out(); + Result r = arrT.ReadScope(row, tempReference_field, tempOut_scope); + scope = tempOut_scope.get(); + field = tempReference_field.get(); + ResultAssert.NotFound(r, tag); + + // Write the array. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = arrT.WriteScope(row, ref field, arrCol.typeArgs().clone(), out scope); + ResultAssert.IsSuccess(r, tag); + + // Verify the nested field doesn't yet appear within the new scope. + assert !scope.MoveNext(row); + TValue value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref scope, out value); + ResultAssert.NotFound(r, tag); + + // Write the nested fields. + RowCursor elm; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope.Clone(out elm); + for (Object item : expected.Value) { + // Write the ith index. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.WriteSparse(row, ref elm, (TValue)item); + ResultAssert.IsSuccess(r, tag); + + // Move cursor to the ith+1 index. + assert !elm.MoveNext(row); + } + + // Read the array and the nested column, validate the nested column has the proper value. + Reference tempReference_field2 = + new Reference(field); + RowCursor scope2; + Out tempOut_scope2 = + new Out(); + r = arrT.ReadScope(row, tempReference_field2, tempOut_scope2); + scope2 = tempOut_scope2.get(); + field = tempReference_field2.get(); + ResultAssert.IsSuccess(r, tag); + Assert.AreEqual(scope.ScopeType, scope2.ScopeType, tag); + Assert.AreEqual(scope.start(), scope2.start(), tag); + Assert.AreEqual(scope.Immutable, scope2.Immutable, tag); + + // Read the nested fields + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope2.Clone(out elm); + for (Object item : expected.Value) { + assert elm.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref elm, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar2 = item instanceof Array; + Array array = tempVar2 ? (Array)item : null; + if (tempVar2) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual((TValue)item, value, tag); + } + } + + // Delete an item. + int indexToDelete = 1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert scope2.Clone(out elm).MoveTo(row, indexToDelete); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.DeleteSparse(row, ref elm); + ResultAssert.IsSuccess(r, tag); + ArrayList remainingValues = new ArrayList(expected.Value); + remainingValues.remove(indexToDelete); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope2.Clone(out elm); + for (Object item : remainingValues) { + assert elm.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref elm, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar3 = item instanceof Array; + Array array = tempVar3 ? (Array)item : null; + if (tempVar3) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual(item, value, tag); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert !scope2.Clone(out elm).MoveTo(row, remainingValues.size()); + + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot).Find(row, arrCol.path()); + Reference tempReference_roRoot = + new Reference(roRoot); + ResultAssert.InsufficientPermissions(arrT.DeleteScope(row, tempReference_roRoot)); + roRoot = tempReference_roRoot.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(arrT.WriteScope(row, ref roRoot, arrCol.typeArgs().clone(), + out scope2)); + + // Overwrite the whole scope. + Reference tempReference_field3 = + new Reference(field); + r = LayoutType.Null.writeSparse(row, tempReference_field3, NullValue.DEFAULT); + field = tempReference_field3.get(); + ResultAssert.IsSuccess(r, tag); + Reference tempReference_field4 = + new Reference(field); + RowCursor _; + Out tempOut__ = + new Out(); + r = arrT.ReadScope(row, tempReference_field4, tempOut__); + _ = tempOut__.get(); + field = tempReference_field4.get(); + ResultAssert.TypeMismatch(r, tag); + Reference tempReference_field5 = + new Reference(field); + r = arrT.DeleteScope(row, tempReference_field5); + field = tempReference_field5.get(); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + + // Overwrite it again, then delete it. + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = arrT.WriteScope(row, ref field, arrCol.typeArgs().clone(), out _, UpdateOptions.Update); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field6 = + new Reference(field); + r = arrT.DeleteScope(row, tempReference_field6); + field = tempReference_field6.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field7 = + new Reference(field); + RowCursor _; + Out tempOut__2 = + new Out(); + r = arrT.ReadScope(row, tempReference_field7, tempOut__2); + _ = tempOut__2.get(); + field = tempReference_field7.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn ArrCol; + public Expected Expected = new Expected(); + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.ArrCol = this.ArrCol; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public LayoutType Type; + public ArrayList Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Type = this.Type; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private final static class RoundTripSparseObject extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn objCol = closure.ObjCol; + LayoutType tempVar = objCol.type(); + LayoutObject objT = tempVar instanceof LayoutObject ? (LayoutObject)tempVar : null; + LayoutColumn col = closure.Col; + Expected expected = closure.Expected.clone(); + + System.out.printf("%1$s" + "\r\n", col.type().getName()); + Assert.IsNotNull(objT, "Json: {0}", expected.Json); + Assert.AreEqual(objCol, col.parent(), "Json: {0}", expected.Json); + + TLayout t = (TLayout)col.type(); + + // Attempt to read the object and the nested column. + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out field).Find(row, objCol.path()); + Reference tempReference_field = + new Reference(field); + RowCursor scope; + Out tempOut_scope = + new Out(); + Result r = objT.ReadScope(row, tempReference_field, tempOut_scope); + scope = tempOut_scope.get(); + field = tempReference_field.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + + // Write the object and the nested column. + Reference tempReference_field2 = + new Reference(field); + Out tempOut_scope2 = + new Out(); + r = objT.WriteScope(row, tempReference_field2, objCol.typeArgs().clone(), tempOut_scope2); + scope = tempOut_scope2.get(); + field = tempReference_field2.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + + // Verify the nested field doesn't yet appear within the new scope. + RowCursor nestedField; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope.Clone(out nestedField).Find(row, col.path()); + TValue value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref nestedField, out value); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + + // Write the nested field. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.WriteSparse(row, ref nestedField, (TValue)expected.Value); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + + // Read the object and the nested column, validate the nested column has the proper value. + Reference tempReference_field3 = + new Reference(field); + RowCursor scope2; + Out tempOut_scope2 = + new Out(); + r = objT.ReadScope(row, tempReference_field3, tempOut_scope2); + scope2 = tempOut_scope2.get(); + field = tempReference_field3.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Assert.AreEqual(scope.ScopeType, scope2.ScopeType, "Json: {0}", expected.Json); + Assert.AreEqual(scope.start(), scope2.start(), "Json: {0}", expected.Json); + Assert.AreEqual(scope.Immutable, scope2.Immutable, "Json: {0}", expected.Json); + + // Read the nested field + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope2.Clone(out nestedField).Find(row, col.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref nestedField, out value); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + boolean tempVar2 = expected.Value instanceof Array; + Array array = tempVar2 ? (Array)expected.Value : null; + if (tempVar2) { + CollectionAssert.AreEqual(array, (Collection)value, "Json: {0}", expected.Json); + } else { + Assert.AreEqual(expected.Value, value, "Json: {0}", expected.Json); + } + + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot).Find(row, objCol.path()); + Reference tempReference_roRoot = + new Reference(roRoot); + ResultAssert.InsufficientPermissions(objT.DeleteScope(row, tempReference_roRoot)); + roRoot = tempReference_roRoot.get(); + Reference tempReference_roRoot2 = + new Reference(roRoot); + Out tempOut_scope22 = + new Out(); + ResultAssert.InsufficientPermissions(objT.WriteScope(row, tempReference_roRoot2, objCol.typeArgs().clone(), + tempOut_scope22)); + scope2 = tempOut_scope22.get(); + roRoot = tempReference_roRoot2.get(); + + // Overwrite the whole scope. + Reference tempReference_field4 = + new Reference(field); + r = LayoutType.Null.writeSparse(row, tempReference_field4, NullValue.DEFAULT); + field = tempReference_field4.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field5 = + new Reference(field); + RowCursor _; + Out tempOut__ = + new Out(); + r = objT.ReadScope(row, tempReference_field5, tempOut__); + _ = tempOut__.get(); + field = tempReference_field5.get(); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + Reference tempReference_field6 = + new Reference(field); + r = objT.DeleteScope(row, tempReference_field6); + field = tempReference_field6.get(); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + + // Overwrite it again, then delete it. + Reference tempReference_field7 = + new Reference(field); + RowCursor _; + Out tempOut__2 = + new Out(); + r = objT.WriteScope(row, tempReference_field7, objCol.typeArgs().clone(), tempOut__2, UpdateOptions.Update); + _ = tempOut__2.get(); + field = tempReference_field7.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field8 = + new Reference(field); + r = objT.DeleteScope(row, tempReference_field8); + field = tempReference_field8.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field9 = + new Reference(field); + RowCursor _; + Out tempOut__3 = + new Out(); + r = objT.ReadScope(row, tempReference_field9, tempOut__3); + _ = tempOut__3.get(); + field = tempReference_field9.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn Col; + public Expected Expected = new Expected(); + public LayoutColumn ObjCol; + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.ObjCol = this.ObjCol; + varCopy.Col = this.Col; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public Object Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private final static class RoundTripSparseObjectMulti extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference scope, + Closure closure) { + LayoutColumn col = closure.Col; + Property prop = closure.Prop.clone(); + Expected expected = closure.Expected.clone(); + String tag = String.format("Prop: %2$s: Json: %1$s", expected.Json, prop.Path); + + System.out.println(tag); + + TLayout t = (TLayout)col.type(); + + // Verify the nested field doesn't yet appear within the new scope. + RowCursor nestedField; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope.get().Clone(out nestedField).Find(row, col.path()); + TValue value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + Result r = t.ReadSparse(row, ref nestedField, out value); + Assert.IsTrue(r == Result.NOT_FOUND || r == Result.TYPE_MISMATCH, tag); + + // Write the nested field. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.WriteSparse(row, ref nestedField, (TValue)prop.Value); + ResultAssert.IsSuccess(r, tag); + + // Read the nested field + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref nestedField, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar = prop.Value instanceof Array; + Array array = tempVar ? (Array)prop.Value : null; + if (tempVar) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual(prop.Value, value, tag); + } + + // Overwrite the nested field. + if (t instanceof LayoutNull) { + Reference tempReference_nestedField = + new Reference(nestedField); + r = LayoutType.Boolean.WriteSparse(row, tempReference_nestedField, false); + nestedField = tempReference_nestedField.get(); + ResultAssert.IsSuccess(r, tag); + } else { + Reference tempReference_nestedField2 = + new Reference(nestedField); + r = LayoutType.Null.writeSparse(row, tempReference_nestedField2, NullValue.DEFAULT); + nestedField = tempReference_nestedField2.get(); + ResultAssert.IsSuccess(r, tag); + } + + // Verify nested field no longer there. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref nestedField, out value); + ResultAssert.TypeMismatch(r, tag); + } + + @Override + public void DispatchObject(Reference row, Reference scope, + Closure closure) { + LayoutColumn col = closure.Col; + Property prop = closure.Prop.clone(); + Expected expected = closure.Expected.clone(); + String tag = String.format("Prop: %2$s: Json: %1$s", expected.Json, prop.Path); + + System.out.println(tag); + + LayoutObject t = (LayoutObject)col.type(); + + // Verify the nested field doesn't yet appear within the new scope. + RowCursor nestedField; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope.get().Clone(out nestedField).Find(row, col.path()); + Reference tempReference_nestedField = + new Reference(nestedField); + RowCursor scope2; + Out tempOut_scope2 = + new Out(); + Result r = t.ReadScope(row, tempReference_nestedField, tempOut_scope2); + scope2 = tempOut_scope2.get(); + nestedField = tempReference_nestedField.get(); + ResultAssert.NotFound(r, tag); + + // Write the nested field. + Reference tempReference_nestedField2 = + new Reference(nestedField); + Out tempOut_scope22 = + new Out(); + r = t.WriteScope(row, tempReference_nestedField2, col.typeArgs().clone(), tempOut_scope22); + scope2 = tempOut_scope22.get(); + nestedField = tempReference_nestedField2.get(); + ResultAssert.IsSuccess(r, tag); + + // Read the nested field + Reference tempReference_nestedField3 = + new Reference(nestedField); + RowCursor scope3; + Out tempOut_scope3 = + new Out(); + r = t.ReadScope(row, tempReference_nestedField3, tempOut_scope3); + scope3 = tempOut_scope3.get(); + nestedField = tempReference_nestedField3.get(); + ResultAssert.IsSuccess(r, tag); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Assert.AreEqual(scope2.AsReadOnly(out _).ScopeType, scope3.ScopeType, tag); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Assert.AreEqual(scope2.AsReadOnly(out _).start, scope3.start(), tag); + + // Overwrite the nested field. + Reference tempReference_nestedField4 = + new Reference(nestedField); + r = LayoutType.Null.writeSparse(row, tempReference_nestedField4, NullValue.DEFAULT); + nestedField = tempReference_nestedField4.get(); + ResultAssert.IsSuccess(r, tag); + + // Verify nested field no longer there. + Reference tempReference_nestedField5 = + new Reference(nestedField); + Out tempOut_scope32 = + new Out(); + r = t.ReadScope(row, tempReference_nestedField5, tempOut_scope32); + scope3 = tempOut_scope32.get(); + nestedField = tempReference_nestedField5.get(); + ResultAssert.TypeMismatch(r, tag); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn Col; + public Expected Expected = new Expected(); + public Property Prop = new Property(); + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.Col = this.Col; + varCopy.Prop = this.Prop.clone(); + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public Property[] Props; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Props = this.Props.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Property + public final static class Property { + public String Path; + public Object Value; + + public Property clone() { + Property varCopy = new Property(); + + varCopy.Path = this.Path; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private final static class RoundTripSparseObjectNested extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn col = closure.Col; + Property prop = closure.Prop.clone(); + Expected expected = closure.Expected.clone(); + String tag = String.format("Prop: %2$s: Json: %1$s", expected.Json, prop.Path); + + System.out.println(tag); + + TLayout t = (TLayout)col.type(); + + // Ensure scope exists. + RowCursor scope = LayoutCompilerUnitTests.EnsureScope(row, root, col.parent(), tag); + + // Write the nested field. + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + scope.Clone(out field).Find(row, col.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + Result r = t.WriteSparse(row, ref field, (TValue)prop.Value); + ResultAssert.IsSuccess(r, tag); + + // Read the nested field + TValue value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref field, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar = prop.Value instanceof Array; + Array array = tempVar ? (Array)prop.Value : null; + if (tempVar) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual(prop.Value, value, tag); + } + + // Overwrite the nested field. + if (t instanceof LayoutNull) { + Reference tempReference_field = + new Reference(field); + r = LayoutType.Boolean.WriteSparse(row, tempReference_field, false); + field = tempReference_field.get(); + ResultAssert.IsSuccess(r, tag); + } else { + Reference tempReference_field2 = + new Reference(field); + r = LayoutType.Null.writeSparse(row, tempReference_field2, NullValue.DEFAULT); + field = tempReference_field2.get(); + ResultAssert.IsSuccess(r, tag); + } + + // Verify nested field no longer there. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref field, out value); + ResultAssert.TypeMismatch(r, tag); + } + + @Override + public void DispatchObject(Reference row, Reference root, Closure closure) { + LayoutColumn col = closure.Col; + Property prop = closure.Prop.clone(); + Expected expected = closure.Expected.clone(); + String tag = String.format("Prop: %2$s: Json: %1$s", expected.Json, prop.Path); + + System.out.println(tag); + + // Ensure scope exists. + RowCursor scope = LayoutCompilerUnitTests.EnsureScope(row, root, col, tag); + assert root.get().clone() != scope.clone(); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn Col; + public Expected Expected = new Expected(); + public Property Prop = new Property(); + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.Col = this.Col; + varCopy.Prop = this.Prop.clone(); + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public Property[] Props; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Props = this.Props.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Property + public final static class Property { + public String Path; + public Object Value; + + public Property clone() { + Property varCopy = new Property(); + + varCopy.Path = this.Path; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private final static class RoundTripSparseOrdering extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutType type = closure.Expected.Type; + String path = closure.Expected.Path; + Object exValue = closure.Expected.Value; + String json = closure.Json; + + TLayout t = (TLayout)type; + TValue value = (TValue)exValue; + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out field).Find(row, path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + Result r = t.WriteSparse(row, ref field, value); + ResultAssert.IsSuccess(r, "Json: {0}", json); + Out tempOut_value = new Out(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref field, tempOut_value); + value = tempOut_value.get(); + ResultAssert.IsSuccess(r, "Json: {0}", json); + boolean tempVar = exValue instanceof Array; + Array array = tempVar ? (Array)exValue : null; + if (tempVar) { + CollectionAssert.AreEqual(array, (Collection)value, "Json: {0}", json); + } else { + Assert.AreEqual(exValue, value, "Json: {0}", json); + } + + if (t instanceof LayoutNull) { + Reference tempReference_field = + new Reference(field); + r = LayoutType.Boolean.WriteSparse(row, tempReference_field, false); + field = tempReference_field.get(); + ResultAssert.IsSuccess(r, "Json: {0}", json); + Out tempOut_value2 = new Out(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref field, tempOut_value2); + value = tempOut_value2.get(); + ResultAssert.TypeMismatch(r, "Json: {0}", json); + } else { + Reference tempReference_field2 = + new Reference(field); + r = LayoutType.Null.writeSparse(row, tempReference_field2, NullValue.DEFAULT); + field = tempReference_field2.get(); + ResultAssert.IsSuccess(r, "Json: {0}", json); + Out tempOut_value3 = new Out(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref field, tempOut_value3); + value = tempOut_value3.get(); + ResultAssert.TypeMismatch(r, "Json: {0}", json); + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public Expected Expected = new Expected(); + public String Json; + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.Json = this.Json; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Path; + public LayoutType Type; + public Object Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Path = this.Path; + varCopy.Type = this.Type; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private final static class RoundTripSparseSet extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn setCol = closure.SetCol; + LayoutType tempVar = setCol.type(); + LayoutUniqueScope setT = tempVar instanceof LayoutUniqueScope ? (LayoutUniqueScope)tempVar : null; + Expected expected = closure.Expected.clone(); + String tag = String.format("Json: %1$s, Set: %2$s", expected.Json, setCol.type().getName()); + + System.out.println(tag); + Assert.IsNotNull(setT, tag); + + TLayout t = (TLayout)expected.Type; + + // Verify the Set doesn't yet exist. + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out field).Find(row, setCol.path()); + Reference tempReference_field = + new Reference(field); + RowCursor scope; + Out tempOut_scope = + new Out(); + Result r = setT.ReadScope(row, tempReference_field, tempOut_scope); + scope = tempOut_scope.get(); + field = tempReference_field.get(); + ResultAssert.NotFound(r, tag); + + // Write the Set. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = setT.WriteScope(row, ref field, setCol.typeArgs().clone(), out scope); + ResultAssert.IsSuccess(r, tag); + + // Verify the nested field doesn't yet appear within the new scope. + assert !scope.MoveNext(row); + TValue value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref scope, out value); + ResultAssert.NotFound(r, tag); + + // Write the nested fields. + for (Object v1 : expected.Value) { + // Write the ith item into staging storage. + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.WriteSparse(row, ref tempCursor, (TValue)v1); + ResultAssert.IsSuccess(r, tag); + + // Move item into the set. + Reference tempReference_scope = + new Reference(scope); + Reference tempReference_tempCursor = + new Reference(tempCursor); + r = setT.MoveField(row, tempReference_scope, tempReference_tempCursor); + tempCursor = tempReference_tempCursor.get(); + scope = tempReference_scope.get(); + ResultAssert.IsSuccess(r, tag); + } + + // Attempts to insert the same items into the set again will fail. + for (Object v2 : expected.Value) { + // Write the ith item into staging storage. + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.WriteSparse(row, ref tempCursor, (TValue)v2); + ResultAssert.IsSuccess(r, tag); + + // Move item into the set. + Reference tempReference_scope2 = + new Reference(scope); + Reference tempReference_tempCursor2 = + new Reference(tempCursor); + r = setT.MoveField(row, tempReference_scope2, tempReference_tempCursor2, UpdateOptions.Insert); + tempCursor = tempReference_tempCursor2.get(); + scope = tempReference_scope2.get(); + ResultAssert.Exists(r, tag); + } + + // Read the Set and the nested column, validate the nested column has the proper value. + Reference tempReference_field2 = + new Reference(field); + RowCursor scope2; + Out tempOut_scope2 = + new Out(); + r = setT.ReadScope(row, tempReference_field2, tempOut_scope2); + scope2 = tempOut_scope2.get(); + field = tempReference_field2.get(); + ResultAssert.IsSuccess(r, tag); + Assert.AreEqual(scope.ScopeType, scope2.ScopeType, tag); + Assert.AreEqual(scope.start(), scope2.start(), tag); + Assert.AreEqual(scope.Immutable, scope2.Immutable, tag); + + // Read the nested fields + Reference tempReference_field3 = + new Reference(field); + Out tempOut_scope2 = + new Out(); + ResultAssert.IsSuccess(setT.ReadScope(row, tempReference_field3, tempOut_scope2)); + scope = tempOut_scope2.get(); + field = tempReference_field3.get(); + for (Object item : expected.Value) { + assert scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref scope, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar2 = item instanceof Array; + Array array = tempVar2 ? (Array)item : null; + if (tempVar2) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual(item, value, tag); + } + } + + // Delete all of the items and then insert them again in the opposite order. + Reference tempReference_field4 = + new Reference(field); + Out tempOut_scope3 = + new Out(); + ResultAssert.IsSuccess(setT.ReadScope(row, tempReference_field4, tempOut_scope3)); + scope = tempOut_scope3.get(); + field = tempReference_field4.get(); + for (int i = 0; i < expected.Value.size(); i++) { + assert scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.DeleteSparse(row, ref scope); + ResultAssert.IsSuccess(r, tag); + } + + Reference tempReference_field5 = + new Reference(field); + Out tempOut_scope4 = + new Out(); + ResultAssert.IsSuccess(setT.ReadScope(row, tempReference_field5, tempOut_scope4)); + scope = tempOut_scope4.get(); + field = tempReference_field5.get(); + for (int i = expected.Value.size() - 1; i >= 0; i--) { + // Write the ith item into staging storage. + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.WriteSparse(row, ref tempCursor, (TValue)expected.Value.get(i)); + ResultAssert.IsSuccess(r, tag); + + // Move item into the set. + Reference tempReference_scope3 = + new Reference(scope); + Reference tempReference_tempCursor3 = + new Reference(tempCursor); + r = setT.MoveField(row, tempReference_scope3, tempReference_tempCursor3); + tempCursor = tempReference_tempCursor3.get(); + scope = tempReference_scope3.get(); + ResultAssert.IsSuccess(r, tag); + } + + // Verify they still enumerate in sorted order. + Reference tempReference_field6 = + new Reference(field); + Out tempOut_scope5 = + new Out(); + ResultAssert.IsSuccess(setT.ReadScope(row, tempReference_field6, tempOut_scope5)); + scope = tempOut_scope5.get(); + field = tempReference_field6.get(); + for (Object item : expected.Value) { + assert scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref scope, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar3 = item instanceof Array; + Array array = tempVar3 ? (Array)item : null; + if (tempVar3) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual(item, value, tag); + } + } + + // Delete one item. + if (expected.Value.size() > 1) { + int indexToDelete = 1; + Reference tempReference_field7 = + new Reference(field); + Out tempOut_scope6 = new Out(); + ResultAssert.IsSuccess(setT.ReadScope(row, tempReference_field7, tempOut_scope6)); + scope = tempOut_scope6.get(); + field = tempReference_field7.get(); + assert scope.MoveTo(row, indexToDelete); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.DeleteSparse(row, ref scope); + ResultAssert.IsSuccess(r, tag); + ArrayList remainingValues = new ArrayList(expected.Value); + remainingValues.remove(indexToDelete); + + Reference tempReference_field8 = new Reference(field); + Out tempOut_scope7 = new Out(); + ResultAssert.IsSuccess(setT.ReadScope(row, tempReference_field8, tempOut_scope7)); + scope = tempOut_scope7.get(); + field = tempReference_field8.get(); + for (Object item : remainingValues) { + assert scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref scope, out value); + ResultAssert.IsSuccess(r, tag); + boolean tempVar4 = item instanceof Array; + Array array = tempVar4 ? (Array)item : null; + if (tempVar4) { + CollectionAssert.AreEqual(array, (Collection)value, tag); + } else { + Assert.AreEqual(item, value, tag); + } + } + + assert !scope.MoveTo(row, remainingValues.size()); + } + + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot).Find(row, setCol.path()); + Reference tempReference_roRoot = new Reference(roRoot); + ResultAssert.InsufficientPermissions(setT.DeleteScope(row, tempReference_roRoot)); + roRoot = tempReference_roRoot.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(setT.WriteScope(row, ref roRoot, setCol.typeArgs().clone(), out _)); + + // Overwrite the whole scope. + Reference tempReference_field9 = new Reference(field); + r = LayoutType.Null.writeSparse(row, tempReference_field9, NullValue.DEFAULT); + field = tempReference_field9.get(); + ResultAssert.IsSuccess(r, tag); + Reference tempReference_field10 = new Reference(field); + RowCursor _; + Out tempOut__ = new Out(); + r = setT.ReadScope(row, tempReference_field10, tempOut__); + _ = tempOut__.get(); + field = tempReference_field10.get(); + ResultAssert.TypeMismatch(r, tag); + Reference tempReference_field11 = new Reference(field); + r = setT.DeleteScope(row, tempReference_field11); + field = tempReference_field11.get(); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + + // Overwrite it again, then delete it. + Reference tempReference_field12 = new Reference(field); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + r = setT.WriteScope(row, tempReference_field12, setCol.typeArgs().clone(), out _, UpdateOptions.Update); + field = tempReference_field12.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field13 = new Reference(field); + r = setT.DeleteScope(row, tempReference_field13); + field = tempReference_field13.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + Reference tempReference_field14 = new Reference(field); + RowCursor _; + Out tempOut__2 = new Out(); + r = setT.ReadScope(row, tempReference_field14, tempOut__2); + _ = tempOut__2.get(); + field = tempReference_field14.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public Expected Expected = new Expected(); + public LayoutColumn SetCol; + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.SetCol = this.SetCol; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public LayoutType Type; + public ArrayList Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Type = this.Type; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private final static class RoundTripSparseSimple extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn col = closure.Col; + Expected expected = closure.Expected.clone(); + + System.out.printf("%1$s" + "\r\n", col.type().getName()); + TLayout t = (TLayout)col.type(); + RowCursor field; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out field).Find(row, col.path()); + TValue value; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + Result r = t.ReadSparse(row, ref field, out value); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.WriteSparse(row, ref field, (TValue)expected.Value, UpdateOptions.Update); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.WriteSparse(row, ref field, (TValue)expected.Value); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.WriteSparse(row, ref field, (TValue)expected.Value, UpdateOptions.Insert); + ResultAssert.Exists(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref field, out value); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + boolean tempVar = expected.Value instanceof Array; + Array array = tempVar ? (Array)expected.Value : null; + if (tempVar) { + CollectionAssert.AreEqual(array, (Collection)value, "Json: {0}", expected.Json); + } else { + Assert.AreEqual(expected.Value, value, "Json: {0}", expected.Json); + } + + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot).Find(row, col.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(t.DeleteSparse(row, ref roRoot)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(t.WriteSparse(row, ref roRoot, (TValue)expected.Value, + UpdateOptions.Update)); + + if (t instanceof LayoutNull) { + Reference tempReference_field = + new Reference(field); + r = LayoutType.Boolean.WriteSparse(row, tempReference_field, false); + field = tempReference_field.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref field, out value); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + } else { + Reference tempReference_field2 = + new Reference(field); + r = LayoutType.Null.writeSparse(row, tempReference_field2, NullValue.DEFAULT); + field = tempReference_field2.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + r = t.ReadSparse(row, ref field, out value); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.DeleteSparse(row, ref field); + ResultAssert.TypeMismatch(r, "Json: {0}", expected.Json); + + // Overwrite it again, then delete it. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.WriteSparse(row, ref field, (TValue)expected.Value, UpdateOptions.Update); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.DeleteSparse(row, ref field); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + r = t.ReadSparse(row, ref field, out value); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn Col; + public Expected Expected = new Expected(); + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.Col = this.Col; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public Object Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Value = this.Value; + + return varCopy; + } + } +} + +private static class RoundTripVariable extends TestActionDispatcher { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + LayoutColumn col = closure.Col; + Expected expected = closure.Expected.clone(); + + System.out.printf("%1$s" + "\r\n", expected.Json); + + this.RoundTrip(row, root, col, expected.Value, expected.clone()); + } + + protected final , TValue> void Compare(Reference row, + Reference root, LayoutColumn col, Object exValue, Expected expected) { + TLayout t = (TLayout)col.type(); + TValue value; + Out tempOut_value = new Out(); + Result r = t.readVariable(row, root, col, tempOut_value); + value = tempOut_value.get(); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + boolean tempVar = exValue instanceof Array; + Array array = tempVar ? (Array)exValue : null; + if (tempVar) { + CollectionAssert.AreEqual(array, (Collection)value, "Json: {0}", expected.Json); + } else { + Assert.AreEqual(exValue, value, "Json: {0}", expected.Json); + } + } + + protected final , TValue> void RoundTrip(Reference row, + Reference root, LayoutColumn col, Object exValue, Expected expected) { + TLayout t = (TLayout)col.type(); + Result r = t.writeVariable(row, root, col, (TValue)exValue); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + this.Compare(row, root, col, exValue, expected.clone()); + + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot); + Reference tempReference_roRoot = + new Reference(roRoot); + ResultAssert.InsufficientPermissions(t.writeVariable(row, tempReference_roRoot, col, (TValue)expected.Value)); + roRoot = tempReference_roRoot.get(); + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Closure + public final static class Closure { + public LayoutColumn Col; + public Expected Expected = new Expected(); + public Layout Layout; + + public Closure clone() { + Closure varCopy = new Closure(); + + varCopy.Col = this.Col; + varCopy.Layout = this.Layout; + varCopy.Expected = this.Expected.clone(); + + return varCopy; + } + } + + //C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may + // differ from the original: + //ORIGINAL LINE: public struct Expected + public final static class Expected { + public String Json; + public Object Long; + public Object Short; + public Object TooBig; + public Object Value; + + public Expected clone() { + Expected varCopy = new Expected(); + + varCopy.Json = this.Json; + varCopy.Short = this.Short; + varCopy.Value = this.Value; + varCopy.Long = this.Long; + varCopy.TooBig = this.TooBig; + + return varCopy; + } + } +} + +private abstract static class TestActionDispatcher { + public abstract , TValue> void Dispatch(Reference row, Reference scope, TClosure closure); + + public void DispatchObject(Reference row, Reference scope, TClosure closure) { + Assert.Fail("not implemented"); + } +} + +private final static class VariableInterleaving extends RoundTripVariable { + @Override + public void Dispatch(Reference row, Reference root, + Closure closure) { + Layout layout = closure.Layout; + Expected expected = closure.Expected.clone(); + + System.out.printf("%1$s" + "\r\n", expected.Json); + + LayoutColumn a = this.Verify(row, root, layout, "a", expected.clone()); + LayoutColumn b = this.Verify(row, root, layout, "b", expected.clone()); + LayoutColumn c = this.Verify(row, root, layout, "c", expected.clone()); + + this.RoundTrip(row, root, b, expected.Value, expected.clone()); + this.RoundTrip(row, root, a, expected.Value, expected.clone()); + this.RoundTrip(row, root, c, expected.Value, expected.clone()); + + // Make the var column shorter. + int rowSizeBeforeShrink = row.get().length(); + this.RoundTrip(row, root, a, expected.Short, expected.clone()); + this.Compare(row, root, c, expected.Value, expected.clone()); + int rowSizeAfterShrink = row.get().length(); + Assert.IsTrue(rowSizeAfterShrink < rowSizeBeforeShrink, "Json: {0}", expected.Json); + + // Make the var column longer. + this.RoundTrip(row, root, a, expected.Long, expected.clone()); + this.Compare(row, root, c, expected.Value, expected.clone()); + int rowSizeAfterGrow = row.get().length(); + Assert.IsTrue(rowSizeAfterGrow > rowSizeAfterShrink, "Json: {0}", expected.Json); + Assert.IsTrue(rowSizeAfterGrow > rowSizeBeforeShrink, "Json: {0}", expected.Json); + + // Check for size overflow errors. + if (a.getSize() > 0) { + this.TooBig(row, root, a, expected.clone()); + } + + // Delete the var column. + this.Delete(row, root, b, expected.clone()); + this.Delete(row, root, c, expected.clone()); + this.Delete(row, root, a, expected.clone()); + } + + private , TValue> void Delete(Reference row, + Reference root, LayoutColumn col, Expected expected) { + TLayout t = (TLayout)col.type(); + RowCursor roRoot; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().AsReadOnly(out roRoot); + Reference tempReference_roRoot = + new Reference(roRoot); + ResultAssert.InsufficientPermissions(t.deleteVariable(row, tempReference_roRoot, col)); + roRoot = tempReference_roRoot.get(); + Result r = t.deleteVariable(row, root, col); + ResultAssert.IsSuccess(r, "Json: {0}", expected.Json); + TValue _; + Out tempOut__ = new Out(); + r = t.readVariable(row, root, col, tempOut__); + _ = tempOut__.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + } + + private , TValue> void TooBig(Reference row, + Reference root, LayoutColumn col, Expected expected) { + TLayout t = (TLayout)col.type(); + Result r = t.writeVariable(row, root, col, (TValue)expected.TooBig); + Assert.AreEqual(Result.TOO_BIG, r, "Json: {0}", expected.Json); + } + + private , TValue> LayoutColumn Verify(Reference row, + Reference root, Layout layout, String path, Expected expected) { + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + boolean found = layout.TryFind(path, out col); + Assert.IsTrue(found, "Json: {0}", expected.Json); + assert col.Type.AllowVariable; + TLayout t = (TLayout)col.Type; + TValue _; + Out tempOut__ = new Out(); + Result r = t.readVariable(row, root, col, tempOut__); + _ = tempOut__.get(); + ResultAssert.NotFound(r, "Json: {0}", expected.Json); + return col; + } +} +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutTypeUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutTypeUnitTests.java new file mode 100644 index 0000000..ee33c06 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/LayoutTypeUnitTests.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public class LayoutTypeUnitTests +public class LayoutTypeUnitTests { + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void LayoutTypeTest() + public final void LayoutTypeTest() { + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Boolean); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Int8); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Int16); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Int32); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Int64); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.UInt8); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.UInt16); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.UInt32); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.UInt64); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.VarInt); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.VarUInt); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Float32); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Float64); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Decimal); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Null); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Boolean); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.DateTime); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Guid); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Utf8); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Binary); + LayoutTypeUnitTests.TestLayoutTypeApi(LayoutType.Object); + } + + private static void TestLayoutTypeApi(LayoutType t) { + assert t.getName() != null; + assert !tangible.StringHelper.isNullOrWhiteSpace(t.getName()); + Assert.AreNotSame(null, t.getIsFixed(), t.getName()); + Assert.AreNotSame(null, t.getAllowVariable(), t.getName()); + Assert.AreNotSame(null, t.getIsBool(), t.getName()); + Assert.AreNotSame(null, t.getIsNull(), t.getName()); + Assert.AreNotSame(null, t.getIsVarint(), t.getName()); + Assert.IsTrue(t.Size >= 0, t.getName()); + Assert.AreNotEqual(LayoutCode.Invalid, t.LayoutCode, t.getName()); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullRowDispatcher.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullRowDispatcher.java new file mode 100644 index 0000000..6eeae45 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullRowDispatcher.java @@ -0,0 +1,87 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal struct NullRowDispatcher : IDispatcher +public final class NullRowDispatcher implements IDispatcher { + + public , TValue> void Dispatch(Reference dispatcher, Reference root, LayoutColumn col, LayoutType t) { + Dispatch(dispatcher, root, col, t, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public void Dispatch(ref RowOperationDispatcher dispatcher, ref RowCursor root, + // LayoutColumn col, LayoutType t, TValue expected = default) where TLayout : LayoutType + public , TValue> void Dispatch(Reference dispatcher, Reference root, LayoutColumn col, LayoutType t, TValue expected) { + switch (col == null ? null : col.getStorage()) { + case Fixed: + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + TValue _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + ResultAssert.NotFound(t.TypeAs().ReadFixed(tempReference_Row, root, col, out _)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + break; + case Variable: + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + TValue _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + ResultAssert.NotFound(t.TypeAs().ReadVariable(tempReference_Row2, root, col, out _)); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + break; + default: + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + TValue _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + ResultAssert.NotFound(t.TypeAs().ReadSparse(tempReference_Row3, root, out _)); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + break; + } + } + + public void DispatchArray(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + } + + public void DispatchMap(Reference dispatcher, Reference scope, LayoutType t, TypeArgumentList typeArgs, Object value) { + } + + public void DispatchNullable(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + } + + public void DispatchObject(Reference dispatcher, + Reference scope) { + } + + public void DispatchSet(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + } + + public void DispatchTuple(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + } + + public void DispatchUDT(Reference dispatcher, Reference scope, LayoutType t, TypeArgumentList typeArgs, Object value) { + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java new file mode 100644 index 0000000..e680e34 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/NullableUnitTests.java @@ -0,0 +1,753 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +// ReSharper disable StringLiteralTypo + + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(NullableUnitTests.SchemaFile, "TestData")] public sealed class +// NullableUnitTests +public final class NullableUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final String SchemaFile = "TestData\\NullableSchema.json"; + private Layout layout; + private LayoutResolver resolver; + private Namespace schema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateNullables() + public void CreateNullables() { + RowBuffer row = new RowBuffer(NullableUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + Nullables t1 = new Nullables(); + t1.NullBool = new ArrayList(Arrays.asList(true, false, null)); + t1.NullArray = new ArrayList(Arrays.asList(1.2F, null, 3.0F)); + t1.NullSet = new ArrayList(Arrays.asList(null, "abc", "def")); + t1.NullTuple = new ArrayList<(Integer, Long) > (Arrays.asList((1, 2), (null, 3),(4, null),(null, null))) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: t1.NullMap = new Dictionary> { { System.GuidCodec.Parse + // ("{00000000-0000-0000-0000-000000000000}"), 1 }, { System.GuidCodec.Parse + // ("{4674962B-CE11-4916-81C5-0421EE36F168}"), 20 }, { System.GuidCodec.Parse + // ("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), null }}; + t1.NullMap = new HashMap(Map.ofEntries(Map.entry(UUID.fromString("{00000000-0000-0000-0000" + + "-000000000000}"), 1), Map.entry(UUID.fromString("{4674962B-CE11-4916-81C5-0421EE36F168}"), 20), + Map.entry(UUID.fromString("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), null))); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteNullables(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Nullables t2 = this.ReadNullables(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert t1 == t2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString(NullableUnitTests.SchemaFile); + this.schema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.schema); + this.layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Nullables")).SchemaId); + } + + // TODO: C# TO JAVA CONVERTER: The C# 'struct' constraint has no equivalent in Java: + //ORIGINAL LINE: private static Result ReadNullable(ref RowBuffer row, ref RowCursor scope, TypeArgument + // itemType, out Nullable item, out RowCursor nullableScope) where TValue : struct + private static Result ReadNullable(Reference row, + Reference scope, TypeArgument itemType, + Out item, + Out nullableScope) { + TValue value; + Out tempOut_value = new Out(); + Result r = NullableUnitTests.ReadNullableImpl(row, scope, itemType.clone(), tempOut_value, + nullableScope.clone()); + value = tempOut_value.get(); + if ((r != Result.SUCCESS) && (r != Result.NOT_FOUND)) { + item.setAndGet(null); + return r; + } + + item.setAndGet((r == Result.NOT_FOUND) ? null : value); + return Result.SUCCESS; + } + + private static Result ReadNullable(Reference row, + Reference scope, TypeArgument itemType, + Out item, + Out nullableScope) { + Result r = NullableUnitTests.ReadNullableImpl(row, scope, itemType.clone(), item, nullableScope.clone()); + return (r == Result.NOT_FOUND) ? Result.SUCCESS : r; + } + + private static Result ReadNullableImpl(Reference row, + Reference scope, TypeArgument itemType, + Out item, + Out nullableScope) { + Result r = itemType.getType().TypeAs().ReadScope(row, scope, nullableScope.clone()); + if (r != Result.SUCCESS) { + item.setAndGet(null); + return r; + } + + if (RowCursors.moveNext(nullableScope.get().clone(), row)) { + ResultAssert.IsSuccess(LayoutNullable.HasValue(row, nullableScope.clone())); + return itemType.getTypeArgs().get(0).getType().>TypeAs().ReadSparse(row, + nullableScope.clone(), item); + } + + ResultAssert.NotFound(LayoutNullable.HasValue(row, nullableScope.clone())); + item.setAndGet(null); + return Result.NOT_FOUND; + } + + private Nullables ReadNullables(Reference row, Reference root) { + Nullables value = new Nullables(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("nullbool", out c); + RowCursor scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref scope, out scope) == Result.SUCCESS) { + value.NullBool = new ArrayList(); + RowCursor nullableScope = null; + Reference tempReference_nullableScope = + new Reference(nullableScope); + while (scope.MoveNext(row, tempReference_nullableScope)) { + nullableScope = tempReference_nullableScope.get(); + Reference tempReference_scope = + new Reference(scope); + Nullable item; + Out tempOut_item = new Out(); + Out tempOut_nullableScope = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_scope, c.TypeArgs[0], tempOut_item + , tempOut_nullableScope)); + nullableScope = tempOut_nullableScope.get(); + item = tempOut_item.get(); + scope = tempReference_scope.get(); + value.NullBool.add(item); + } + nullableScope = tempReference_nullableScope.get(); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("nullarray", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref scope, out scope) == Result.SUCCESS) { + value.NullArray = new ArrayList(); + RowCursor nullableScope = null; + Reference tempReference_nullableScope2 = + new Reference(nullableScope); + while (scope.MoveNext(row, tempReference_nullableScope2)) { + nullableScope = tempReference_nullableScope2.get(); + Reference tempReference_scope2 = + new Reference(scope); + Nullable item; + Out tempOut_item2 = new Out(); + Out tempOut_nullableScope2 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_scope2, c.TypeArgs[0], + tempOut_item2, tempOut_nullableScope2)); + nullableScope = tempOut_nullableScope2.get(); + item = tempOut_item2.get(); + scope = tempReference_scope2.get(); + value.NullArray.add(item); + } + nullableScope = tempReference_nullableScope2.get(); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("nullset", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref scope, out scope) == Result.SUCCESS) { + value.NullSet = new ArrayList(); + RowCursor nullableScope = null; + Reference tempReference_nullableScope3 = + new Reference(nullableScope); + while (scope.MoveNext(row, tempReference_nullableScope3)) { + nullableScope = tempReference_nullableScope3.get(); + Reference tempReference_scope3 = + new Reference(scope); + String item; + Out tempOut_item3 = new Out(); + Out tempOut_nullableScope3 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_scope3, c.TypeArgs[0], + tempOut_item3, tempOut_nullableScope3)); + nullableScope = tempOut_nullableScope3.get(); + item = tempOut_item3.get(); + scope = tempReference_scope3.get(); + value.NullSet.add(item); + } + nullableScope = tempReference_nullableScope3.get(); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("nulltuple", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref scope, out scope) == Result.SUCCESS) { + value.NullTuple = new ArrayList<(Integer, Long) > (); + RowCursor tupleScope = null; + TypeArgument tupleType = c.TypeArgs[0]; + Reference tempReference_tupleScope = + new Reference(tupleScope); + while (scope.MoveNext(row, tempReference_tupleScope)) { + tupleScope = tempReference_tupleScope.get(); + Reference tempReference_scope4 = + new Reference(scope); + Out tempOut_tupleScope = + new Out(); + ResultAssert.IsSuccess(tupleType.TypeAs().ReadScope(row, tempReference_scope4, + tempOut_tupleScope)); + tupleScope = tempOut_tupleScope.get(); + scope = tempReference_scope4.get(); + + assert RowCursors.moveNext(tupleScope.clone() + , row); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + Nullable item1; + Out tempOut_item1 = new Out(); + RowCursor nullableScope; + Out tempOut_nullableScope4 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_tupleScope2, + tupleType.getTypeArgs().get(0).clone(), tempOut_item1, tempOut_nullableScope4)); + nullableScope = tempOut_nullableScope4.get(); + item1 = tempOut_item1.get(); + tupleScope = tempReference_tupleScope2.get(); + Reference tempReference_nullableScope4 = + new Reference(nullableScope); + assert RowCursors.moveNext(tupleScope.clone() + , row, tempReference_nullableScope4); + nullableScope = tempReference_nullableScope4.get(); + Reference tempReference_tupleScope3 = + new Reference(tupleScope); + Nullable item2; + Out tempOut_item2 = new Out(); + Out tempOut_nullableScope5 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_tupleScope3, + tupleType.getTypeArgs().get(1).clone(), tempOut_item2, tempOut_nullableScope5)); + nullableScope = tempOut_nullableScope5.get(); + item2 = tempOut_item2.get(); + tupleScope = tempReference_tupleScope3.get(); + + Reference tempReference_nullableScope5 = + new Reference(nullableScope); + assert !RowCursors.moveNext(tupleScope.clone(), row, tempReference_nullableScope5); + nullableScope = tempReference_nullableScope5.get(); + value.NullTuple.add((item1, item2)) + } + tupleScope = tempReference_tupleScope.get(); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("nullmap", out c); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref scope, out scope) == Result.SUCCESS) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: value.NullMap = new Dictionary>(); + value.NullMap = new HashMap(); + RowCursor tupleScope = null; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + TypeArgument tupleType = c.typeAs().FieldType(ref scope); + Reference tempReference_tupleScope4 = + new Reference(tupleScope); + while (scope.MoveNext(row, tempReference_tupleScope4)) { + tupleScope = tempReference_tupleScope4.get(); + Reference tempReference_scope5 = + new Reference(scope); + Out tempOut_tupleScope2 = + new Out(); + ResultAssert.IsSuccess(tupleType.TypeAs().ReadScope(row, tempReference_scope5, + tempOut_tupleScope2)); + tupleScope = tempOut_tupleScope2.get(); + scope = tempReference_scope5.get(); + + assert RowCursors.moveNext(tupleScope.clone() + , row); + Reference tempReference_tupleScope5 = + new Reference(tupleScope); + Nullable itemKey; + Out tempOut_itemKey = new Out(); + RowCursor nullableScope; + Out tempOut_nullableScope6 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_tupleScope5, + tupleType.getTypeArgs().get(0).clone(), tempOut_itemKey, tempOut_nullableScope6)); + nullableScope = tempOut_nullableScope6.get(); + itemKey = tempOut_itemKey.get(); + tupleScope = tempReference_tupleScope5.get(); + + Reference tempReference_nullableScope6 = + new Reference(nullableScope); + assert RowCursors.moveNext(tupleScope.clone() + , row, tempReference_nullableScope6); + nullableScope = tempReference_nullableScope6.get(); + Reference tempReference_tupleScope6 = + new Reference(tupleScope); + Nullable itemValue; + Out tempOut_itemValue = new Out(); + Out tempOut_nullableScope7 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.ReadNullable(row, tempReference_tupleScope6, + tupleType.getTypeArgs().get(1).clone(), tempOut_itemValue, tempOut_nullableScope7)); + nullableScope = tempOut_nullableScope7.get(); + itemValue = tempOut_itemValue.get(); + tupleScope = tempReference_tupleScope6.get(); + + Reference tempReference_nullableScope7 = + new Reference(nullableScope); + assert !RowCursors.moveNext(tupleScope.clone(), row, tempReference_nullableScope7); + nullableScope = tempReference_nullableScope7.get(); + value.NullMap.put(itemKey != null ? itemKey : UUID.Empty, itemValue); + } + tupleScope = tempReference_tupleScope4.get(); + } + + return value; + } + + // TODO: C# TO JAVA CONVERTER: The C# 'struct' constraint has no equivalent in Java: + //ORIGINAL LINE: private static Result WriteNullable(ref RowBuffer row, ref RowCursor scope, TypeArgument + // itemType, Nullable item, out RowCursor nullableScope) where TValue : struct + private static Result WriteNullable(Reference row, + Reference scope, TypeArgument itemType, + TValue item, Out nullableScope) { + return NullableUnitTests.WriteNullableImpl(row, scope, itemType.clone(), item != null, item != null ? item : + default,nullableScope.clone()) + } + + private static Result WriteNullable(Reference row, + Reference scope, TypeArgument itemType, + TValue item, Out nullableScope) { + return NullableUnitTests.WriteNullableImpl(row, scope, itemType.clone(), item != null, item, + nullableScope.clone()); + } + + private static Result WriteNullableImpl(Reference row, + Reference scope, TypeArgument itemType, + boolean hasValue, TValue item, + Out nullableScope) { + Result r = itemType.TypeAs().WriteScope(row, scope, itemType.getTypeArgs().clone(), hasValue, + nullableScope); + + if (r != Result.SUCCESS) { + return r; + } + + if (hasValue) { + r = itemType.getTypeArgs().get(0).getType().>TypeAs().WriteSparse(row, + nullableScope.clone(), item); + return r; + } + + return Result.SUCCESS; + } + + private void WriteNullables(Reference row, Reference root, + Nullables value) { + LayoutColumn c; + + if (value.NullBool != null) { + Out tempOut_c = + new Out(); + assert this.layout.TryFind("nullbool", tempOut_c); + c = tempOut_c.get(); + RowCursor outerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out outerScope).Find(row, c.path()); + Reference tempReference_outerScope = + new Reference(outerScope); + Out tempOut_outerScope = + new Out(); + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, tempReference_outerScope, + c.typeArgs().clone(), tempOut_outerScope)); + outerScope = tempOut_outerScope.get(); + outerScope = tempReference_outerScope.get(); + for (Boolean item : value.NullBool) { + Reference tempReference_outerScope2 = + new Reference(outerScope); + RowCursor innerScope; + Out tempOut_innerScope = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_outerScope2, + c.typeArgs().get(0).clone(), item, tempOut_innerScope)); + innerScope = tempOut_innerScope.get(); + outerScope = tempReference_outerScope2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !outerScope.MoveNext(row, ref innerScope); + } + } + + if (value.NullArray != null) { + Out tempOut_c2 = + new Out(); + assert this.layout.TryFind("nullarray", tempOut_c2); + c = tempOut_c2.get(); + RowCursor outerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out outerScope).Find(row, c.path()); + Reference tempReference_outerScope3 = + new Reference(outerScope); + Out tempOut_outerScope2 = + new Out(); + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, tempReference_outerScope3, + c.typeArgs().clone(), tempOut_outerScope2)); + outerScope = tempOut_outerScope2.get(); + outerScope = tempReference_outerScope3.get(); + for (Float item : value.NullArray) { + Reference tempReference_outerScope4 = + new Reference(outerScope); + RowCursor innerScope; + Out tempOut_innerScope2 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_outerScope4, + c.typeArgs().get(0).clone(), item, tempOut_innerScope2)); + innerScope = tempOut_innerScope2.get(); + outerScope = tempReference_outerScope4.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !outerScope.MoveNext(row, ref innerScope); + } + } + + if (value.NullSet != null) { + Out tempOut_c3 = + new Out(); + assert this.layout.TryFind("nullset", tempOut_c3); + c = tempOut_c3.get(); + RowCursor outerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out outerScope).Find(row, c.path()); + Reference tempReference_outerScope5 = + new Reference(outerScope); + Out tempOut_outerScope3 = + new Out(); + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, tempReference_outerScope5, + c.typeArgs().clone(), tempOut_outerScope3)); + outerScope = tempOut_outerScope3.get(); + outerScope = tempReference_outerScope5.get(); + for (String item : value.NullSet) { + RowCursor temp; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + RowCursor.createForAppend(row, out temp).Find(row, ""); + Reference tempReference_temp = + new Reference(temp); + RowCursor _; + Out tempOut__ = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_temp, + c.typeArgs().get(0).clone(), item, tempOut__)); + _ = tempOut__.get(); + temp = tempReference_temp.get(); + Reference tempReference_outerScope6 = + new Reference(outerScope); + Reference tempReference_temp2 = + new Reference(temp); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_outerScope6, + tempReference_temp2)); + temp = tempReference_temp2.get(); + outerScope = tempReference_outerScope6.get(); + } + } + + if (value.NullTuple != null) { + Out tempOut_c4 = + new Out(); + assert this.layout.TryFind("nulltuple", tempOut_c4); + c = tempOut_c4.get(); + RowCursor outerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out outerScope).Find(row, c.path()); + Reference tempReference_outerScope7 = + new Reference(outerScope); + Out tempOut_outerScope4 = + new Out(); + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, tempReference_outerScope7, + c.typeArgs().clone(), tempOut_outerScope4)); + outerScope = tempOut_outerScope4.get(); + outerScope = tempReference_outerScope7.get(); + for ((Integer item1,Long item2) :value.NullTuple) + { + TypeArgument tupleType = c.typeArgs().get(0).clone(); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(tupleType.TypeAs().WriteScope(row, ref outerScope, + tupleType.getTypeArgs().clone(), out tupleScope)); + + Reference tempReference_tupleScope = + new Reference(tupleScope); + RowCursor nullableScope; + Out tempOut_nullableScope = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_tupleScope, + tupleType.getTypeArgs().get(0).clone(), item1, tempOut_nullableScope)); + nullableScope = tempOut_nullableScope.get(); + tupleScope = tempReference_tupleScope.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert tupleScope.MoveNext(row, ref nullableScope); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + Out tempOut_nullableScope2 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_tupleScope2, + tupleType.getTypeArgs().get(1).clone(), item2, tempOut_nullableScope2)); + nullableScope = tempOut_nullableScope2.get(); + tupleScope = tempReference_tupleScope2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !tupleScope.MoveNext(row, ref nullableScope); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !outerScope.MoveNext(row, ref tupleScope); + } + } + + if (value.NullMap != null) { + Out tempOut_c5 = + new Out(); + assert this.layout.TryFind("nullmap", tempOut_c5); + c = tempOut_c5.get(); + RowCursor outerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out outerScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref outerScope, + c.typeArgs().clone(), out outerScope)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: foreach ((GuidCodec key, Nullable itemValue) in value.NullMap) + for ((UUID key,Byte itemValue) :value.NullMap) + { + Reference tempReference_outerScope8 = + new Reference(outerScope); + TypeArgument tupleType = c.typeAs().FieldType(tempReference_outerScope8).clone(); + outerScope = tempReference_outerScope8.get(); + RowCursor temp; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + RowCursor.createForAppend(row, out temp).Find(row, ""); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(tupleType.TypeAs().WriteScope(row, ref temp, + tupleType.getTypeArgs().clone(), out tupleScope)); + + UUID itemKey = key.equals(UUID.Empty) ? null : key; + Reference tempReference_tupleScope3 = + new Reference(tupleScope); + RowCursor nullableScope; + Out tempOut_nullableScope3 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_tupleScope3, + tupleType.getTypeArgs().get(0).clone(), itemKey, tempOut_nullableScope3)); + nullableScope = tempOut_nullableScope3.get(); + tupleScope = tempReference_tupleScope3.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert tupleScope.MoveNext(row, ref nullableScope); + Reference tempReference_tupleScope4 = + new Reference(tupleScope); + Out tempOut_nullableScope4 = + new Out(); + ResultAssert.IsSuccess(NullableUnitTests.WriteNullable(row, tempReference_tupleScope4, + tupleType.getTypeArgs().get(1).clone(), itemValue, tempOut_nullableScope4)); + nullableScope = tempOut_nullableScope4.get(); + tupleScope = tempReference_tupleScope4.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !tupleScope.MoveNext(row, ref nullableScope); + + Reference tempReference_outerScope9 = + new Reference(outerScope); + Reference tempReference_temp3 = + new Reference(temp); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_outerScope9, + tempReference_temp3)); + temp = tempReference_temp3.get(); + outerScope = tempReference_outerScope9.get(); + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class Nullables + private final static class Nullables { + public ArrayList NullArray; + public ArrayList NullBool; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public Dictionary> NullMap; + public HashMap NullMap; + public ArrayList<(Integer,Long)>NullTuple + public ArrayList NullSet; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Nullables; + Nullables nullables = tempVar ? (Nullables)obj : null; + return tempVar && this.equals(nullables); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = 0; + hashCode = (hashCode * 397) ^ (this.NullBool == null ? null : this.NullBool.hashCode() != null ? this.NullBool.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.NullSet == null ? null : this.NullSet.hashCode() != null ? this.NullSet.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.NullArray == null ? null : this.NullArray.hashCode() != null ? this.NullArray.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.NullTuple == null ? null : this.NullTuple.hashCode() != null ? this.NullTuple.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.NullMap == null ? null : this.NullMap.hashCode() != null ? this.NullMap.hashCode() : 0); + return hashCode; + } + } + + private static boolean MapEquals(HashMap left, HashMap right) { + if (left.size() != right.size()) { + return false; + } + + for (Map.Entry item : left.entrySet()) { + TValue value; + if (!(right.containsKey(item.getKey()) && (value = right.get(item.getKey())) == value)) { + return false; + } + + if (!item.getValue().equals(value)) { + return false; + } + } + + return true; + } + + private boolean equals(Nullables other) { + //C# TO JAVA CONVERTER WARNING: Java AbstractList 'equals' is not always identical to LINQ 'SequenceEqual': + //ORIGINAL LINE: return (object.ReferenceEquals(this.NullBool, other.NullBool) || ((this.NullBool != null) && (other.NullBool != null) && this.NullBool.SequenceEqual(other.NullBool))) && (object.ReferenceEquals(this.NullSet, other.NullSet) || ((this.NullSet != null) && (other.NullSet != null) && this.NullSet.SequenceEqual(other.NullSet))) && (object.ReferenceEquals(this.NullArray, other.NullArray) || ((this.NullArray != null) && (other.NullArray != null) && this.NullArray.SequenceEqual(other.NullArray))) && (object.ReferenceEquals(this.NullTuple, other.NullTuple) || ((this.NullTuple != null) && (other.NullTuple != null) && this.NullTuple.SequenceEqual(other.NullTuple))) && (object.ReferenceEquals(this.NullMap, other.NullMap) || ((this.NullMap != null) && (other.NullMap != null) && Nullables.MapEquals(this.NullMap, other.NullMap))); + return (this.NullBool == other.NullBool || ((this.NullBool != null) && (other.NullBool != null) && this.NullBool.equals(other.NullBool))) && (this.NullSet == other.NullSet || ((this.NullSet != null) && (other.NullSet != null) && this.NullSet.equals(other.NullSet))) && (this.NullArray == other.NullArray || ((this.NullArray != null) && (other.NullArray != null) && this.NullArray.equals(other.NullArray))) && (this.NullTuple == other.NullTuple || ((this.NullTuple != null) && (other.NullTuple != null) && this.NullTuple.equals(other.NullTuple))) && (this.NullMap == other.NullMap || ((this.NullMap != null) && (other.NullMap != null) && Nullables.MapEquals(this.NullMap, other.NullMap))); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/PermuteExtensions.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/PermuteExtensions.java new file mode 100644 index 0000000..5e3d4b9 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/PermuteExtensions.java @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +/** + * Extension methods for computing permutations of {@link IEnumerable{T}}. + */ +public final class PermuteExtensions { + /** + * Generate all permutations of a given enumerable. + */ + public static java.lang.Iterable> Permute(java.lang.Iterable list) { + int start = 0; + for (T element : list) { + int index = start; + T[] first = { element }; + java.lang.Iterable rest = list.Where((s, i) -> i != index); + if (!rest.Any()) { + // TODO: C# TO JAVA CONVERTER: Java does not have an equivalent to the C# 'yield' keyword: + yield return first; + } + + for (java.lang.Iterable sub : + PermuteExtensions.Permute(rest)) { + // TODO: C# TO JAVA CONVERTER: Java does not have an equivalent to the C# 'yield' keyword: + yield return first.Concat(sub); + } + + start++; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RandomGeneratorUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RandomGeneratorUnitTests.java new file mode 100644 index 0000000..322c6f1 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RandomGeneratorUnitTests.java @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import java.util.Random; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public class RandomGeneratorUnitTests +public class RandomGeneratorUnitTests { + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void RangeTest() + public final void RangeTest() { + int seed = 42; + RandomGenerator rand = new RandomGenerator(new Random(seed)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ulong l1 = rand.NextUInt64(); + long l1 = rand.NextUInt64(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ulong l2 = rand.NextUInt64(); + long l2 = rand.NextUInt64(); + assert l1 != l2; + + System.out.println("Check full range of min/max for ushort."); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: for (int min = 0; min <= ushort.MaxValue; min++) + for (int min = 0; min <= Short.MAX_VALUE; min++) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ushort i1 = rand.NextUInt16((ushort)min, ushort.MaxValue); + short i1 = rand.NextUInt16((short)min, Short.MAX_VALUE); + assert i1 >= min; + } + + System.out.println("Check ushort range of min/max for uint."); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: for (uint min = 0; min <= (uint)ushort.MaxValue; min++) + for (int min = 0; min <= (int)Short.MAX_VALUE; min++) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: uint i1 = rand.NextUInt32(min, (uint)ushort.MaxValue); + int i1 = rand.NextUInt32(min, (int)Short.MAX_VALUE); + assert i1 >= min; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Assert.IsTrue(i1 <= ushort.MaxValue); + assert i1 <= Short.MAX_VALUE; + } + + boolean seenMax = false; + boolean seenMin = false; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: const ushort maxUShortRange = 10; + final short maxUShortRange = 10; + System.out.println("Check inclusivity for ushort."); + while (!(seenMax && seenMin)) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ushort i1 = rand.NextUInt16(ushort.MinValue, maxUShortRange); + short i1 = rand.NextUInt16(Short.MIN_VALUE, maxUShortRange); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: seenMin = seenMin || i1 == ushort.MinValue; + seenMin = seenMin || i1 == Short.MIN_VALUE; + seenMax = seenMax || i1 == maxUShortRange; + assert i1 <= maxUShortRange; + } + + seenMax = false; + seenMin = false; + System.out.println("Check inclusivity for short."); + final short minShortRange = -10; + final short maxShortRange = 10; + while (!(seenMax && seenMin)) { + short i1 = rand.NextInt16(minShortRange, maxShortRange); + seenMin = seenMin || i1 == -10; + seenMax = seenMax || i1 == 10; + assert i1 >= minShortRange; + assert i1 <= maxShortRange; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ReadRowDispatcher.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ReadRowDispatcher.java new file mode 100644 index 0000000..4e33d55 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ReadRowDispatcher.java @@ -0,0 +1,239 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedArray; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; + +import java.util.Collection; +import java.util.List; + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal struct ReadRowDispatcher : IDispatcher +public final class ReadRowDispatcher implements IDispatcher { + + public , TValue> void Dispatch(Reference dispatcher, Reference root, LayoutColumn col, LayoutType t) { + Dispatch(dispatcher, root, col, t, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public void Dispatch(ref RowOperationDispatcher dispatcher, ref RowCursor root, + // LayoutColumn col, LayoutType t, TValue expected = default) where TLayout : LayoutType + public , TValue> void Dispatch(Reference dispatcher, Reference root, LayoutColumn col, LayoutType t, TValue expected) { + TValue value; + switch (col == null ? null : col.getStorage()) { + case Fixed: + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + Out tempOut_value = new Out(); + ResultAssert.IsSuccess(t.typeAs().readFixed(tempReference_Row, root, col, tempOut_value)); + value = tempOut_value.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + break; + case Variable: + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + Out tempOut_value2 = new Out(); + ResultAssert.IsSuccess(t.typeAs().readVariable(tempReference_Row2, root, col, tempOut_value2)); + value = tempOut_value2.get(); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + break; + default: + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + Out tempOut_value3 = new Out(); + ResultAssert.IsSuccess(t.typeAs().readSparse(tempReference_Row3, root, tempOut_value3)); + value = tempOut_value3.get(); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + break; + } + + if (TValue.class.IsArray) { + CollectionAssert.AreEqual((Collection)expected, (Collection)value); + } else { + assert expected == value; + } + } + + public void DispatchArray(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor arrayScope; + Out tempOut_arrayScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_arrayScope)); + arrayScope = tempOut_arrayScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + int i = 0; + List items = (List)value; + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + while (arrayScope.MoveNext(tempReference_Row2)) { + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref arrayScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), items.get(i++)); + } + dispatcher.get().argValue.Row = tempReference_Row2.get(); + } + + public void DispatchMap(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 2); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor mapScope; + Out tempOut_mapScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_mapScope)); + mapScope = tempOut_mapScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + int i = 0; + List items = (List)value; + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + while (mapScope.MoveNext(tempReference_Row2)) { + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref mapScope, null, LayoutType.TypedTuple, typeArgs.clone(), + items.get(i++)); + } + dispatcher.get().argValue.Row = tempReference_Row2.get(); + } + + public void DispatchNullable(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor nullableScope; + Out tempOut_nullableScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_nullableScope)); + nullableScope = tempOut_nullableScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + if (value != null) { + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + Reference tempReference_nullableScope = + new Reference(nullableScope); + ResultAssert.IsSuccess(LayoutNullable.HasValue(tempReference_Row2, tempReference_nullableScope)); + nullableScope = tempReference_nullableScope.get(); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + nullableScope.MoveNext(tempReference_Row3); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref nullableScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), value); + } else { + Reference tempReference_Row4 = + new Reference(dispatcher.get().Row); + Reference tempReference_nullableScope2 = + new Reference(nullableScope); + ResultAssert.NotFound(LayoutNullable.HasValue(tempReference_Row4, tempReference_nullableScope2)); + nullableScope = tempReference_nullableScope2.get(); + dispatcher.get().argValue.Row = tempReference_Row4.get(); + } + } + + public void DispatchObject(Reference dispatcher, + Reference scope) { + } + + public void DispatchSet(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor setScope; + Out tempOut_setScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_setScope)); + setScope = tempOut_setScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + int i = 0; + List items = (List)value; + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + while (setScope.MoveNext(tempReference_Row2)) { + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref setScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), items.get(i++)); + } + dispatcher.get().argValue.Row = tempReference_Row2.get(); + } + + public void DispatchTuple(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() >= 2); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor tupleScope; + Out tempOut_tupleScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_tupleScope)); + tupleScope = tempOut_tupleScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + for (int i = 0; i < typeArgs.count(); i++) { + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + tupleScope.MoveNext(tempReference_Row2); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + PropertyInfo valueAccessor = value.getClass().GetProperty(String.format("Item%1$s", i + 1)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref tupleScope, null, typeArgs.get(i).type(), + typeArgs.get(i).typeArgs().clone(), valueAccessor.GetValue(value)); + } + } + + public void DispatchUDT(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + Reference tempReference_Row = new Reference(dispatcher.get().Row); + RowCursor udtScope; + Out tempOut_udtScope = new Out(); + ResultAssert.IsSuccess(t.typeAs().ReadScope(tempReference_Row, scope, tempOut_udtScope)); + udtScope = tempOut_udtScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + IDispatchable valueDispatcher = value instanceof IDispatchable ? (IDispatchable)value : null; + assert valueDispatcher != null; + Reference tempReference_udtScope = new Reference(udtScope); + valueDispatcher.Dispatch(dispatcher, tempReference_udtScope); + udtScope = tempReference_udtScope.get(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RecordIOUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RecordIOUnitTests.java new file mode 100644 index 0000000..59a9cc6 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RecordIOUnitTests.java @@ -0,0 +1,242 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.MemorySpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.recordio.RecordIOStream; +import com.azure.data.cosmos.serialization.hybridrow.io.Segment; +import com.azure.data.cosmos.serialization.hybridrow.unit.customerschema.Address; + +import java.nio.file.Files; +import java.util.ArrayList; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(RecordIOUnitTests.SchemaFile, "TestData")] public class RecordIOUnitTests +public class RecordIOUnitTests { + private static final int InitialRowSize = 0; + private static final String SchemaFile = "TestData\\CustomerSchema.json"; + private Layout addressLayout; + private Namespace ns; + private LayoutResolver resolver; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void LoadSchema() + public final void LoadSchema() { + LayoutResolver systemResolver = SystemSchema.LayoutResolver; + Layout segmentLayout = systemResolver.Resolve(SystemSchema.SegmentSchemaId); + assert segmentLayout.getName().equals("Segment"); + assert segmentLayout.getSchemaId().clone() == SystemSchema.SegmentSchemaId; + + Layout recordLayout = systemResolver.Resolve(SystemSchema.RecordSchemaId); + assert recordLayout.getName().equals("Record"); + assert recordLayout.getSchemaId().clone() == SystemSchema.RecordSchemaId; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public final void ParseNamespaceExample() { + String json = Files.readString(RecordIOUnitTests.SchemaFile); + this.ns = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.ns); + this.addressLayout = this.resolver.Resolve(tangible.ListHelper.find(this.ns.getSchemas(), x -> x.Name.equals( + "Address")).SchemaId); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public async Task RoundTripAsync() + // TODO: C# TO JAVA CONVERTER: There is no equivalent in Java to the 'async' keyword: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public async Task RoundTripAsync() + public final Task RoundTripAsync() { + Address tempVar = new Address(); + tempVar.setStreet("300B Chocolate Hole"); + tempVar.setCity("Great Cruz Bay"); + tempVar.setState("VI"); + PostalCode tempVar2 = new PostalCode(); + tempVar2.setZip(00830); + tempVar2.setPlus4(0001); + tempVar.setPostalCode(tempVar2); + Address tempVar3 = new Address(); + tempVar3.setStreet("1 Microsoft Way"); + tempVar3.setCity("Redmond"); + tempVar3.setState("WA"); + PostalCode tempVar4 = new PostalCode(); + tempVar4.setZip(98052); + tempVar3.setPostalCode(tempVar4); + Address[] addresses = { tempVar, tempVar3 }; + + String sampleComment = "hello there"; + String sampleSDL = "some SDL"; + + try (Stream stm = new MemoryStream()) { + // Create a reusable, resizable buffer. + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MemorySpanResizer resizer = new MemorySpanResizer(RecordIOUnitTests + // .InitialRowSize); + MemorySpanResizer resizer = new MemorySpanResizer(RecordIOUnitTests.InitialRowSize); + + // Write a RecordIO stream. + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'out' keyword - these are + // not converted by C# to Java Converter: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: Result r = await stm.WriteRecordIOAsync(new Segment(sampleComment, sampleSDL), (long + // index, out ReadOnlyMemory body) => + Result r = await + RecordIOStream.WriteRecordIOAsync(stm, + new Segment(sampleComment, sampleSDL), (long index, out ReadOnlyMemorybody) -> + { + body = null; + if (index >= addresses.length) { + return Result.SUCCESS; + } + + Out> tempOut_body = new Out>(); + Task tempVar5 = this.WriteAddress(resizer, addresses[index], tempOut_body); + body = tempOut_body.get(); + return tempVar5; + }); + + // Read a RecordIO stream. + ArrayList
addressesRead = new ArrayList
(); + stm.Position = 0; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: resizer = new MemorySpanResizer(1); + resizer = new MemorySpanResizer(1); + // TODO: C# TO JAVA CONVERTER: There is no equivalent to 'await' in Java: + r = await + RecordIOStream.ReadRecordIOAsync(stm, record -> + { + assert !record.IsEmpty; + + Address obj; + Out
tempOut_obj = new Out
(); + r = this.ReadAddress(record, tempOut_obj); + obj = tempOut_obj.get(); + ResultAssert.IsSuccess(r); + addressesRead.add(obj); + return Result.SUCCESS; + }, segment -> + { + assert !segment.IsEmpty; + + Segment obj; + Out tempOut_obj = + new Out(); + r = this.ReadSegment(segment, tempOut_obj); + obj = tempOut_obj.get(); + ResultAssert.IsSuccess(r); + assert obj.comment() == sampleComment; + assert obj.sdl() == sampleSDL; + return Result.SUCCESS; + }, resizer); + + ResultAssert.IsSuccess(r); + + // Check that the values all round-tripped. + assert addresses.length == addressesRead.size(); + for (int i = 0; i < addresses.length; i++) { + assert addresses[i] == addressesRead.get(i); + } + } + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private Result ReadAddress(Memory buffer, out Address obj) + private Result ReadAddress(Memory buffer, Out
obj) { + RowBuffer row = new RowBuffer(buffer.Span, HybridRowVersion.V1, this.resolver); + Reference tempReference_row = + new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + + // Use the reader to dump to the screen. + Reference tempReference_reader = + new Reference(reader); + String str; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Result r = DiagnosticConverter.ReaderToString(tempReference_reader, out str); + reader = tempReference_reader.get(); + if (r != Result.SUCCESS) { + obj.setAndGet(null); + return r; + } + + System.out.println(str); + + // Reset the reader and materialize the object. + Reference tempReference_row2 = + new Reference(row); + reader = new RowReader(tempReference_row2); + row = tempReference_row2.get(); + Reference tempReference_reader2 = + new Reference(reader); + Result tempVar = AddressSerializer.Read(tempReference_reader2, obj); + reader = tempReference_reader2.get(); + return tempVar; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private Result ReadSegment(Memory buffer, out Segment obj) + private Result ReadSegment(Memory buffer, Out obj) { + RowBuffer row = new RowBuffer(buffer.Span, HybridRowVersion.V1, SystemSchema.LayoutResolver); + Reference tempReference_row = + new Reference(row); + RowReader reader = new RowReader(tempReference_row); + row = tempReference_row.get(); + + // Use the reader to dump to the screen. + Reference tempReference_reader = + new Reference(reader); + String str; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Result r = DiagnosticConverter.ReaderToString(tempReference_reader, out str); + reader = tempReference_reader.get(); + if (r != Result.SUCCESS) { + obj.setAndGet(null); + return r; + } + + System.out.println(str); + + // Reset the reader and materialize the object. + Reference tempReference_row2 = new Reference(row); + reader = new RowReader(tempReference_row2); + row = tempReference_row2.get(); + Reference tempReference_reader2 = new Reference(reader); + Result tempVar = SegmentSerializer.Read(tempReference_reader2, obj.clone()); + reader = tempReference_reader2.get(); + return tempVar; + } + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private Result WriteAddress(MemorySpanResizer resizer, Address obj, out + // ReadOnlyMemory buffer) + private Result WriteAddress(MemorySpanResizer resizer, Address obj, + Out> buffer) { + RowBuffer row = new RowBuffer(RecordIOUnitTests.InitialRowSize, resizer); + row.initLayout(HybridRowVersion.V1, this.addressLayout, this.resolver); + Reference tempReference_row = + new Reference(row); + Result r = RowWriter.WriteBuffer(tempReference_row, obj, AddressSerializer.Write); + row = tempReference_row.get(); + if (r != Result.SUCCESS) { + buffer.setAndGet(null); + return r; + } + + buffer.setAndGet(resizer.getMemory().Slice(0, row.length())); + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ResultAssert.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ResultAssert.java new file mode 100644 index 0000000..cb0da5f --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/ResultAssert.java @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.serialization.hybridrow.Result; + +public final class ResultAssert { + public static void Exists(Result actual) { + assert Result.EXISTS == actual; + } + + public static void Exists(Result actual, String message) { + Assert.AreEqual(Result.EXISTS, actual, message); + } + + public static void Exists(Result actual, String message, Object... parameters) { + Assert.AreEqual(Result.EXISTS, actual, message, parameters); + } + + public static void InsufficientPermissions(Result actual) { + assert Result.INSUFFICIENT_PERMISSIONS == actual; + } + + public static void InsufficientPermissions(Result actual, String message) { + Assert.AreEqual(Result.INSUFFICIENT_PERMISSIONS, actual, message); + } + + public static void InsufficientPermissions(Result actual, String message, Object... parameters) { + Assert.AreEqual(Result.INSUFFICIENT_PERMISSIONS, actual, message, parameters); + } + + public static void IsSuccess(Result actual) { + assert Result.SUCCESS == actual; + } + + public static void IsSuccess(Result actual, String message) { + Assert.AreEqual(Result.SUCCESS, actual, message); + } + + public static void IsSuccess(Result actual, String message, Object... parameters) { + Assert.AreEqual(Result.SUCCESS, actual, message, parameters); + } + + public static void NotFound(Result actual) { + assert Result.NOT_FOUND == actual; + } + + public static void NotFound(Result actual, String message) { + Assert.AreEqual(Result.NOT_FOUND, actual, message); + } + + public static void NotFound(Result actual, String message, Object... parameters) { + Assert.AreEqual(Result.NOT_FOUND, actual, message, parameters); + } + + public static void TypeConstraint(Result actual) { + assert Result.TYPE_CONSTRAINT == actual; + } + + public static void TypeConstraint(Result actual, String message) { + Assert.AreEqual(Result.TYPE_CONSTRAINT, actual, message); + } + + public static void TypeConstraint(Result actual, String message, Object... parameters) { + Assert.AreEqual(Result.TYPE_CONSTRAINT, actual, message, parameters); + } + + public static void TypeMismatch(Result actual) { + assert Result.TYPE_MISMATCH == actual; + } + + public static void TypeMismatch(Result actual, String message) { + Assert.AreEqual(Result.TYPE_MISMATCH, actual, message); + } + + public static void TypeMismatch(Result actual, String message, Object... parameters) { + Assert.AreEqual(Result.TYPE_MISMATCH, actual, message, parameters); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowBufferUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowBufferUnitTests.java new file mode 100644 index 0000000..c7bd056 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowBufferUnitTests.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public class RowBufferUnitTests +public class RowBufferUnitTests { + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][SuppressMessage("StyleCop.CSharp.ReadabilityRules", + // "SA1139:UseLiteralsSuffixNotationInsteadOfCasting", Justification = "Explicit")] public void VarIntTest() + public final void VarIntTest() { + // Brute force test all signed 16-bit values. + for (int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) { + short s = (short)i; + this.RoundTripVarInt(s); + } + + // Test boundary conditions for larger values. + this.RoundTripVarInt(0); + this.RoundTripVarInt(Integer.MIN_VALUE); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.RoundTripVarInt(unchecked((int)0x80000000ul)); + this.RoundTripVarInt(0x80000000); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.RoundTripVarInt(unchecked((int)0x7FFFFFFFul)); + this.RoundTripVarInt(0x7FFFFFFF); + this.RoundTripVarInt(Integer.MAX_VALUE); + this.RoundTripVarInt(Long.MIN_VALUE); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.RoundTripVarInt(unchecked((long)0x8000000000000000ul)); + this.RoundTripVarInt((long)0x8000000000000000); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: this.RoundTripVarInt(unchecked((long)0x7FFFFFFFFFFFFFFFul)); + this.RoundTripVarInt((long)0x7FFFFFFFFFFFFFFF); + this.RoundTripVarInt(Long.MAX_VALUE); + } + + private void RoundTripVarInt(short s) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ulong encoded = RowBuffer.RotateSignToLsb(s); + long encoded = RowBuffer.rotateSignToLsb(s); + long decoded = RowBuffer.rotateSignToMsb(encoded); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: short t = unchecked((short)decoded); + short t = (short)decoded; + Assert.AreEqual(s, t, "Value: {0}", s); + } + + private void RoundTripVarInt(int s) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ulong encoded = RowBuffer.RotateSignToLsb(s); + long encoded = RowBuffer.rotateSignToLsb(s); + long decoded = RowBuffer.rotateSignToMsb(encoded); + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to 'unchecked' in this context: + //ORIGINAL LINE: int t = unchecked((int)decoded); + int t = (int)decoded; + Assert.AreEqual(s, t, "Value: {0}", s); + } + + private void RoundTripVarInt(long s) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ulong encoded = RowBuffer.RotateSignToLsb(s); + long encoded = RowBuffer.rotateSignToLsb(s); + long decoded = RowBuffer.rotateSignToMsb(encoded); + Assert.AreEqual(s, decoded, "Value: {0}", s); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowOperationDispatcher.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowOperationDispatcher.java new file mode 100644 index 0000000..59a65a1 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowOperationDispatcher.java @@ -0,0 +1,437 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBinary; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBoolean; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutDecimal; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat128; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutGuid; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt16; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutMongoDbObjectId; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutNull; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt16; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUtf8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutVarInt; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutVarUInt; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; +import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1402 // FileMayOnlyContainASingleType +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1201 // OrderingRules +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Public Fields + + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal ref struct RowOperationDispatcher +//C# TO JAVA CONVERTER WARNING: Java has no equivalent to the C# ref struct: +public final class RowOperationDispatcher { + private static final int InitialRowSize = 2 * 1024 * 1024; + public LayoutResolver Resolver; + public RowBuffer Row = new RowBuffer(); + private IDispatcher dispatcher; + + public RowOperationDispatcher() { + } + + private RowOperationDispatcher(IDispatcher dispatcher, Layout layout, LayoutResolver resolver) { + this.dispatcher = dispatcher; + this.Row = new RowBuffer(RowOperationDispatcher.InitialRowSize); + this.Resolver = resolver; + this.Row.initLayout(HybridRowVersion.V1, layout, this.Resolver); + } + + private RowOperationDispatcher(IDispatcher dispatcher, LayoutResolver resolver, String expected) { + this.dispatcher = dispatcher; + this.Row = new RowBuffer(RowOperationDispatcher.InitialRowSize); + this.Resolver = resolver; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: byte[] bytes = ByteConverter.ToBytes(expected); + byte[] bytes = ByteConverter.ToBytes(expected); + this.Row.readFrom(bytes, HybridRowVersion.V1, this.Resolver); + } + + // TODO: C# TO JAVA CONVERTER: The C# 'struct' constraint has no equivalent in Java: + //ORIGINAL LINE: public static RowOperationDispatcher Create(Layout layout, LayoutResolver resolver) + // where TDispatcher : struct, IDispatcher + public static RowOperationDispatcher Create(Layout layout, + LayoutResolver resolver) { + return new RowOperationDispatcher(null, layout, resolver); + } + + public RowReader GetReader() { + Reference tempReference_Row = + new Reference(this.Row); + // TODO: C# TO JAVA CONVERTER: The following line could not be converted: + return new RowReader(ref this.Row) + this.Row = tempReference_Row.get(); + return tempVar; + } + + public void LayoutCodeSwitch(String path, LayoutType type, TypeArgumentList typeArgs) { + LayoutCodeSwitch(path, type, typeArgs, null); + } + + public void LayoutCodeSwitch(String path, LayoutType type) { + LayoutCodeSwitch(path, type, null, null); + } + + public void LayoutCodeSwitch(String path) { + LayoutCodeSwitch(path, null, null, null); + } + + public void LayoutCodeSwitch() { + LayoutCodeSwitch(null, null, null, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public void LayoutCodeSwitch(string path = null, LayoutType type = null, TypeArgumentList + // typeArgs = default, object value = null) + public void LayoutCodeSwitch(String path, LayoutType type, TypeArgumentList typeArgs, Object value) { + Reference tempReference_Row = + new Reference(this.Row); + RowCursor root = RowCursor.create(tempReference_Row); + this.Row = tempReference_Row.get(); + Reference tempReference_root = + new Reference(root); + this.LayoutCodeSwitch(tempReference_root, path, type, typeArgs.clone(), value); + root = tempReference_root.get(); + } + + public void LayoutCodeSwitch(Reference scope, String path, LayoutType type, + TypeArgumentList typeArgs) { + LayoutCodeSwitch(scope, path, type, typeArgs, null); + } + + public void LayoutCodeSwitch(Reference scope, String path, LayoutType type) { + LayoutCodeSwitch(scope, path, type, null, null); + } + + public void LayoutCodeSwitch(Reference scope, String path) { + LayoutCodeSwitch(scope, path, null, null, null); + } + + public void LayoutCodeSwitch(Reference scope) { + LayoutCodeSwitch(scope, null, null, null, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public void LayoutCodeSwitch(ref RowCursor scope, string path = null, LayoutType type = null, + // TypeArgumentList typeArgs = default, object value = null) + public void LayoutCodeSwitch(Reference scope, String path, LayoutType type, + TypeArgumentList typeArgs, Object value) { + LayoutColumn col = null; + if (type == null) { + assert path != null; + Out tempOut_col = + new Out(); + assert scope.get().getLayout().TryFind(path, tempOut_col); + col = tempOut_col.get(); + assert col != null; + type = col.type(); + typeArgs = col.typeArgs().clone(); + } + + if ((path != null) && (col == null || col.storage() == StorageKind.SPARSE)) { + Reference tempReference_Row = + new Reference(this.Row); + scope.get().Find(tempReference_Row, path); + this.Row = tempReference_Row.get(); + } + + switch (type.LayoutCode) { + case Null: + Reference tempReference_this = new Reference(this); + this.dispatcher.Dispatch(tempReference_this, scope, col, type, NullValue.DEFAULT); + this = tempReference_this.get(); + break; + case Boolean: + Reference tempReference_this2 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this2, scope, col, type, + value != null ? value : + default) + this = tempReference_this2.get(); + + break; + case Int8: + Reference tempReference_this3 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this3, scope, col, type, value != null ? + value : + default) + this = tempReference_this3.get(); + + break; + case Int16: + Reference tempReference_this4 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this4, scope, col, type, value != null ? + value : + default) + this = tempReference_this4.get(); + + break; + case Int32: + Reference tempReference_this5 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this5, scope, col, type, + value != null ? value : + default) + this = tempReference_this5.get(); + break; + case Int64: + Reference tempReference_this6 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this6, scope, col, type, value != null ? + value : + default) + this = tempReference_this6.get(); + break; + case UInt8: + Reference tempReference_this7 = new Reference(this); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.dispatcher.Dispatch(tempRef_this7, scope, col, type, + // (Nullable)value != null ? value : default); + this.dispatcher.Dispatch(tempReference_this7, scope, col, type, value != null ? + value : + default) + this = tempReference_this7.get(); + break; + case UInt16: + Reference tempReference_this8 = new Reference(this); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.dispatcher.Dispatch(tempRef_this8, scope, col, type, + // (Nullable)value != null ? value : default); + this.dispatcher.Dispatch(tempReference_this8, scope, col, type, value != null ? + value : + default) + this = tempReference_this8.get(); + + break; + case UInt32: + Reference tempReference_this9 = new Reference(this); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.dispatcher.Dispatch(tempRef_this9, scope, col, type, + // (Nullable)value != null ? value : default); + this.dispatcher.Dispatch(tempReference_this9, scope, col, type, + value != null ? value : + default) + this = tempReference_this9.get(); + break; + case UInt64: + Reference tempReference_this10 = new Reference(this); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.dispatcher.Dispatch(tempRef_this10, scope, col, type, + // (Nullable)value != null ? value : default); + this.dispatcher.Dispatch(tempReference_this10, scope, col, type, value != null ? + value : + default) + this = tempReference_this10.get(); + + break; + case VarInt: + Reference tempReference_this11 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this11, scope, col, type, value != null ? + value : + default) + this = tempReference_this11.get(); + break; + case VarUInt: + Reference tempReference_this12 = new Reference(this); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.dispatcher.Dispatch(tempRef_this12, scope, col, type, + // (Nullable)value != null ? value : default); + this.dispatcher.Dispatch(tempReference_this12, scope, col, type, value != null ? + value : + default) + this = tempReference_this12.get(); + + break; + case Float32: + Reference tempReference_this13 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this13, scope, col, type, + value != null ? value : + default) + this = tempReference_this13.get(); + + break; + case Float64: + Reference tempReference_this14 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this14, scope, col, type, + value != null ? value : + default) + this = tempReference_this14.get(); + + break; + case Float128: + Reference tempReference_this15 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this15, scope, col, type, + value != null ? value : + default) + this = tempReference_this15.get(); + + break; + case Decimal: + Reference tempReference_this16 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this16, scope, col, type, + value != null ? value : + default) + this = tempReference_this16.get(); + + break; + case DateTime: + Reference tempReference_this17 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this17, scope, col, type, + value != null ? value : + default) + this = tempReference_this17.get(); + + break; + case UnixDateTime: + Reference tempReference_this18 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this18, scope, col, type, + value != null ? value : + default) + this = tempReference_this18.get(); + + break; + case Guid: + Reference tempReference_this19 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this19, scope, col, type, value != null ? + value : + default) + this = tempReference_this19.get(); + break; + case MongoDbObjectId: + Reference tempReference_this20 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this20, scope, col, type, + value != null ? value : + default) + this = tempReference_this20.get(); + + break; + case Utf8: + Reference tempReference_this21 = new Reference(this); + this.dispatcher.Dispatch(tempReference_this21, scope, col, type, (String)value); + this = tempReference_this21.get(); + + break; + case Binary: + Reference tempReference_this22 = new Reference(this); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: this.dispatcher.Dispatch(ref this, ref scope, col, type, + // (byte[])value); + this.dispatcher.Dispatch(tempReference_this22, scope, col, type, (byte[])value); + this = tempReference_this22.get(); + + break; + case ObjectScope: + case ImmutableObjectScope: + Reference tempReference_this23 = new Reference(this); + this.dispatcher.DispatchObject(tempReference_this23, scope); + this = tempReference_this23.get(); + break; + case TypedArrayScope: + case ImmutableTypedArrayScope: + Reference tempReference_this24 = new Reference(this); + this.dispatcher.DispatchArray(tempReference_this24, scope, type, typeArgs.clone(), value); + this = tempReference_this24.get(); + break; + case TypedSetScope: + case ImmutableTypedSetScope: + Reference tempReference_this25 = new Reference(this); + this.dispatcher.DispatchSet(tempReference_this25, scope, type, typeArgs.clone(), value); + this = tempReference_this25.get(); + break; + case TypedMapScope: + case ImmutableTypedMapScope: + Reference tempReference_this26 = new Reference(this); + this.dispatcher.DispatchMap(tempReference_this26, scope, type, typeArgs.clone(), value); + this = tempReference_this26.get(); + break; + case TupleScope: + case ImmutableTupleScope: + case TypedTupleScope: + case ImmutableTypedTupleScope: + case TaggedScope: + case ImmutableTaggedScope: + case Tagged2Scope: + case ImmutableTagged2Scope: + Reference tempReference_this27 = new Reference(this); + this.dispatcher.DispatchTuple(tempReference_this27, scope, type, typeArgs.clone(), value); + this = tempReference_this27.get(); + break; + case NullableScope: + Reference tempReference_this28 = new Reference(this); + this.dispatcher.DispatchNullable(tempReference_this28, scope, type, typeArgs.clone(), value); + this = tempReference_this28.get(); + break; + case Schema: + case ImmutableSchema: + Reference tempReference_this29 = new Reference(this); + this.dispatcher.DispatchUDT(tempReference_this29, scope, type, typeArgs.clone(), value); + this = tempReference_this29.get(); + break; + default: + if (logger.) + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s", type.LayoutCode)); + break; + } + } + + // TODO: C# TO JAVA CONVERTER: The C# 'struct' constraint has no equivalent in Java: + //ORIGINAL LINE: public static RowOperationDispatcher ReadFrom(LayoutResolver resolver, string + // expected) where TDispatcher : struct, IDispatcher + public static RowOperationDispatcher ReadFrom(LayoutResolver resolver, + String expected) { + return new RowOperationDispatcher(null, resolver, expected); + } + + public String RowToHex() { + try (MemoryStream stm = new MemoryStream()) { + this.Row.writeTo(stm); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ReadOnlyMemory bytes = stm.GetBuffer().AsMemory(0, (int)stm.Position); + ReadOnlyMemory bytes = stm.GetBuffer().AsMemory(0, (int)stm.Position); + return ByteConverter.ToHex(bytes.Span); + } + } + + public RowOperationDispatcher clone() { + RowOperationDispatcher varCopy = new RowOperationDispatcher(); + + varCopy.Resolver = this.Resolver; + varCopy.Row = this.Row.clone(); + varCopy.dispatcher = this.dispatcher; + + return varCopy; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowReaderUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowReaderUnitTests.java new file mode 100644 index 0000000..1b9600f --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowReaderUnitTests.java @@ -0,0 +1,426 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.MemorySpanResizer; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; + +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("StyleCop.CSharp.ReadabilityRules", +// "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Test code.")][DeploymentItem(RowReaderUnitTests +// .SchemaFile, "TestData")] public sealed class RowReaderUnitTests +public final class RowReaderUnitTests { + private static final LocalDateTime SampleDateTime = LocalDateTime.parse("2018-08-14 02:05:00.0000000"); + private static final Float128 SampleFloat128 = new Float128(0, 42); + private static final UUID SampleGuid = UUID.fromString("{2A9C25B9-922E-4611-BB0A-244A9496503C}"); + private static final MongoDbObjectId SampleMongoDbObjectId = new MongoDbObjectId(0, 42); + private static final UnixDateTime SampleUnixDateTime = new UnixDateTime(42); + private static final String SchemaFile = "TestData\\ReaderSchema.json"; + private LayoutResolver resolver; + private Namespace schema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString(RowReaderUnitTests.SchemaFile); + this.schema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.schema); + } + + public static void PrintReader(Reference reader, int indent) { + String str; + Out tempOut_str = new Out(); + ResultAssert.IsSuccess(DiagnosticConverter.ReaderToString(reader, tempOut_str)); + str = tempOut_str.get(); + System.out.println(str); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ReadMixed() + public void ReadMixed() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Mixed")).SchemaId); + assert layout != null; + + RowOperationDispatcher d = RowOperationDispatcher.Create(layout, this.resolver); + d.LayoutCodeSwitch("null"); + d.LayoutCodeSwitch("bool", value:true) + d.LayoutCodeSwitch("int8", value:(byte)-86) + d.LayoutCodeSwitch("int16", value:(short)-21846) + d.LayoutCodeSwitch("int32", value:-1431655766) + d.LayoutCodeSwitch("int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("float128", value:RowReaderUnitTests.SampleFloat128) + d.LayoutCodeSwitch("decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("datetime", value:RowReaderUnitTests.SampleDateTime) + d.LayoutCodeSwitch("unixdatetime", value:RowReaderUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("guid", value:RowReaderUnitTests.SampleGuid) + d.LayoutCodeSwitch("mongodbobjectid", value:RowReaderUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("utf8", value:"abc") + d.LayoutCodeSwitch("utf8_span", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("binary_span", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("binary_span", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + d.LayoutCodeSwitch("var_varint", value:-6148914691236517206L) + d.LayoutCodeSwitch("var_varuint", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("var_utf8", value:"abc") + d.LayoutCodeSwitch("var_utf8_span", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("var_binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("var_binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("var_binary_span", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("var_binary_span", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + d.LayoutCodeSwitch("sparse_null"); + d.LayoutCodeSwitch("sparse_bool", value:true) + d.LayoutCodeSwitch("sparse_int8", value:(byte)-86) + d.LayoutCodeSwitch("sparse_int16", value:(short)-21846) + d.LayoutCodeSwitch("sparse_int32", value:-1431655766) + d.LayoutCodeSwitch("sparse_int64", value:-6148914691236517206L) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("sparse_uint8", value: (byte)0xAA); + d.LayoutCodeSwitch("sparse_uint8", value:(byte)0xAA) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("sparse_uint16", value: (ushort)0xAAAA); + d.LayoutCodeSwitch("sparse_uint16", value:(short)0xAAAA) + d.LayoutCodeSwitch("sparse_uint32", value:0xAAAAAAAA) + d.LayoutCodeSwitch("sparse_uint64", value:0xAAAAAAAAAAAAAAAAL) + d.LayoutCodeSwitch("sparse_float32", value:1.0F / 3.0F) + d.LayoutCodeSwitch("sparse_float64", value:1.0 / 3.0) + d.LayoutCodeSwitch("sparse_float128", value:RowReaderUnitTests.SampleFloat128) + d.LayoutCodeSwitch("sparse_decimal", value:java.math.BigDecimal.ONE / 3.0) + d.LayoutCodeSwitch("sparse_datetime", value:RowReaderUnitTests.SampleDateTime) + d.LayoutCodeSwitch("sparse_unixdatetime", value:RowReaderUnitTests.SampleUnixDateTime) + d.LayoutCodeSwitch("sparse_guid", value:RowReaderUnitTests.SampleGuid) + d.LayoutCodeSwitch("sparse_mongodbobjectid", value:RowReaderUnitTests.SampleMongoDbObjectId) + d.LayoutCodeSwitch("sparse_utf8", value:"abc") + d.LayoutCodeSwitch("sparse_utf8_span", value:"abc") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("sparse_binary", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("sparse_binary", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("sparse_binary_span", value: new[] { (byte)0, (byte)1, (byte)2 }); + d.LayoutCodeSwitch("sparse_binary_span", value:new byte[] { (byte)0, (byte)1, (byte)2 }) + d.LayoutCodeSwitch("array_t", value:new byte[] { -86, -86, -86 }) + d.LayoutCodeSwitch("array_t>", value:new float[][] + { + new float[] { 1, 2, 3 }, + new float[] { 1, 2, 3 } + }) + d.LayoutCodeSwitch("array_t", value:new String[] { "abc", "def", "hij" }) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(-6148914691236517206L, -6148914691236517206L)) + d.LayoutCodeSwitch("tuple>", value: + Tuple.Create(NullValue.DEFAULT, Tuple.Create((byte)-86, (byte)-86))) + d.LayoutCodeSwitch("tuple", value:Tuple.Create(false, new Point(1, 2))) + d.LayoutCodeSwitch("nullable", value:Tuple.Create(null, (Long)123L)) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("tagged", value: Tuple.Create((byte)3, "hello")); + d.LayoutCodeSwitch("tagged", value:Tuple.Create((byte)3, "hello")) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: d.LayoutCodeSwitch("tagged", value: Tuple.Create((byte)5, true, "bye")); + d.LayoutCodeSwitch("tagged", value:Tuple.Create((byte)5, true, "bye")) + d.LayoutCodeSwitch("set_t", value:new String[] { "abc", "efg", "xzy" }) + d.LayoutCodeSwitch("set_t>", value:new byte[][] + { + new byte[] { 1, 2, 3 }, + new byte[] { 4, 5, 6 }, + new byte[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t>", value:new int[][] + { + new int[] { 1, 2, 3 }, + new int[] { 4, 5, 6 }, + new int[] { 7, 8, 9 } + }) + d.LayoutCodeSwitch("set_t", value:new Point[] + { + new Point(1, 2), + new Point(3, 4), + new Point(5, 6) + }) + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create("Mark", "Luke"), Tuple.Create("Harrison", "Han") }) + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((byte)1, new byte[] { 1, 2, 3 }), Tuple.Create((byte)2, + new byte[] { 4, 5, 6 }) }) + + d.LayoutCodeSwitch("map_t>", value: + new System.Tuple[] { Tuple.Create((short)1, new System.Tuple[] { Tuple.Create(1, 2), + Tuple.Create(3, 4) }), Tuple.Create((short)2, new System.Tuple[] { Tuple.Create(5, 6), + Tuple.Create(7, 8) }) }) + + d.LayoutCodeSwitch("map_t", value: + new System.Tuple[] { Tuple.Create(1.0, new Point(1, 2)), Tuple.Create(2.0, new Point(3, 4)), + Tuple.Create(3.0, new Point(5, 6)) }) + + RowReader reader = d.GetReader().clone(); + assert reader.length() == d.Row.length(); + Reference tempReference_reader = + new Reference(reader); + RowReaderUnitTests.PrintReader(tempReference_reader, 0); + reader = tempReference_reader.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ReadScopes() + public void ReadScopes() { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: MemorySpanResizer resizer = new MemorySpanResizer(0); + MemorySpanResizer resizer = new MemorySpanResizer(0); + RowBuffer row = new RowBuffer(0, resizer); + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Mixed")).SchemaId); + row.initLayout(HybridRowVersion.V1, layout, this.resolver); + + Reference tempReference_row = + new Reference(row); + ResultAssert.IsSuccess(RowWriter.WriteBuffer(tempReference_row, 2, RowReaderUnitTests.WriteNestedDocument)); + row = tempReference_row.get(); + Reference tempReference_row2 = + new Reference(row); + RowReader rowReader = new RowReader(tempReference_row2); + row = tempReference_row2.get(); + + Reference tempReference_rowReader = + new Reference(rowReader); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadNestedDocumentDelegate(tempReference_rowReader, 0)); + rowReader = tempReference_rowReader.get(); + + Reference tempReference_row3 = + new Reference(row); + rowReader = new RowReader(tempReference_row3); + row = tempReference_row3.get(); + Reference tempReference_rowReader2 = + new Reference(rowReader); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadNestedDocumentNonDelegate(tempReference_rowReader2, 0)); + rowReader = tempReference_rowReader2.get(); + + Reference tempReference_row4 = + new Reference(row); + rowReader = new RowReader(tempReference_row4); + row = tempReference_row4.get(); + Reference tempReference_rowReader3 = + new Reference(rowReader); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadNestedDocumentNonDelegateWithSkipScope(tempReference_rowReader3, 0)); + rowReader = tempReference_rowReader3.get(); + + // SkipScope not okay after advancing parent + Reference tempReference_row5 = + new Reference(row); + rowReader = new RowReader(tempReference_row5); + row = tempReference_row5.get(); + assert rowReader.read(); + assert rowReader.type().LayoutCode == LayoutCode.ObjectScope; + RowReader nestedScope = rowReader.readScope().clone(); + Reference tempReference_nestedScope = + new Reference(nestedScope); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadNestedDocumentDelegate(tempReference_nestedScope, 0)); + nestedScope = tempReference_nestedScope.get(); + assert rowReader.read(); + Reference tempReference_nestedScope2 = + new Reference(nestedScope); + Result result = rowReader.skipScope(tempReference_nestedScope2); + nestedScope = tempReference_nestedScope2.get(); + assert Result.SUCCESS != result; + } + + private static Result ReadNestedDocumentDelegate(Reference reader, int context) { + while (reader.get().read()) { + switch (reader.get().type().LayoutCode) { + case TupleScope: { + ResultAssert.IsSuccess(reader.get().readScope(0, RowReaderUnitTests.ReadTuplePartial)); + break; + } + + case ObjectScope: { + ResultAssert.IsSuccess(reader.get().readScope(0, RowReaderUnitTests.ReadNestedDocumentDelegate)); + break; + } + } + } + + return Result.SUCCESS; + } + + private static Result ReadNestedDocumentNonDelegate(Reference reader, int context) { + while (reader.get().read()) { + switch (reader.get().type().LayoutCode) { + case TupleScope: { + RowReader nested = reader.get().readScope().clone(); + Reference tempReference_nested = + new Reference(nested); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadTuplePartial(tempReference_nested, 0)); + nested = tempReference_nested.get(); + break; + } + + case ObjectScope: { + RowReader nested = reader.get().readScope().clone(); + Reference tempReference_nested2 = + new Reference(nested); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadNestedDocumentNonDelegate(tempReference_nested2, 0)); + nested = tempReference_nested2.get(); + ResultAssert.IsSuccess(reader.get().readScope(0, RowReaderUnitTests.ReadNestedDocumentDelegate)); + break; + } + } + } + + return Result.SUCCESS; + } + + private static Result ReadNestedDocumentNonDelegateWithSkipScope(Reference reader, + int context) { + while (reader.get().read()) { + switch (reader.get().type().LayoutCode) { + case TupleScope: { + RowReader nested = reader.get().readScope().clone(); + Reference tempReference_nested = + new Reference(nested); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadTuplePartial(tempReference_nested, 0)); + nested = tempReference_nested.get(); + Reference tempReference_nested2 = + new Reference(nested); + ResultAssert.IsSuccess(reader.get().skipScope(tempReference_nested2)); + nested = tempReference_nested2.get(); + break; + } + + case ObjectScope: { + RowReader nested = reader.get().readScope().clone(); + Reference tempReference_nested3 = + new Reference(nested); + ResultAssert.IsSuccess(RowReaderUnitTests.ReadNestedDocumentNonDelegate(tempReference_nested3, 0)); + nested = tempReference_nested3.get(); + ResultAssert.IsSuccess(reader.get().readScope(0, RowReaderUnitTests.ReadNestedDocumentDelegate)); + Reference tempReference_nested4 = new Reference(nested); + ResultAssert.IsSuccess(reader.get().skipScope(tempReference_nested4)); + nested = tempReference_nested4.get(); + break; + } + } + } + + return Result.SUCCESS; + } + + private static Result ReadTuplePartial(Reference reader, int unused) { + // Read only part of our tuple + assert reader.get().read(); + assert reader.get().read(); + return Result.SUCCESS; + } + + private static Result WriteNestedDocument(Reference writer, TypeArgument typeArgument, + int level) { + TypeArgument tupleArgument = new TypeArgument(LayoutType.Tuple, new TypeArgumentList(new TypeArgument[] + { + new TypeArgument(LayoutType.Int32), + new TypeArgument(LayoutType.Int32), + new TypeArgument(LayoutType.Int32) + })); + + // TODO: C# TO JAVA CONVERTER: Local functions are not converted by C# to Java Converter: + // Result WriteTuple(ref RowWriter tupleWriter, TypeArgument tupleTypeArgument, int unused) + // { + // ResultAssert.IsSuccess(tupleWriter.WriteInt32(null, 1)); + // ResultAssert.IsSuccess(tupleWriter.WriteInt32(null, 2)); + // ResultAssert.IsSuccess(tupleWriter.WriteInt32(null, 3)); + // return Result.Success; + // } + + if (level == 0) { + ResultAssert.IsSuccess(writer.get().WriteScope("x", tupleArgument.clone(), 0, WriteTuple)); + return Result.SUCCESS; + } + + ResultAssert.IsSuccess(writer.get().WriteScope("a", new TypeArgument(LayoutType.Object), level - 1, + RowReaderUnitTests.WriteNestedDocument)); + ResultAssert.IsSuccess(writer.get().WriteScope("x", tupleArgument.clone(), 0, WriteTuple)); + ResultAssert.IsSuccess(writer.get().WriteScope("b", new TypeArgument(LayoutType.Object), level - 1, + RowReaderUnitTests.WriteNestedDocument)); + ResultAssert.IsSuccess(writer.get().WriteScope("y", tupleArgument.clone(), 0, WriteTuple)); + ResultAssert.IsSuccess(writer.get().WriteScope("c", new TypeArgument(LayoutType.Object), level - 1, + RowReaderUnitTests.WriteNestedDocument)); + + return Result.SUCCESS; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] internal sealed class Point : IDispatchable, IRowSerializable + public final static class Point implements IDispatchable, IRowSerializable { + public int X; + public int Y; + + public Point(int x, int y) { + this.X = x; + this.Y = y; + } + + public void Dispatch(Reference dispatcher, Reference scope) { + dispatcher.get().LayoutCodeSwitch(scope, "x", value:this.X) + dispatcher.get().LayoutCodeSwitch(scope, "y", value:this.Y) + } + + public Result Write(Reference writer, TypeArgument typeArg) { + Result result = writer.get().WriteInt32("x", this.X); + if (result != Result.SUCCESS) { + return result; + } + + return writer.get().WriteInt32("y", this.Y); + } + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + return obj instanceof Point && this.equals((Point)obj); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + return ((new Integer(this.X)).hashCode() * 397) ^ (new Integer(this.Y)).hashCode(); + } + } + + private boolean equals(Point other) { + return this.X == other.X && this.Y == other.Y; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowWriterUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowWriterUnitTests.java new file mode 100644 index 0000000..79fa2e8 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/RowWriterUnitTests.java @@ -0,0 +1,509 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; + +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("StyleCop.CSharp.ReadabilityRules", +// "SA1118:ParameterMustNotSpanMultipleLines", Justification = "Test code.")][DeploymentItem(RowWriterUnitTests +// .SchemaFile, "TestData")] public sealed class RowWriterUnitTests +public final class RowWriterUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final LocalDateTime SampleDateTime = LocalDateTime.parse("2018-08-14 02:05:00.0000000"); + private static final Float128 SampleFloat128 = new Float128(0, 42); + private static final UUID SampleGuid = UUID.fromString("{2A9C25B9-922E-4611-BB0A-244A9496503C}"); + private static final MongoDbObjectId SampleMongoDbObjectId = new MongoDbObjectId(0, 42); + private static final UnixDateTime SampleUnixDateTime = new UnixDateTime(42); + private static final String SchemaFile = "TestData\\ReaderSchema.json"; + private LayoutResolver resolver; + private Namespace schema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void TestInitialize() + public void TestInitialize() { + String json = Files.readString(RowWriterUnitTests.SchemaFile); + this.schema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.schema); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void WriteMixed() + public void WriteMixed() { + Layout layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "Mixed")).SchemaId); + assert layout != null; + + RowBuffer row = new RowBuffer(RowWriterUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, layout, this.resolver); + + int writerLength = 0; + Reference tempReference_row = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + ResultAssert.IsSuccess(RowWriter.writeBuffer(tempReference_row, null, (RowWriter RowWriter writer, + TypeArgument rootTypeArg, Object ignored) -> + { + ResultAssert.IsSuccess(writer.WriteNull("null")); + ResultAssert.IsSuccess(writer.WriteBool("bool", true)); + ResultAssert.IsSuccess(writer.WriteInt8("int8", (byte)-86)); + ResultAssert.IsSuccess(writer.WriteInt16("int16", (short)-21846)); + ResultAssert.IsSuccess(writer.WriteInt32("int32", -1431655766)); + ResultAssert.IsSuccess(writer.WriteInt64("int64", -6148914691236517206L)); + ResultAssert.IsSuccess(writer.WriteUInt8("uint8", (byte)0xAA)); + ResultAssert.IsSuccess(writer.WriteUInt16("uint16", (short)0xAAAA)); + ResultAssert.IsSuccess(writer.WriteUInt32("uint32", 0xAAAAAAAA)); + ResultAssert.IsSuccess(writer.WriteUInt64("uint64", 0xAAAAAAAAAAAAAAAAL)); + ResultAssert.IsSuccess(writer.WriteFloat32("float32", 1.0F / 3.0F)); + ResultAssert.IsSuccess(writer.WriteFloat64("float64", 1.0 / 3.0)); + ResultAssert.IsSuccess(writer.WriteFloat128("float128", RowWriterUnitTests.SampleFloat128)); + ResultAssert.IsSuccess(writer.WriteDecimal("decimal", java.math.BigDecimal.ONE / 3.0)); + ResultAssert.IsSuccess(writer.WriteDateTime("datetime", RowWriterUnitTests.SampleDateTime)); + ResultAssert.IsSuccess(writer.WriteUnixDateTime("unixdatetime", RowWriterUnitTests.SampleUnixDateTime)); + ResultAssert.IsSuccess(writer.WriteGuid("guid", RowWriterUnitTests.SampleGuid)); + ResultAssert.IsSuccess(writer.WriteMongoDbObjectId("mongodbobjectid", + RowWriterUnitTests.SampleMongoDbObjectId)); + ResultAssert.IsSuccess(writer.WriteString("utf8", "abc")); + ResultAssert.IsSuccess(writer.WriteString("utf8_span", Utf8Span.TranscodeUtf16("abc"))); + ResultAssert.IsSuccess(writer.WriteBinary("binary", new byte[] { (byte)0, (byte)1, (byte)2 })); + ResultAssert.IsSuccess(writer.WriteBinary("binary_span", + new byte[] { (byte)0, (byte)1, (byte)2 }.AsSpan())); + ResultAssert.IsSuccess(writer.WriteBinary("binary_sequence", + new ReadOnlySequence(new byte[] { (byte)0, (byte)1, (byte)2 }))); + + ResultAssert.IsSuccess(writer.WriteVarInt("var_varint", -6148914691236517206L)); + ResultAssert.IsSuccess(writer.WriteVarUInt("var_varuint", 0xAAAAAAAAAAAAAAAAL)); + ResultAssert.IsSuccess(writer.WriteString("var_utf8", "abc")); + ResultAssert.IsSuccess(writer.WriteString("var_utf8_span", Utf8Span.TranscodeUtf16("abc"))); + ResultAssert.IsSuccess(writer.WriteBinary("var_binary", new byte[] { (byte)0, (byte)1, (byte)2 })); + ResultAssert.IsSuccess(writer.WriteBinary("var_binary_span", + new byte[] { (byte)0, (byte)1, (byte)2 }.AsSpan())); + ResultAssert.IsSuccess(writer.WriteBinary("var_binary_sequence", + new ReadOnlySequence(new byte[] { (byte)0, (byte)1, (byte)2 }))); + + ResultAssert.IsSuccess(writer.WriteNull("sparse_null")); + ResultAssert.IsSuccess(writer.WriteBool("sparse_bool", true)); + ResultAssert.IsSuccess(writer.WriteInt8("sparse_int8", (byte)-86)); + ResultAssert.IsSuccess(writer.WriteInt16("sparse_int16", (short)-21846)); + ResultAssert.IsSuccess(writer.WriteInt32("sparse_int32", -1431655766)); + ResultAssert.IsSuccess(writer.WriteInt64("sparse_int64", -6148914691236517206L)); + ResultAssert.IsSuccess(writer.WriteUInt8("sparse_uint8", (byte)0xAA)); + ResultAssert.IsSuccess(writer.WriteUInt16("sparse_uint16", (short)0xAAAA)); + ResultAssert.IsSuccess(writer.WriteUInt32("sparse_uint32", 0xAAAAAAAA)); + ResultAssert.IsSuccess(writer.WriteUInt64("sparse_uint64", 0xAAAAAAAAAAAAAAAAL)); + ResultAssert.IsSuccess(writer.WriteFloat32("sparse_float32", 1.0F / 3.0F)); + ResultAssert.IsSuccess(writer.WriteFloat64("sparse_float64", 1.0 / 3.0)); + ResultAssert.IsSuccess(writer.WriteFloat128("sparse_float128", RowWriterUnitTests.SampleFloat128)); + ResultAssert.IsSuccess(writer.WriteDecimal("sparse_decimal", java.math.BigDecimal.ONE / 3.0)); + ResultAssert.IsSuccess(writer.WriteDateTime("sparse_datetime", RowWriterUnitTests.SampleDateTime)); + ResultAssert.IsSuccess(writer.WriteUnixDateTime("sparse_unixdatetime", + RowWriterUnitTests.SampleUnixDateTime)); + ResultAssert.IsSuccess(writer.WriteGuid("sparse_guid", RowWriterUnitTests.SampleGuid)); + ResultAssert.IsSuccess(writer.WriteMongoDbObjectId("sparse_mongodbobjectid", + RowWriterUnitTests.SampleMongoDbObjectId)); + ResultAssert.IsSuccess(writer.WriteString("sparse_utf8", "abc")); + ResultAssert.IsSuccess(writer.WriteString("sparse_utf8_span", Utf8Span.TranscodeUtf16("abc"))); + ResultAssert.IsSuccess(writer.WriteBinary("sparse_binary", new byte[] { (byte)0, (byte)1, (byte)2 })); + ResultAssert.IsSuccess(writer.WriteBinary("sparse_binary_span", + new byte[] { (byte)0, (byte)1, (byte)2 }.AsSpan())); + ResultAssert.IsSuccess(writer.WriteBinary("sparse_binary_sequence", + new ReadOnlySequence(new byte[] { (byte)0, (byte)1, (byte)2 }))); + + LayoutColumn col; + Out tempOut_col = + new Out(); + assert layout.TryFind("array_t", tempOut_col); + col = tempOut_col.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new byte[] { -86, -87, + -88 }, (ref RowWriter writer2, TypeArgument typeArg, byte[] values) -> + { + for (byte value : values) { + ResultAssert.IsSuccess(writer2.WriteInt8(null, value)); + } + + return Result.SUCCESS; + })); + + Out tempOut_col2 = + new Out(); + assert layout.TryFind("array_t>", tempOut_col2); + col = tempOut_col2.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new float[][] + { + new float[] { 1, 2, 3 }, + new float[] { 1, 2, 3 } + }, (ref RowWriter writer2, TypeArgument typeArg, float[][] values) -> + { + for (float[] value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(0).clone(), value, + (ref RowWriter writer3, TypeArgument typeArg2, float[] values2) -> + { + for (float value2 : values2) { + ResultAssert.IsSuccess(writer3.WriteFloat32(null, value2)); + } + + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + Out tempOut_col3 = + new Out(); + assert layout.TryFind("array_t", tempOut_col3); + col = tempOut_col3.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new String[] { "abc", + "def", "hij" }, (ref RowWriter writer2, TypeArgument typeArg, String[] values) -> + { + for (String value : values) { + ResultAssert.IsSuccess(writer2.WriteString(null, value)); + } + + return Result.SUCCESS; + })); + + Out tempOut_col4 = + new Out(); + assert layout.TryFind("tuple", tempOut_col4); + col = tempOut_col4.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), + Tuple.Create(-6148914691236517206L, -6148914691236517206L), (ref RowWriter writer2, + TypeArgument typeArg, + Tuple values) -> + { + ResultAssert.IsSuccess(writer2.WriteVarInt(null, values.Item1)); + ResultAssert.IsSuccess(writer2.WriteInt64(null, values.Item2)); + return Result.SUCCESS; + })); + + Out tempOut_col5 = + new Out(); + assert layout.TryFind("tuple>", tempOut_col5); + col = tempOut_col5.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), + Tuple.Create(NullValue.DEFAULT, Tuple.Create((byte)-86, (byte)-86)), (ref RowWriter writer2, + TypeArgument typeArg, + Tuple> values) -> + { + ResultAssert.IsSuccess(writer2.WriteNull(null)); + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(1).clone(), values.Item2, + (ref RowWriter writer3, TypeArgument typeArg2, Tuple values2) -> + { + ResultAssert.IsSuccess(writer3.WriteInt8(null, values2.Item1)); + ResultAssert.IsSuccess(writer3.WriteInt8(null, values2.Item2)); + return Result.SUCCESS; + })); + + return Result.SUCCESS; + })); + + Out tempOut_col6 = + new Out(); + assert layout.TryFind("tuple", tempOut_col6); + col = tempOut_col6.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), Tuple.Create(false, + new RowReaderUnitTests.Point(1, 2)), (ref RowWriter writer2, TypeArgument typeArg, Tuple values) -> + { + ResultAssert.IsSuccess(writer2.WriteBool(null, values.Item1)); + Reference tempReference_writer3 = + new Reference(writer3); + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(1).clone(), values.Item2, + (ref RowWriter writer3, TypeArgument typeArg2, IRowSerializable values2) -> values2.Write(tempReference_writer3, typeArg2.clone()))); + writer3 = tempReference_writer3.get(); + + return Result.SUCCESS; + })); + + Out tempOut_col7 = + new Out(); + assert layout.TryFind("nullable", tempOut_col7); + col = tempOut_col7.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), Tuple.Create(null, + (Long)123L), (ref RowWriter writer2, TypeArgument typeArg, Tuple values) -> + { + RowWriter.WriterFunc f0 = (com.azure.data.cosmos.serialization.hybridrow.io.RowWriter writer, TypeArgument typeArg, + Integer context) -> null.invoke(writer, typeArg.clone(), context); + if (values.Item1 != null) { + f0 = (com.azure.data.cosmos.serialization.hybridrow.io.RowWriter RowWriter writer3, TypeArgument typeArg2, Integer value) -> writer3.WriteInt32(null, + value.intValue()); + } + + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(0).clone(), values.Item1, + f0)); + + RowWriter.WriterFunc f1 = (com.azure.data.cosmos.serialization.hybridrow.io.RowWriter writer, TypeArgument typeArg, + Long context) -> null.invoke(writer, typeArg.clone(), context); + if (values.Item2 != null) { + f1 = (com.azure.data.cosmos.serialization.hybridrow.io.RowWriter RowWriter writer3, TypeArgument typeArg2, Long value) -> writer3.WriteInt64(null, + value.longValue()); + } + + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(1).clone(), values.Item2, + f1)); + return Result.SUCCESS; + })); + + Out tempOut_col8 = + new Out(); + assert layout.TryFind("tagged", tempOut_col8); + col = tempOut_col8.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), Tuple.Create((byte)3, + "hello"), (ref RowWriter writer2, TypeArgument typeArg, Tuple values) -> + { + ResultAssert.IsSuccess(writer2.WriteUInt8(null, values.Item1)); + ResultAssert.IsSuccess(writer2.WriteString(null, values.Item2)); + return Result.SUCCESS; + })); + + Out tempOut_col9 = + new Out(); + assert layout.TryFind("tagged", tempOut_col9); + col = tempOut_col9.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), Tuple.Create((byte)5, + true, "bye"), (ref RowWriter writer2, TypeArgument typeArg, Tuple values) -> + { + ResultAssert.IsSuccess(writer2.WriteUInt8(null, values.Item1)); + ResultAssert.IsSuccess(writer2.WriteBool(null, values.Item2)); + ResultAssert.IsSuccess(writer2.WriteString(null, values.Item3)); + return Result.SUCCESS; + })); + + Out tempOut_col10 = + new Out(); + assert layout.TryFind("set_t", tempOut_col10); + col = tempOut_col10.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new String[] { "abc", + "xzy", "efg" }, (ref RowWriter writer2, TypeArgument typeArg, String[] values) -> + { + for (String value : values) { + ResultAssert.IsSuccess(writer2.WriteString(null, value)); + } + + return Result.SUCCESS; + })); + + Out tempOut_col11 = + new Out(); + assert layout.TryFind("set_t>", tempOut_col11); + col = tempOut_col11.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new byte[][] + { + new byte[] { 7, 8, 9 }, + new byte[] { 4, 5, 6 }, + new byte[] { 1, 2, 3 } + }, (ref RowWriter writer2, TypeArgument typeArg, byte[][] values) -> + { + for (byte[] value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(0).clone(), value, + (ref RowWriter writer3, TypeArgument typeArg2, byte[] values2) -> + { + for (byte value2 : values2) { + ResultAssert.IsSuccess(writer3.WriteInt8(null, value2)); + } + + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + Out tempOut_col12 = + new Out(); + assert layout.TryFind("set_t>", tempOut_col12); + col = tempOut_col12.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new int[][] + { + new int[] { 4, 5, 6 }, + new int[] { 7, 8, 9 }, + new int[] { 1, 2, 3 } + }, (ref RowWriter writer2, TypeArgument typeArg, int[][] values) -> + { + for (int[] value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(0).clone(), value, + (ref RowWriter writer3, TypeArgument typeArg2, int[] values2) -> + { + for (int value2 : values2) { + ResultAssert.IsSuccess(writer3.WriteInt32(null, value2)); + } + + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + Out tempOut_col13 = + new Out(); + assert layout.TryFind("set_t", tempOut_col13); + col = tempOut_col13.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), + new RowReaderUnitTests.Point[] + { + new RowReaderUnitTests.Point(1, 2), + new RowReaderUnitTests.Point(3, 4), + new RowReaderUnitTests.Point(5, 6) + }, (ref RowWriter writer2, TypeArgument typeArg, RowReaderUnitTests.Point[] values) -> + { + for (RowReaderUnitTests.Point value : values) { + Reference tempReference_writer3 = + new Reference(writer3); + ResultAssert.IsSuccess(writer2.WriteScope(null, typeArg.getTypeArgs().get(0).clone(), value, + (ref RowWriter writer3, TypeArgument typeArg2, IRowSerializable values2) -> values2.Write(tempReference_writer3, typeArg2.clone()))); + writer3 = tempReference_writer3.get(); + } + + return Result.SUCCESS; + })); + + Out tempOut_col14 = + new Out(); + assert layout.TryFind("map_t", tempOut_col14); + col = tempOut_col14.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new System.Tuple[] { Tuple.Create("Harrison", "Han"), Tuple.Create("Mark", "Luke") }, (ref RowWriter writer2, + TypeArgument typeArg, + Tuple[] values) -> + { + for (Tuple value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, new TypeArgument(LayoutType.TypedTuple, + typeArg.getTypeArgs().clone()), value, (ref RowWriter writer3, TypeArgument typeArg2, + Tuple values2) -> + { + ResultAssert.IsSuccess(writer3.WriteString(null, values2.Item1)); + ResultAssert.IsSuccess(writer3.WriteString(null, values2.Item2)); + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + Out tempOut_col15 = + new Out(); + assert layout.TryFind("map_t>", tempOut_col15); + col = tempOut_col15.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new System.Tuple[] { Tuple.Create((byte)2, new byte[] { 4, 5, 6 }), + Tuple.Create((byte)1, new byte[] { 1, 2, 3 }) }, (ref RowWriter writer2, TypeArgument typeArg, + Tuple[] values) -> + { + for (Tuple value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, new TypeArgument(LayoutType.TypedTuple, + typeArg.getTypeArgs().clone()), value, (ref RowWriter writer3, TypeArgument typeArg2, + Tuple values2) -> + { + ResultAssert.IsSuccess(writer3.WriteInt8(null, values2.Item1)); + ResultAssert.IsSuccess(writer3.WriteScope(null, typeArg2.getTypeArgs().get(1).clone(), + values2.Item2, (ref RowWriter writer4, TypeArgument typeArg3, byte[] values3) -> + { + for (byte value3 : values3) { + ResultAssert.IsSuccess(writer4.WriteInt8(null, value3)); + } + + return Result.SUCCESS; + })); + + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + Out tempOut_col16 = + new Out(); + assert layout.TryFind("map_t>", tempOut_col16); + col = tempOut_col16.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new System.Tuple[] { Tuple.Create((short)2, new System.Tuple[] { Tuple.Create(7, 8), Tuple.Create(5, 6) }) + , Tuple.Create((short)1, new System.Tuple[] { Tuple.Create(3, 4), Tuple.Create(1, 2) }) }, + (ref RowWriter writer2, TypeArgument typeArg, Tuple[]>[] values) -> + { + for (Tuple[]> value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, new TypeArgument(LayoutType.TypedTuple, + typeArg.getTypeArgs().clone()), value, (ref RowWriter writer3, TypeArgument typeArg2, + Tuple[]> values2) -> + { + ResultAssert.IsSuccess(writer3.WriteInt16(null, values2.Item1)); + ResultAssert.IsSuccess(writer3.WriteScope(null, typeArg2.getTypeArgs().get(1).clone(), + values2.Item2, (ref RowWriter writer4, TypeArgument typeArg3, + Tuple[] values3) -> + { + for (Tuple value3 : values3) { + ResultAssert.IsSuccess(writer4.WriteScope(null, + new TypeArgument(LayoutType.TypedTuple, typeArg3.getTypeArgs().clone()), value3, + (ref RowWriter writer5, TypeArgument typeArg4, Tuple values4) -> + { + ResultAssert.IsSuccess(writer5.WriteInt32(null, values4.Item1)); + ResultAssert.IsSuccess(writer5.WriteInt32(null, values4.Item2)); + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + Out tempOut_col17 = + new Out(); + assert layout.TryFind("map_t", tempOut_col17); + col = tempOut_col17.get(); + ResultAssert.IsSuccess(writer.WriteScope(col.path(), col.typeArg().clone(), new System.Tuple[] { Tuple.Create(1.0, new RowReaderUnitTests.Point(1, 2)), Tuple.Create(2.0, new RowReaderUnitTests.Point(3, 4)), Tuple.Create(3.0, new RowReaderUnitTests.Point(5, 6)) }, (ref RowWriter writer2, TypeArgument typeArg, Tuple[] values) -> + { + for (Tuple value : values) { + ResultAssert.IsSuccess(writer2.WriteScope(null, new TypeArgument(LayoutType.TypedTuple, typeArg.getTypeArgs().clone()), value, (ref RowWriter writer3, TypeArgument typeArg2, Tuple values2) -> + { + ResultAssert.IsSuccess(writer3.WriteFloat64(null, values2.Item1)); + Reference tempReference_writer4 = new Reference(writer4); + ResultAssert.IsSuccess(writer3.WriteScope(null, typeArg2.getTypeArgs().get(1).clone(), values2.Item2, (ref RowWriter writer4, TypeArgument typeArg3, IRowSerializable values3) -> values3.Write(tempReference_writer4, typeArg3.clone()))); + writer4 = tempReference_writer4.get(); + + return Result.SUCCESS; + })); + } + + return Result.SUCCESS; + })); + + // Save the RowWriter length after everything is written for later comparison. + writerLength = writer.Length; + return Result.SUCCESS; + })); + row = tempReference_row.get(); + + Reference tempReference_row2 = new Reference(row); + RowReader reader = new RowReader(tempReference_row2); + row = tempReference_row2.get(); + assert reader.length() == writerLength; + Reference tempReference_reader = new Reference(reader); + RowReaderUnitTests.PrintReader(tempReference_reader, 0); + reader = tempReference_reader.get(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaHashUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaHashUnitTests.java new file mode 100644 index 0000000..38719d0 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaHashUnitTests.java @@ -0,0 +1,272 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import Newtonsoft.Json.*; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.PropertyType; + +import java.nio.file.Files; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(SchemaHashUnitTests.SchemaFile, "TestData")] public class +// SchemaHashUnitTests +public class SchemaHashUnitTests { + private static final String SchemaFile = "TestData\\SchemaHashCoverageSchema.json"; + private Namespace ns; + private Schema tableSchema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void InitializeSuite() + public final void InitializeSuite() { + String json = Files.readString(SchemaHashUnitTests.SchemaFile); + this.ns = Namespace.Parse(json); + this.tableSchema = tangible.ListHelper.find(this.ns.getSchemas(), s -> s.Name.equals("Table")); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void SchemaHashCompileTest() + public final void SchemaHashCompileTest() { + Layout layout = this.tableSchema.Compile(this.ns); + assert layout != null; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void SchemaHashTest() + public final void SchemaHashTest() { + // TODO: C# TO JAVA CONVERTER: Tuple variables are not converted by C# to Java Converter: + ( long low, long high)hash = SchemaHash.ComputeHash(this.ns, this.tableSchema); + assert (0,0) !=hash; + // TODO: C# TO JAVA CONVERTER: Tuple variables are not converted by C# to Java Converter: + ( long low, long high)hash2 = SchemaHash.ComputeHash(this.ns, this.tableSchema, (1, 1)) + assert hash != hash2; + + // Test clone are the same. + Schema clone = SchemaHashUnitTests.Clone(this.tableSchema); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash == hash2; + + // Test Schema changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.setName("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash == hash2; // Name not part of the hash + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.setComment("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash == hash2; // Comment not part of the hash + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.setVersion(SchemaLanguageVersion.forValue((byte)1)); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash == hash2; // Encoding version not part of the hash + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.setSchemaId(new SchemaId(42)); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.setType(TypeKind.Int8); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Options changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getOptions().setEnablePropertyLevelTimestamp(!clone.getOptions().getEnablePropertyLevelTimestamp()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getOptions().setDisallowUnschematized(!clone.getOptions().getDisallowUnschematized()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Partition Keys changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getPartitionKeys().get(0).setPath("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Primary Sort Keys changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getPrimarySortKeys().get(0).setPath("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getPrimarySortKeys().get(0).setDirection(SortDirection.Descending); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Static Keys changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getStaticKeys().get(0).setPath("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Properties changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getProperties().get(0).setComment("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash == hash2; // Comment not part of the hash + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getProperties().get(0).setPath("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getProperties().get(0).getPropertyType().setApiType("something else"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getProperties().get(0).getPropertyType().setType(TypeKind.Binary); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + clone.getProperties().get(0).getPropertyType().setNullable(!clone.getProperties().get(0).getPropertyType().getNullable()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Primitive Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar = + clone.getProperties().get(0).getPropertyType(); + (tempVar instanceof PrimitivePropertyType ? (PrimitivePropertyType)tempVar : null).setLength(42); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar2 = + clone.getProperties().get(0).getPropertyType(); + (tempVar2 instanceof PrimitivePropertyType ? (PrimitivePropertyType)tempVar2 : null).setStorage(StorageKind.Variable); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Scope Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar3 = + clone.getProperties().get(1).getPropertyType(); + PropertyType tempVar4 = + clone.getProperties().get(1).getPropertyType(); + (tempVar3 instanceof ScopePropertyType ? (ScopePropertyType)tempVar3 : null).setImmutable(!(tempVar4 instanceof ScopePropertyType ? (ScopePropertyType)tempVar4 : null).getImmutable()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Array Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar5 = + clone.getProperties().get(1).getPropertyType(); + (tempVar5 instanceof ArrayPropertyType ? (ArrayPropertyType)tempVar5 : null).setItems(clone.getProperties().get(0).getPropertyType()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Object Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar6 = + clone.getProperties().get(2).getPropertyType(); + (tempVar6 instanceof ObjectPropertyType ? (ObjectPropertyType)tempVar6 : null).getProperties().set(0, + clone.getProperties().get(0)); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Map Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar7 = + clone.getProperties().get(3).getPropertyType(); + (tempVar7 instanceof MapPropertyType ? (MapPropertyType)tempVar7 : null).setKeys(clone.getProperties().get(0).getPropertyType()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar8 = + clone.getProperties().get(3).getPropertyType(); + (tempVar8 instanceof MapPropertyType ? (MapPropertyType)tempVar8 : null).setValues(clone.getProperties().get(0).getPropertyType()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Set Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar9 = + clone.getProperties().get(4).getPropertyType(); + (tempVar9 instanceof SetPropertyType ? (SetPropertyType)tempVar9 : null).setItems(clone.getProperties().get(0).getPropertyType()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Tagged Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar10 = + clone.getProperties().get(5).getPropertyType(); + (tempVar10 instanceof TaggedPropertyType ? (TaggedPropertyType)tempVar10 : null).getItems().set(0, + clone.getProperties().get(0).getPropertyType()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test Tuple Property Type changes + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar11 = + clone.getProperties().get(6).getPropertyType(); + (tempVar11 instanceof TuplePropertyType ? (TuplePropertyType)tempVar11 : null).getItems().set(0, + clone.getProperties().get(0).getPropertyType()); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Test UDT Property Type changes + try { + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar12 = + clone.getProperties().get(7).getPropertyType(); + (tempVar12 instanceof UdtPropertyType ? (UdtPropertyType)tempVar12 : null).setName("some non-existing UDT" + + " name"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + Assert.Fail("Should have thrown an exception."); + } catch (RuntimeException ex) { + assert ex != null; + } + + try { + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar13 = + clone.getProperties().get(7).getPropertyType(); + (tempVar13 instanceof UdtPropertyType ? (UdtPropertyType)tempVar13 : null).setName("Table"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + Assert.Fail("Should have thrown an exception."); + } catch (RuntimeException ex) { + assert ex != null; + } + + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar14 = + clone.getProperties().get(7).getPropertyType(); + (tempVar14 instanceof UdtPropertyType ? (UdtPropertyType)tempVar14 : null).setName("Table"); + PropertyType tempVar15 = + clone.getProperties().get(7).getPropertyType(); + (tempVar15 instanceof UdtPropertyType ? (UdtPropertyType)tempVar15 : null).setSchemaId(new SchemaId(2)); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash != hash2; + + // Renaming an UDT is not a breaking change as long as the SchemaId has not changed. + this.ns.getSchemas().get(0).setName("RenameActualUDT"); + clone = SchemaHashUnitTests.Clone(this.tableSchema); + PropertyType tempVar16 = clone.getProperties().get(7).getPropertyType(); + (tempVar16 instanceof UdtPropertyType ? (UdtPropertyType)tempVar16 : null).setName("RenameActualUDT"); + hash2 = SchemaHash.ComputeHash(this.ns, clone); + assert hash == hash2; + } + + private static Schema Clone(Schema s) { + JsonSerializerSettings settings = new JsonSerializerSettings(); + settings.NullValueHandling = NullValueHandling.Ignore; + settings.Formatting = Formatting.Indented; + settings.CheckAdditionalContent = true; + + String json = JsonConvert.SerializeObject(s, settings); + return JsonConvert.DeserializeObject(json, settings); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaIdUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaIdUnitTests.java new file mode 100644 index 0000000..98485ef --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaIdUnitTests.java @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import Newtonsoft.Json.*; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public class SchemaIdUnitTests +public class SchemaIdUnitTests { + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void SchemaIdTest() + public final void SchemaIdTest() { + SchemaId a = new SchemaId(1); + SchemaId b = new SchemaId(2); + SchemaId c = new SchemaId(); + + assert 1 == a.value(); + assert 2 == b.value(); + assert SchemaId.INVALID == c.clone(); + assert 2 != a.value(); + assert a.clone() != b.clone(); + assert SchemaId.opEquals(a.clone(), a.clone()); + assert SchemaId.opNotEquals(a.clone(), b.clone()); + assert !a.equals(null); + assert a.hashCode() == (new SchemaId(1)).hashCode(); + assert a.hashCode() != (new SchemaId(-1)).hashCode(); + + String json = JsonConvert.SerializeObject(a.clone()); + assert "1" == json; + assert "1" == a.toString(); + + assert a.clone() == JsonConvert.DeserializeObject(json); + json = JsonConvert.SerializeObject(b.clone()); + assert "2" == json; + assert "2" == b.toString(); + assert b.clone() == JsonConvert.DeserializeObject(json); + json = JsonConvert.SerializeObject(c.clone()); + assert "0" == json; + assert "0" == c.toString(); + assert c.clone() == JsonConvert.DeserializeObject(json); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaUnitTests.java new file mode 100644 index 0000000..8867a64 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SchemaUnitTests.java @@ -0,0 +1,994 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import Newtonsoft.Json.*; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.SortDirection; +import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind; +import com.azure.data.cosmos.serialization.hybridrow.schemas.TypeKind; + +import java.nio.file.Files; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("Naming", "DontUseVarForVariableTypes", Justification = "The types here +// are anonymous.")] public class SchemaUnitTests +public class SchemaUnitTests { + PrimitivePropertyType sp = (PrimitivePropertyType)p.getPropertyType(); + String tableSchema = String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s]}", + columnSchema); + Schema s = Schema.Parse(tableSchema);) + Property p = s.getProperties().get(0); + + { + case Utf8: + case Binary: + switch (sp.getStorage()) { + case Fixed: + case Variable: + case Sparse: + Assert.AreEqual(expected.Len, sp.getLength(), "Json: {0}", expected.Json); + break; + default: + Assert.Fail("Json: {0}", expected.Json); + break; + } + + break; + } + Assert.AreEqual(1,s.getProperties(). + + getType(), "Json: {0}",expected.Json) + + getType() + Assert.AreEqual(expected.Type,p.getPropertyType(). + + size(), "Json: {0}",expected.Json) + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseNamespace() + public final void ParseNamespace() { + { + // Test empty schemas. + String[] emptyNamespaceJsonInput = { "{ }", "{'schemas': [ ] }", "{'name': null }", "{'name': null, " + + "'schemas': null }", "{'version': 'v1', 'name': null, 'schemas': null }" }; + + for (String json : emptyNamespaceJsonInput) { + Namespace n1 = Namespace.Parse(json); + Assert.IsNull(n1.getName(), "Got: {0}, Json: {1}", n1.getName(), json); + Assert.IsNotNull(n1.getSchemas(), "Json: {0}", json); + Assert.AreEqual(0, n1.getSchemas().size(), "Got: {0}, Json: {1}", n1.getSchemas(), json); + assert SchemaLanguageVersion.V1 == n1.getVersion(); + } + } + + { + // Test simple schemas and schema options. + String json = "{'name': 'myschema', 'schemas': null }"; + Namespace n1 = Namespace.Parse(json); + Assert.AreEqual("myschema", n1.getName(), "Json: {0}", json); + Assert.IsNotNull(n1.getSchemas(), "Json: {0}", json); + + // Version defaults propertly when NOT specified. + assert SchemaLanguageVersion.V1 == n1.getVersion(); + } + + { + String json = "{'name': 'myschema', 'schemas': [" + "\r\n" + + " {'version': 'v1', 'name': 'emptyTable', 'id': -1, 'type': 'schema', " + "\r\n" + + " 'options': { 'disallowUnschematized': true }, 'properties': null } ] }"; + + Namespace n1 = Namespace.Parse(json); + Assert.AreEqual("myschema", n1.getName(), "Json: {0}", json); + Assert.AreEqual(1, n1.getSchemas().size(), "Json: {0}", json); + Assert.AreEqual("emptyTable", n1.getSchemas().get(0).getName(), "Json: {0}", json); + Assert.AreEqual(new SchemaId(-1), n1.getSchemas().get(0).getSchemaId().clone(), "Json: {0}", json); + Assert.AreEqual(TypeKind.SCHEMA, n1.getSchemas().get(0).getType(), "Json: {0}", json); + Assert.AreEqual(true, n1.getSchemas().get(0).getOptions().getDisallowUnschematized(), "Json: {0}", json); + Assert.IsNotNull(n1.getSchemas().get(0).getProperties().size(), "Json: {0}", json); + Assert.AreEqual(0, n1.getSchemas().get(0).getProperties().size(), "Json: {0}", json); + assert SchemaLanguageVersion.V1 == n1.getVersion(); + } + + { + // Test basic schema with primitive columns. + String json = "{'name': 'myschema', 'schemas': [" + "\r\n" + + " {'name': 'myUDT', 'id': 1, 'type': 'schema', 'options': { " + + "'disallowUnschematized': false }, " + "\r\n" + + " 'properties': [ " + "\r\n" + + " { 'path': 'a', 'type': { 'type': 'int8', 'storage': 'fixed' }}, " + "\r\n" + + " { 'path': 'b', 'type': { 'type': 'utf8', 'storage': 'variable' }} " + "\r\n" + + " ] }" + "\r\n" + + " ] }"; + + Namespace n1 = Namespace.Parse(json); + Assert.AreEqual(1, n1.getSchemas().size(), "Json: {0}", json); + Assert.AreEqual("myUDT", n1.getSchemas().get(0).getName(), "Json: {0}", json); + Assert.AreEqual(new SchemaId(1), n1.getSchemas().get(0).getSchemaId().clone(), "Json: {0}", json); + Assert.AreEqual(TypeKind.SCHEMA, n1.getSchemas().get(0).getType(), "Json: {0}", json); + Assert.AreEqual(false, n1.getSchemas().get(0).getOptions().getDisallowUnschematized(), "Json: {0}", json); + Assert.AreEqual(2, n1.getSchemas().get(0).getProperties().size(), "Json: {0}", json); + + class AnonymousType { + public String Path; + public StorageKind Storage; + public TypeKind Type; + + public AnonymousType(String _Path, + TypeKind _Type, + StorageKind _Storage) { + Path = _Path; + Type = _Type; + Storage = _Storage; + } + } + class AnonymousType2 { + public String Path; + public StorageKind Storage; + public TypeKind Type; + + public AnonymousType2(String _Path, + TypeKind _Type, + StorageKind _Storage) { + Path = _Path; + Type = _Type; + Storage = _Storage; + } + } + Object[] expectedProps = new Object[] { AnonymousType("a", TypeKind.INT_8, StorageKind.FIXED), + AnonymousType2("b", TypeKind.UTF_8, StorageKind.VARIABLE) }; + + for (int i = 0; i < n1.getSchemas().get(0).getProperties().size(); i++) { + Property p = n1.getSchemas().get(0).getProperties().get(i); + Assert.AreEqual(expectedProps[i].Path, p.getPath(), "Json: {0}", json); + Assert.AreEqual(expectedProps[i].Type, p.getPropertyType().getType(), "Json: {0}", json); + PrimitivePropertyType sp = (PrimitivePropertyType)p.getPropertyType(); + Assert.AreEqual(expectedProps[i].Storage, sp.getStorage(), "Json: {0}", json); + } + } + } + switch(p.getPropertyType(). + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")][DeploymentItem("TestData\\CoverageSchema.json", "TestData")] + // public void ParseNamespaceExample() + public final void ParseNamespaceExample() { + String json = Files.readString("TestData\\CoverageSchema.json"); + Namespace n1 = Namespace.Parse(json); + JsonSerializerSettings settings = new JsonSerializerSettings(); + settings.NullValueHandling = NullValueHandling.Ignore; + settings.Formatting = Formatting.Indented; + + String json2 = JsonConvert.SerializeObject(n1, settings); + Namespace n2 = Namespace.Parse(json2); + String json3 = JsonConvert.SerializeObject(n2, settings); + assert json2 == json3; + }) + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaPrimitives() + public final void ParseSchemaPrimitives() { + // Test all primitive column types. + class AnonymousType { + public String Json; + public TypeKind Type; + + public AnonymousType(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType10 { + public String Json; + public TypeKind Type; + + public AnonymousType10(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType11 { + public String Json; + public TypeKind Type; + + public AnonymousType11(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType12 { + public String Json; + public TypeKind Type; + + public AnonymousType12(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType13 { + public String Json; + public TypeKind Type; + + public AnonymousType13(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType14 { + public String Json; + public TypeKind Type; + + public AnonymousType14(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType15 { + public String Json; + public TypeKind Type; + + public AnonymousType15(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType16 { + public String Json; + public TypeKind Type; + + public AnonymousType16(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType17 { + public String Json; + public TypeKind Type; + + public AnonymousType17(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType18 { + public String Json; + public TypeKind Type; + + public AnonymousType18(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType19 { + public String Json; + public TypeKind Type; + + public AnonymousType19(String _Json, + TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType2 { + public String Json; + public TypeKind Type; + + public AnonymousType2(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType20 { + public String Json; + public int Len; + public TypeKind Type; + + public AnonymousType20(String _Json, + TypeKind _Type, int _Len) { + Json = _Json; + Type = _Type; + Len = _Len; + } + } + + class AnonymousType21 { + public String Json; + public int Len; + public TypeKind Type; + + public AnonymousType21(String _Json, + TypeKind _Type, int _Len) { + Json = _Json; + Type = _Type; + Len = _Len; + } + } + + class AnonymousType22 { + public String Json; + public int Len; + public TypeKind Type; + + public AnonymousType22(String _Json, + TypeKind _Type, int _Len) { + Json = _Json; + Type = _Type; + Len = _Len; + } + } + + class AnonymousType23 { + public String Json; + public int Len; + public TypeKind Type; + + public AnonymousType23(String _Json, + TypeKind _Type, int _Len) { + Json = _Json; + Type = _Type; + Len = _Len; + } + } + + class AnonymousType24 { + public String Json; + public int Len; + public TypeKind Type; + + public AnonymousType24(String _Json, + TypeKind _Type, int _Len) { + Json = _Json; + Type = _Type; + Len = _Len; + } + } + + class AnonymousType25 { + public String Json; + public int Len; + public TypeKind Type; + + public AnonymousType25(String _Json, + TypeKind _Type, int _Len) { + Json = _Json; + Type = _Type; + Len = _Len; + } + } + + class AnonymousType3 { + public String Json; + public TypeKind Type; + + public AnonymousType3(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType4 { + public String Json; + public TypeKind Type; + + public AnonymousType4(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType5 { + public String Json; + public TypeKind Type; + + public AnonymousType5(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType6 { + public String Json; + public TypeKind Type; + + public AnonymousType6(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType7 { + public String Json; + public TypeKind Type; + + public AnonymousType7(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType8 { + public String Json; + public TypeKind Type; + + public AnonymousType8(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + + class AnonymousType9 { + public String Json; + public TypeKind Type; + + public AnonymousType9(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } + } + // TODO: C# TO JAVA CONVERTER: There is no Java equivalent to the C# 'dynamic' keyword: + dynamic[] expectedSchemas = { AnonymousType("{'type': 'bool', 'storage': 'fixed'}", TypeKind.BOOLEAN), + AnonymousType2("{'type': 'int8', 'storage': 'fixed'}", TypeKind.INT_8), AnonymousType3("{'type': 'int16', " + + "'storage': 'fixed'}", TypeKind.INT_16), AnonymousType4("{'type': 'int32', 'storage': 'fixed'}", + TypeKind.INT_32), AnonymousType5("{'type': 'int64', 'storage': 'fixed'}", TypeKind.INT_64), AnonymousType6( + "{'type': 'uint8', 'storage': 'fixed'}", TypeKind.UINT_8), AnonymousType7("{'type': 'uint16', " + + "'storage': 'fixed'}", TypeKind.UINT_16), AnonymousType8("{'type': 'uint32', 'storage': 'fixed'}", + TypeKind.UINT_32), AnonymousType9("{'type': 'uint64', 'storage': 'fixed'}", TypeKind.UINT_64), + AnonymousType10("{'type': 'float32', 'storage': 'fixed'}", TypeKind.FLOAT_32), AnonymousType11("{'type': " + + "'float64', 'storage': 'fixed'}", TypeKind.FLOAT_64), AnonymousType12("{'type': 'float128', 'storage': " + + "'fixed'}", TypeKind.FLOAT_128), AnonymousType13("{'type': 'decimal', 'storage': 'fixed'}", + TypeKind.DECIMAL), AnonymousType14("{'type': 'datetime', 'storage': 'fixed'}", TypeKind.DATE_TIME), + AnonymousType15("{'type': 'unixdatetime', 'storage': 'fixed'}", TypeKind.UNIX_DATE_TIME), AnonymousType16( + "{'type': 'guid', 'storage': 'fixed'}", TypeKind.GUID), AnonymousType17("{'type': 'mongodbobjectid', " + + "'storage': 'fixed'}", TypeKind.MONGODB_OBJECT_ID), AnonymousType18("{'type': 'varint', 'storage': " + + "'variable'}", TypeKind.VAR_INT), AnonymousType19("{'type': 'varuint', 'storage': 'variable'}", + TypeKind.VAR_UINT), AnonymousType20("{'type': 'utf8', 'storage': 'fixed', 'length': 2}", TypeKind.UTF_8, 2) + , AnonymousType21("{'type': 'binary', 'storage': 'fixed', 'length': 2}", TypeKind.BINARY, 2), + AnonymousType22("{'type': 'utf8', 'storage': 'variable', 'length': 100}", TypeKind.UTF_8, 100), + AnonymousType23("{'type': 'binary', 'storage': 'variable', 'length': 100}", TypeKind.BINARY, 100), + AnonymousType24("{'type': 'utf8', 'sparse': 'variable', 'length': 1000}", TypeKind.UTF_8, 1000), + AnonymousType25("{'type': 'binary', 'sparse': 'variable', 'length': 1000}", TypeKind.BINARY, 1000) }; + + for (dynamic expected : expectedSchemas) { + String columnSchema = String.format("{'path': 'a', 'type': %1$s", expected.Json + } + } +} + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaArray() +public final void ParseSchemaArray() + { + +// Test array types include nested arrays. +class AnonymousType { + public String Json; + public TypeKind Type; + + public AnonymousType(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } +} + +class AnonymousType2 { + public String Json; + public TypeKind Type; + + public AnonymousType2(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } +} + +class AnonymousType3 { + public String Json; + public int Len; + + public AnonymousType3(String _Json, int _Len) { + Json = _Json; + Len = _Len; + } +} + +class AnonymousType4 { + public String Json; + public String Name; +// TODO: C# TO JAVA CONVERTER: There is no Java equivalent to the C# 'dynamic' keyword: + dynamic[] expectedSchemas = { AnonymousType("{'type': 'int8' }", TypeKind.INT_8), AnonymousType2("{'type': " + + "'array', 'items': {'type': 'int32'}}", TypeKind.INT_32), AnonymousType3("{'type': 'object', 'properties': " + + "null}", 0), AnonymousType4("{'type': 'schema', 'name': 'myUDT'}", "myUDT") }; + + public AnonymousType4(String _Json, String _Name) { + Json = _Json; + Name = _Name; + } +} + for(dynamic expected:expectedSchemas) + { + String arrayColumnSchema=String.format("{'path': 'a', 'type': {'type': 'array', 'items': %1$s } }", + expected.Json); + String tableSchema=String.format("{'name': 'table', 'id': -1, 'type': 'schema', 'properties': [%1$s] }", + arrayColumnSchema); + Schema s=Schema.Parse(tableSchema); + Assert.AreEqual(1,s.getProperties().size(),"Json: {0}",expected.Json); + Property p=s.getProperties().get(0); + Assert.AreEqual(TypeKind.Array,p.getPropertyType().getType(),"Json: {0}",expected.Json); + ArrayPropertyType pt=(ArrayPropertyType)p.getPropertyType(); + Assert.IsNotNull(pt.getItems(),"Json: {0}",expected.Json); + switch(pt.getItems().getType()) + { + case Array: + ArrayPropertyType subArray=(ArrayPropertyType)pt.getItems(); + Assert.AreEqual(expected.Type,subArray.getItems().getType(),"Json: {0}",expected.Json); + break; + case Object: + ObjectPropertyType subObj=(ObjectPropertyType)pt.getItems(); + Assert.AreEqual(expected.Len,subObj.getProperties().size(),"Json: {0}",expected.Json); + break; + case Schema: + UdtPropertyType subRow=(UdtPropertyType)pt.getItems(); + Assert.AreEqual(expected.Name,subRow.getName(),"Json: {0}",expected.Json); + break; +default: + Assert.AreEqual(expected.Type,pt.getItems().getType(),"Json: {0}",expected.Json); + break; + } + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaObject() +public final void ParseSchemaObject() + { + +// Test object types include nested objects. +class AnonymousType { + public String Json; + public TypeKind Type; + + public AnonymousType(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } +} + +class AnonymousType2 { + public String Json; + public TypeKind Type; + + public AnonymousType2(String _Json, TypeKind _Type) { + Json = _Json; + Type = _Type; + } +} + +class AnonymousType3 { + public String Json; + public int Len; + + public AnonymousType3(String _Json, int _Len) { + Json = _Json; + Len = _Len; + } +} + +class AnonymousType4 { + public String Json; + public String Name; + + publ TO JAVA CONVERTER TODO TASK: There is no Java equivalent to the C# 'dynamic' keyword: + dynamic[] expectedSchemas = { AnonymousType("{'path': 'b', 'type': {'type': 'int8', 'storage': 'fixed'}}", + TypeKind.INT_8), AnonymousType2("{'path': 'b', 'type': {'type': 'array', 'items': {'type': 'int32'}}}", + TypeKind.INT_32), AnonymousType3("{'path': 'b', 'type': {'type': 'object', 'properties': [{'path': 'c', " + + "'type': {'type': 'bool'}}]}}", 1), AnonymousType4("{'path': 'b', 'type': {'type': 'schema', 'name': " + + "'myUDT'}}", "myUDT") }; + + for(/C#ic AnonymousType4(String _Json, String _Name) { + Json = _Json; + Name = _Name; + } +} + /dynamic expected:expectedSchemas) + { + String objectColumnSchema=String.format("{'path': 'a', 'type': {'type': 'object', 'properties': [%1$s] } " + + "}",expected.Json); + String tableSchema=String.format("{'name': 'table', 'id': -2, 'type': 'schema', 'properties': [%1$s] }", + objectColumnSchema); + try + { + Schema s=Schema.Parse(tableSchema); + Assert.AreEqual(1,s.getProperties().size(),"Json: {0}",expected.Json); + Property pa=s.getProperties().get(0); + Assert.AreEqual(TypeKind.Object,pa.getPropertyType().getType(),"Json: {0}",expected.Json); + ObjectPropertyType pt=(ObjectPropertyType)pa.getPropertyType(); + Assert.AreEqual(1,pt.getProperties().size(),"Json: {0}",expected.Json); + Property pb=pt.getProperties().get(0); + switch(pb.getPropertyType().getType()) + { + case Array: + ArrayPropertyType subArray=(ArrayPropertyType)pb.getPropertyType(); + Assert.AreEqual(expected.Type,subArray.getItems().getType(),"Json: {0}",expected.Json); + break; + case Object: + ObjectPropertyType subObj=(ObjectPropertyType)pb.getPropertyType(); + Assert.AreEqual(expected.Len,subObj.getProperties().size(),"Json: {0}",expected.Json); + break; + case Schema: + UdtPropertyType subRow=(UdtPropertyType)pb.getPropertyType(); + Assert.AreEqual(expected.Name,subRow.getName(),"Json: {0}",expected.Json); + break; +default: + Assert.AreEqual(expected.Type,pb.getPropertyType().getType(),"Json: {0}",expected.Json); + break; + } + } + catch(RuntimeException ex) + { + Assert.Fail("Exception: {0}, Json: {1}",ex,expected.Json); + } + } + } + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void ParseSchemaPartitionPrimaryKeys() +public final void ParseSchemaPartitionPrimaryKeys() + { + +// Test parsing both partition and primary sort keys. +class AnonymousType { + public Object[] CK; + + pulic String JsonCK + public String JsonPK; + public String[] PK; + pubblic AnonymousType(String _JsonPK, String _JsonCK, String[] _PK, Object[] _CK) { + JsonPK = _JsonPK; + JsonCK = _JsonCK; + PK = _PK; + CK = _CK; + } +} + +class AnonymousType2 { + public SortDirection Dir; + + pulic String Path + + pubblic AnonymousType2(String _Path, SortDirection _Dir) { + Path = _Path; + Dir = _Dir; + } +} + +class AnonymousType3 { + public SortDirection Dir; + + pulic String Path + pubblct[] expectedSchemas = new Object[] { AnonymousType("{'path': 'a'}", "{'path': 'b', 'direction': 'desc'}, " + + "{'path': 'c'}", new String[] { "a" }, new Object[] { AnonymousType2("b", SortDirection.DESCENDING), + AnonymousType3("c", SortDirection.ASCENDING) }) }; + + for(bjeic AnonymousType3(String _Path, SortDirection _Dir) { + Path = _Path; + Dir = _Dir; + } +} + OObject expected:expectedSchemas) + { + String tableSchema=String.format("{{"+"\r\n"+ + " 'name': 'table', "+"\r\n"+ + " 'id': -3,"+"\r\n"+ + " 'type': 'schema', "+"\r\n"+ + " 'properties': ["+"\r\n"+ + " {{'path': 'a', 'type': {{'type': 'int8', 'storage': 'fixed'}}}},")+"\r\n"+ + " {{'path': 'b', 'type': {{'type': 'utf8', 'storage': 'variable', 'length': 2}}}}," + +"\r\n"+ + " {{'path': 'c', 'type': {{'type': 'datetime', 'storage': 'fixed'}}}},"+"\r\n"+ + " ],"+"\r\n"+ + " 'partitionkeys': [{expected.JsonPK}],"+"\r\n"+ + " 'primarykeys': [{expected.JsonCK}]"+"\r\n"+ + " }}"; + + try + { + Schema s=Schema.Parse(tableSchema); + Assert.AreEqual(3,s.getProperties().size(),"PK: {0}, CK: {1}",expected.JsonPK,expected.JsonCK); + for(int i=0;iThrowsException(()->Namespace.Parse(t.getJson())); + } + } + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ from the original: +//ORIGINAL LINE: private struct NamespaceParserTest +private final static class NamespaceParserTest { + private String Name; + + publblivate String Json + + publ +ic String getName() { + return Name; + } + + puic String getJson() { + return Json; + } + + publ +ic void setName(String value) { + Name = value; + } + + pric void setJson(String value) { + Json = value; + } +} +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SerializerUnitTest.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SerializerUnitTest.java new file mode 100644 index 0000000..1bb34e9 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/SerializerUnitTest.java @@ -0,0 +1,317 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReaderExtensions; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1201 // Elements should appear in the correct order +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1204 // Elements should appear in the correct order +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable CA1034 // Nested types should not be visible +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable CA1051 // Do not declare visible instance fields + + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(SerializerUnitTest.SchemaFile, "TestData")] public sealed class +// SerializerUnitTest +public final class SerializerUnitTest { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final String SchemaFile = "TestData\\BatchApiSchema.json"; + private Layout layout; + private LayoutResolver resolver; + private Namespace schema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateBatchRequest() + public void CreateBatchRequest() { + BatchRequest request = new BatchRequest(); + BatchOperation tempVar = new BatchOperation(); + tempVar.OperationType = 3; + tempVar.Headers = new BatchRequestHeaders(); + tempVar.Headers.SampleRequestHeader = 12345L; + tempVar.ResourceType = 1; + tempVar.ResourcePath = "/some/url/path"; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar.ResourceBody = new byte[] { 1, 2, 3 }; + tempVar.ResourceBody = new byte[] { 1, 2, 3 }; + BatchOperation tempVar2 = new BatchOperation(); + tempVar2.OperationType = 2; + tempVar2.Headers = new BatchRequestHeaders(); + tempVar2.Headers.SampleRequestHeader = 98746L; + tempVar2.ResourceType = 2; + tempVar2.ResourcePath = "/some/other/url/path"; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: tempVar2.ResourceBody = new byte[] { 3, 2, 1 }; + tempVar2.ResourceBody = new byte[] { 3, 2, 1 }; + request.Operations = new ArrayList(Arrays.asList(tempVar, tempVar2)); + + // Write the request by serializing it to a row. + RowBuffer row = new RowBuffer(SerializerUnitTest.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + Result r = RowWriter.WriteBuffer(tempReference_row, request, BatchRequestSerializer.Write); + row = tempReference_row.get(); + assert Result.SUCCESS == r; + System.out.printf("Length of serialized row: %1$s" + "\r\n", row.length()); + + // Read the row back again. + Reference tempReference_row2 = + new Reference(row); + RowReader reader = new RowReader(tempReference_row2); + row = tempReference_row2.get(); + Reference tempReference_reader = + new Reference(reader); + BatchRequest _; + Out tempOut__ = new Out(); + r = BatchRequestSerializer.Read(tempReference_reader, tempOut__); + _ = tempOut__.get(); + reader = tempReference_reader.get(); + assert Result.SUCCESS == r; + + // Dump the materialized request to the console. + Reference tempReference_row3 = + new Reference(row); + reader = new RowReader(tempReference_row3); + row = tempReference_row3.get(); + Reference tempReference_reader2 = + new Reference(reader); + String dumpStr; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + r = DiagnosticConverter.ReaderToString(tempReference_reader2, out dumpStr); + reader = tempReference_reader2.get(); + assert Result.SUCCESS == r; + System.out.println(dumpStr); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void InitTestSuite() + public void InitTestSuite() { + String json = Files.readString(SerializerUnitTest.SchemaFile); + this.schema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.schema); + this.layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "BatchRequest")).SchemaId); + } + + public final static class BatchOperation { + public BatchRequestHeaders Headers; + public int OperationType; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ResourceBody; + public byte[] ResourceBody; + public String ResourcePath; + public int ResourceType; + } + + public final static class BatchOperationResponse { + public BatchResponseHeaders Headers; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte[] ResourceBody; + public byte[] ResourceBody; + public int StatusCode; + } + + public static class BatchOperationSerializer { + public static final TypeArgument TypeArg = new TypeArgument(LayoutType.UDT, + new TypeArgumentList(new SchemaId(2))); + + public static Result Read(Reference reader, Out operation) { + BatchOperation retval = new BatchOperation(); + operation.setAndGet(null); + while (reader.get().read()) { + Result r; + switch (reader.get().path()) { + case "operationType": + Out tempOut_OperationType = new Out(); + r = reader.get().readInt32(tempOut_OperationType); + retval.OperationType = tempOut_OperationType.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "headers": + Reference tempReference_child = new Reference(child); + Out tempOut_Headers = new Out(); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword + // - these are not converted by C# to Java Converter: + r = reader.get().readScope(retval, + (RowReader RowReader child, BatchOperation parent) -> BatchRequestHeadersSerializer.Read(tempReference_child, tempOut_Headers)); + parent.Headers = tempOut_Headers.get(); + child = tempReference_child.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "resourceType": + Out tempOut_ResourceType = new Out(); + r = reader.get().readInt32(tempOut_ResourceType); + retval.ResourceType = tempOut_ResourceType.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "resourcePath": + Out tempOut_ResourcePath = new Out(); + r = reader.get().readUtf8String(tempOut_ResourcePath); + retval.ResourcePath = tempOut_ResourcePath.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "resourceBody": + Out tempOut_ResourceBody = new Out(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: r = reader.ReadBinary(out retval.ResourceBody); + r = reader.get().ReadBinary(tempOut_ResourceBody); + retval.ResourceBody = tempOut_ResourceBody.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + } + } + + operation.setAndGet(retval); + return Result.SUCCESS; + } + + public static Result Write(Reference writer, TypeArgument typeArg, + BatchOperation operation) { + Result r = writer.get().WriteInt32("operationType", operation.OperationType); + if (r != Result.SUCCESS) { + return r; + } + + r = writer.get().WriteScope("headers", BatchRequestHeadersSerializer.TypeArg, operation.Headers, + BatchRequestHeadersSerializer.Write); + if (r != Result.SUCCESS) { + return r; + } + + r = writer.get().WriteInt32("resourceType", operation.ResourceType); + if (r != Result.SUCCESS) { + return r; + } + + r = writer.get().WriteString("resourcePath", operation.ResourcePath); + if (r != Result.SUCCESS) { + return r; + } + + r = writer.get().WriteBinary("resourceBody", operation.ResourceBody); + return r; + } + } + + public final static class BatchRequest { + public ArrayList Operations; + } + + public final static class BatchRequestHeaders { + public long SampleRequestHeader; + } + + public static class BatchRequestHeadersSerializer { + public static final TypeArgument TypeArg = new TypeArgument(LayoutType.UDT, + new TypeArgumentList(new SchemaId(1))); + + public static Result Read(Reference reader, + Out header) { + BatchRequestHeaders retval = new BatchRequestHeaders(); + header.setAndGet(null); + while (reader.get().read()) { + switch (reader.get().path()) { + case "sampleRequestHeader": + Out tempOut_SampleRequestHeader = new Out(); + Result r = reader.get().readInt64(tempOut_SampleRequestHeader); + retval.SampleRequestHeader = tempOut_SampleRequestHeader.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + } + } + + header.setAndGet(retval); + return Result.SUCCESS; + } + + public static Result Write(Reference writer, TypeArgument typeArg, + BatchRequestHeaders header) { + Result r = writer.get().WriteInt64("sampleRequestHeader", header.SampleRequestHeader); + return r; + } + } + + public static class BatchRequestSerializer { + public static final TypeArgument OperationsTypeArg = new TypeArgument(LayoutType.TypedArray, new TypeArgumentList(new TypeArgument[] { BatchOperationSerializer.TypeArg })); + + public static Result Read(Reference reader, Out request) { + assert reader.get().read(); + checkState(reader.get().path().equals("operations")); + + java.util.ArrayList operations; + Out> tempOut_operations = new Out>(); + Result r = RowReaderExtensions.readList(reader.get().clone(), BatchOperationSerializer.Read, tempOut_operations); + operations = tempOut_operations.get(); + if (r != Result.SUCCESS) { + request.setAndGet(null); + return r; + } + + request.setAndGet(new BatchRequest()); + request.get().Operations = operations; + + return Result.SUCCESS; + } + + public static Result Write(Reference writer, TypeArgument typeArg, BatchRequest request) { + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + return writer.get().WriteScope("operations", BatchRequestSerializer.OperationsTypeArg, request.Operations, (ref RowWriter writer2, TypeArgument typeArg2, ArrayList operations) -> + { + for (BatchOperation operation : operations) { + Result r = writer2.WriteScope(null, BatchOperationSerializer.TypeArg, operation, BatchOperationSerializer.Write); + if (r != Result.SUCCESS) { + return r; + } + } + + return Result.SUCCESS; + }); + } + } + + public final static class BatchResponse { + public ArrayList Operations; + } + + public final static class BatchResponseHeaders { + public String SampleResponseHeader; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TaggedUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TaggedUnitTests.java new file mode 100644 index 0000000..eba79c6 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TaggedUnitTests.java @@ -0,0 +1,256 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import java.nio.file.Files; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(TaggedUnitTests.SchemaFile, "TestData")] public sealed class TaggedUnitTests +public final class TaggedUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final String SchemaFile = "TestData\\TaggedApiSchema.json"; + private Layout layout; + private LayoutResolver resolver; + private Namespace schema; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateTaggedApi() + public void CreateTaggedApi() { + RowBuffer row = new RowBuffer(TaggedUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + TaggedApi c1 = new TaggedApi(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: c1.Tag1 = ((byte)1, "hello"); + c1.Tag1 = ((byte)1, "hello") + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: c1.Tag2 = ((byte)2, 28, 1974L); + c1.Tag2 = ((byte)2, 28, 1974L) + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteTaggedApi(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + TaggedApi c2 = this.ReadTaggedApi(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert c1 == c2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString(TaggedUnitTests.SchemaFile); + this.schema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.schema); + this.layout = this.resolver.Resolve(tangible.ListHelper.find(this.schema.getSchemas(), x -> x.Name.equals( + "TaggedApi")).SchemaId); + } + + private TaggedApi ReadTaggedApi(Reference row, Reference root) { + TaggedApi pc = new TaggedApi(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("tag1", out c); + assert c.Type.Immutable; + RowCursor tag1Scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out tag1Scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref tag1Scope, out tag1Scope) == Result.SUCCESS) { + assert tag1Scope.Immutable; + assert tag1Scope.MoveNext(row); + byte apiCode; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(ref row, ref + // tag1Scope, out byte apiCode)); + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref tag1Scope, + out apiCode)); + assert tag1Scope.MoveNext(row); + String str; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().ReadSparse(row, ref tag1Scope, out str)); + pc.Tag1 = (apiCode, str) + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("tag2", out c); + assert !c.Type.Immutable; + RowCursor tag2Scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out tag2Scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref tag2Scope, out tag2Scope) == Result.SUCCESS) { + assert !tag2Scope.Immutable; + assert tag2Scope.MoveNext(row); + byte apiCode; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(ref row, ref + // tag2Scope, out byte apiCode)); + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref tag2Scope, + out apiCode)); + assert tag2Scope.MoveNext(row); + int val1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().ReadSparse(row, ref tag2Scope, out val1)); + assert tag2Scope.MoveNext(row); + long val2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[2].Type.TypeAs().ReadSparse(row, ref tag2Scope, out val2)); + pc.Tag2 = (apiCode, val1, val2) + } + + return pc; + } + + private void WriteTaggedApi(Reference row, Reference root, TaggedApi pc) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("tag1", out c); + RowCursor tag1Scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out tag1Scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref tag1Scope, c.TypeArgs, + out tag1Scope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref tag1Scope, pc.Tag1.Item1)); + assert tag1Scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().WriteSparse(row, ref tag1Scope, pc.Tag1.Item2)); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("tag2", out c); + RowCursor tag2Scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out tag2Scope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref tag2Scope, c.TypeArgs, + out tag2Scope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref tag2Scope, pc.Tag2.Item1)); + assert tag2Scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().WriteSparse(row, ref tag2Scope, pc.Tag2.Item2)); + assert tag2Scope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[2].Type.TypeAs().WriteSparse(row, ref tag2Scope, pc.Tag2.Item3)); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test + // types.")] private sealed class TaggedApi + private final static class TaggedApi { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public (byte, string) Tag1; + public (byte,String)Tag1 + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public (byte, int, long) Tag2; + public (byte,int,long)Tag2 + + // ReSharper disable once MemberCanBePrivate.Local + public boolean equals(TaggedApi other) { + return this.Tag1.equals(other.Tag1) && this.Tag2.equals(other.Tag2); + } + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof TaggedApi; + TaggedApi taggedApi = tempVar ? (TaggedApi)obj : null; + return tempVar && this.equals(taggedApi); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = 0; + hashCode = (hashCode * 397) ^ this.Tag1.hashCode(); + hashCode = (hashCode * 397) ^ this.Tag2.hashCode(); + return hashCode; + } + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TupleUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TupleUnitTests.java new file mode 100644 index 0000000..f217792 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TupleUnitTests.java @@ -0,0 +1,1104 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.layouts.StringToken; + +import java.nio.file.Files; +import java.time.LocalDateTime; + +// ReSharper disable once StringLiteralTypo +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][SuppressMessage("Naming", "DontUseVarForVariableTypes", Justification = "The types here +// are anonymous.")][DeploymentItem("TestData\\PerfCounterSchema.json", "TestData")] public sealed class TupleUnitTests +public final class TupleUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + + private final PerfCounter counterExample = new PerfCounter() { + Name ="RowInserts",Value =Tuple.Create("units",12046L) + }; + + private Namespace counterSchema; + private Layout countersLayout; + private LayoutResolver countersResolver; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateCoordCounter() + public void CreateCoordCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = new PerfCounter(); + c1.Name = "CoordInserts"; + Coord tempVar = new Coord(); + tempVar.Lat = 12L; + tempVar.Lng = 40L; + c1.Coord = Tuple.Create("units", tempVar); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + PerfCounter c2 = this.ReadCounter(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert c1 == c2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateCounter() + public void CreateCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = this.counterExample; + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + PerfCounter c2 = this.ReadCounter(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert c1 == c2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateMinMeanMaxCounter() + public void CreateMinMeanMaxCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = new PerfCounter(); + c1.Name = "RowInserts"; + c1.MinMaxValue = Tuple.Create("units", Tuple.Create(12L, 542L, 12046L)); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + PerfCounter c2 = this.ReadCounter(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert c1 == c2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void DownwardDelegateWriteScope() + public void DownwardDelegateWriteScope() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + Layout layout = this.countersResolver.Resolve(tangible.ListHelper.find(this.counterSchema.getSchemas(), + x -> x.Name.equals("CounterSet")).SchemaId); + row.initLayout(HybridRowVersion.V1, layout, this.countersResolver); + + LayoutColumn col; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert layout.TryFind("history", out col); + StringToken historyToken; + Out tempOut_historyToken = + new Out(); + assert layout.getTokenizer().TryFindToken(col.Path, tempOut_historyToken); + historyToken = tempOut_historyToken.get(); + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor history; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row, out history).Find(tempReference_row2, historyToken); + row = tempReference_row2.get(); + row = tempReference_row.get(); + int ctx = 1; // ignored + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_history = + new Reference(history); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not + // converted by C# to Java Converter: + ResultAssert.IsSuccess(LayoutType.TypedArray.WriteScope(tempReference_row3, tempReference_history, col.TypeArgs, ctx, + (ref RowBuffer row2, ref RowCursor arrCur, int ctx2) -> + { + for (int i = 0; i < 5; i++) { + Reference tempReference_row2 = + new Reference(row2); + Reference tempReference_arrCur = + new Reference(arrCur); + ResultAssert.IsSuccess(LayoutType.UDT.WriteScope(tempReference_row2, tempReference_arrCur, + arrCur.ScopeTypeArgs[0].TypeArgs, i, (ref RowBuffer row3, ref RowCursor udtCur, int ctx3) -> + { + LayoutColumn col3; + assert udtCur.Layout.TryFind("minmeanmax", out col3); + Reference tempReference_row3 = + new Reference(row3); + ReferencetempRef_row32 = new Reference (row3); + ResultAssert.IsSuccess(LayoutType.TypedTuple.WriteScope(tempReference_row3, udtCur.Find(tempRef_row32, + col3.Path), col3.TypeArgs, ctx3, (ref RowBuffer row4, ref RowCursor tupCur, int ctx4) -> + { + if (ctx4 > 0) { + ReferencetempRef_row4 = new Reference (row4); + ReferencetempRef_tupCur = new Reference (tupCur); + ResultAssert.IsSuccess(LayoutType.Utf8.WriteSparse(tempRef_row4, tempRef_tupCur, "abc")); + tupCur = tempRef_tupCur.argValue; + row4 = tempRef_row4.argValue; + } + + if (ctx4 > 1) { + ReferencetempRef_row42 = new Reference (row4); + assert tupCur.MoveNext(tempRef_row42); + row4 = tempRef_row42.argValue; + Reference tempReference_row43 = new Reference(row4); + Reference tempReference_tupCur2 = new Reference(tupCur); + ResultAssert.IsSuccess(LayoutType.TypedTuple.WriteScope(tempReference_row43, + tempReference_tupCur2, + tupCur.ScopeTypeArgs[1].TypeArgs, ctx4, (ref RowBuffer row5, ref RowCursor tupCur2, + int ctx5) -> + { + if (ctx5 > 1) { + Reference tempReference_row5 = new Reference(row5); + Reference tempReference_tupCur2 = new Reference(tupCur2); + ResultAssert.IsSuccess(LayoutType.Int64.WriteSparse(tempReference_row5, tempReference_tupCur2 + , ctx5)); + tupCur2 = tempReference_tupCur2.get(); + row5 = tempReference_row5.get(); + } + + if (ctx5 > 2) { + ReferencetempRef_row52 = new Reference (row5); + assert tupCur2.MoveNext(tempRef_row52); + row5 = tempRef_row52.argValue; + Reference tempReference_row53 = new Reference(row5); + Reference tempReference_tupCur22 = new Reference(tupCur2); + ResultAssert.IsSuccess(LayoutType.Int64.WriteSparse(tempReference_row53, + tempReference_tupCur22, ctx5)); + tupCur2 = tempReference_tupCur22.get(); + row5 = tempReference_row53.get(); + } + + if (ctx5 > 3) { + ReferencetempRef_row54 = new Reference (row5); + assert tupCur2.MoveNext(tempRef_row54); + row5 = tempRef_row54.argValue; + Reference tempReference_row55 = new Reference(row5); + Reference tempReference_tupCur23 = new Reference(tupCur2); + ResultAssert.IsSuccess(LayoutType.Int64.WriteSparse(tempReference_row55, + tempReference_tupCur23, ctx5)); + tupCur2 = tempReference_tupCur23.get(); + row5 = tempReference_row55.get(); + } + + return Result.SUCCESS; + })); + tupCur = tempReference_tupCur2.get(); + row4 = tempReference_row43.get(); + } + + return Result.SUCCESS; + })); + row3 = tempRef_row32.argValue; + row3 = tempReference_row3.get(); + + return Result.SUCCESS; + })); + arrCur = tempReference_arrCur.get(); + row2 = tempReference_row2.get(); + + ReferencetempRef_row22 = new Reference (row2); + assert !arrCur.MoveNext(tempRef_row22); + row2 = tempRef_row22.argValue; + } + + return Result.SUCCESS; + })); + history = tempReference_history.get(); + row = tempReference_row3.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString("TestData\\PerfCounterSchema.json"); + this.counterSchema = Namespace.Parse(json); + this.countersResolver = new LayoutResolverNamespace(this.counterSchema); + this.countersLayout = this.countersResolver.Resolve(tangible.ListHelper.find(this.counterSchema.getSchemas(), + x -> x.Name.equals("Counters")).SchemaId); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void PreventInsertsAndDeletesInFixedArityCounter() + public void PreventInsertsAndDeletesInFixedArityCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = this.counterExample; + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("value", out c); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row3, out valueScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(tempReference_row5, ref valueScope, c.TypeArgs, + out valueScope)); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_row7 = + new Reference(row); + RowCursor valueScope2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row6, out valueScope2).Find(tempReference_row7, c.Path); + row = tempReference_row7.get(); + row = tempReference_row6.get(); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().ReadScope(tempReference_row8, ref valueScope2, + out valueScope2)); + row = tempReference_row8.get(); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert valueScope.AsReadOnly(out _).ScopeType == valueScope2.ScopeType; + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert valueScope.AsReadOnly(out _).start == valueScope2.start(); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert valueScope.AsReadOnly(out _).Immutable == valueScope2.Immutable; + + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.TypeConstraint(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row9, ref valueScope, + "millis", UpdateOptions.InsertAt)); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.TypeConstraint(c.TypeArgs[0].Type.TypeAs().DeleteSparse(tempReference_row10, + ref valueScope)); + row = tempReference_row10.get(); + Reference tempReference_row11 = + new Reference(row); + assert !valueScope.MoveTo(tempReference_row11, 2); + row = tempReference_row11.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void VerifyTypeConstraintsCoordCounter() + public void VerifyTypeConstraintsCoordCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = new PerfCounter(); + c1.Name = "RowInserts"; + Coord tempVar = new Coord(); + tempVar.Lat = 12L; + tempVar.Lng = 40L; + c1.Coord = Tuple.Create("units", tempVar); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("coord", out c); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row3, out valueScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(tempReference_row5, ref valueScope, c.TypeArgs, + out valueScope)); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_valueScope = + new Reference(valueScope); + ResultAssert.TypeConstraint(LayoutType.DateTime.WriteSparse(tempReference_row6, tempReference_valueScope, + LocalDateTime.now())); + valueScope = tempReference_valueScope.get(); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, ref valueScope, + "mins")); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + assert valueScope.MoveNext(tempReference_row8); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + Reference tempReference_valueScope2 = + new Reference(valueScope); + ResultAssert.TypeConstraint(LayoutType.Int8.WriteSparse(tempReference_row9, tempReference_valueScope2, (byte)42)); + valueScope = tempReference_valueScope2.get(); + row = tempReference_row9.get(); + + TypeArgument coordType = c.TypeArgs[1]; + + // Invalid because is a UDT but the wrong type. + Reference tempReference_row10 = + new Reference(row); + Reference tempReference_valueScope3 = + new Reference(valueScope); + RowCursor _; + Out tempOut__ = + new Out(); + ResultAssert.TypeConstraint(coordType.getType().TypeAs().WriteScope(tempReference_row10, + tempReference_valueScope3, new TypeArgumentList(this.countersLayout.getSchemaId().clone()), tempOut__)); + _ = tempOut__.get(); + valueScope = tempReference_valueScope3.get(); + row = tempReference_row10.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void VerifyTypeConstraintsCounter() + public void VerifyTypeConstraintsCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = this.counterExample; + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("value", out c); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row3, out valueScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(tempReference_row5, ref valueScope, c.TypeArgs, + out valueScope)); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_valueScope = + new Reference(valueScope); + ResultAssert.TypeConstraint(LayoutType.Boolean.WriteSparse(tempReference_row6, tempReference_valueScope, true)); + valueScope = tempReference_valueScope.get(); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, ref valueScope, + "millis")); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + assert valueScope.MoveNext(tempReference_row8); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + Reference tempReference_valueScope2 = + new Reference(valueScope); + ResultAssert.TypeConstraint(LayoutType.Float32.WriteSparse(tempReference_row9, tempReference_valueScope2, + 0.1F)); + valueScope = tempReference_valueScope2.get(); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().WriteSparse(tempReference_row10, ref valueScope, + 100L)); + row = tempReference_row10.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void VerifyTypeConstraintsMinMeanMaxCounter() + public void VerifyTypeConstraintsMinMeanMaxCounter() { + RowBuffer row = new RowBuffer(TupleUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.countersLayout, this.countersResolver); + + PerfCounter c1 = new PerfCounter(); + c1.Name = "RowInserts"; + c1.MinMaxValue = Tuple.Create("units", Tuple.Create(12L, 542L, 12046L)); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteCounter(tempReference_row, RowCursor.create(tempReference_row2, out _), c1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + // ReSharper disable once StringLiteralTypo + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("minmeanmax", out c); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row3, out valueScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(tempReference_row5, ref valueScope, c.TypeArgs, + out valueScope)); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_valueScope = + new Reference(valueScope); + ResultAssert.TypeConstraint(LayoutType.DateTime.WriteSparse(tempReference_row6, tempReference_valueScope, + LocalDateTime.now())); + valueScope = tempReference_valueScope.get(); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, ref valueScope, + "secs")); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + assert valueScope.MoveNext(tempReference_row8); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + Reference tempReference_valueScope2 = + new Reference(valueScope); + ResultAssert.TypeConstraint(LayoutType.Decimal.WriteSparse(tempReference_row9, tempReference_valueScope2, 12)); + valueScope = tempReference_valueScope2.get(); + row = tempReference_row9.get(); + + TypeArgument mmmType = c.TypeArgs[1]; + + // Invalid because not a tuple type. + Reference tempReference_row10 = + new Reference(row); + RowCursor mmmScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.TypeConstraint(mmmType.getType().TypeAs().WriteScope(tempReference_row10, + ref valueScope, TypeArgumentList.Empty, out mmmScope)); + row = tempReference_row10.get(); + + // Invalid because is a tuple type but with the wrong parameters. + Reference tempReference_row11 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.TypeConstraint(mmmType.getType().TypeAs().WriteScope(tempReference_row11, + ref valueScope, new TypeArgumentList(new TypeArgument[] + { + new TypeArgument(LayoutType.Boolean), + new TypeArgument(LayoutType.Int64) + }), out mmmScope)); + row = tempReference_row11.get(); + + // Invalid because is a tuple type but with the wrong arity. + Reference tempReference_row12 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.TypeConstraint(mmmType.getType().TypeAs().WriteScope(tempReference_row12, + ref valueScope, new TypeArgumentList(new TypeArgument[] { new TypeArgument(LayoutType.Utf8) }), + out mmmScope)); + row = tempReference_row12.get(); + + Reference tempReference_row13 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(mmmType.getType().TypeAs().WriteScope(tempReference_row13, + ref valueScope, mmmType.getTypeArgs().clone(), out mmmScope)); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ResultAssert.TypeConstraint(LayoutType.Binary.WriteSparse(ref row, ref valueScope, new + // byte[] { 1, 2, 3 })); + ResultAssert.TypeConstraint(LayoutType.Binary.WriteSparse(tempReference_row14, ref valueScope, new byte[] { 1 + , 2, + 3 })); + row = tempReference_row14.get(); + Reference tempReference_row15 = + new Reference(row); + Reference tempReference_mmmScope = + new Reference(mmmScope); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(0).getType().TypeAs().WriteSparse(tempReference_row15 + , tempReference_mmmScope, 1L)); + mmmScope = tempReference_mmmScope.get(); + row = tempReference_row15.get(); + Reference tempReference_row16 = + new Reference(row); + assert mmmScope.MoveNext(tempReference_row16); + row = tempReference_row16.get(); + Reference tempReference_row17 = + new Reference(row); + Reference tempReference_mmmScope2 = + new Reference(mmmScope); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(1).getType().TypeAs().WriteSparse(tempReference_row17 + , tempReference_mmmScope2, 2L)); + mmmScope = tempReference_mmmScope2.get(); + row = tempReference_row17.get(); + Reference tempReference_row18 = + new Reference(row); + assert mmmScope.MoveNext(tempReference_row18); + row = tempReference_row18.get(); + Reference tempReference_row19 = + new Reference(row); + Reference tempReference_mmmScope3 = + new Reference(mmmScope); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(2).getType().TypeAs().WriteSparse(tempReference_row19 + , tempReference_mmmScope3, 3L)); + mmmScope = tempReference_mmmScope3.get(); + row = tempReference_row19.get(); + } + + private static Coord ReadCoord(Reference row, Reference coordScope) { + Layout coordLayout = coordScope.get().getLayout(); + Coord cd = new Coord(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert coordLayout.TryFind("lat", out c); + Out tempOut_Lat = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, coordScope, c, tempOut_Lat)); + cd.Lat = tempOut_Lat.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert coordLayout.TryFind("lng", out c); + Out tempOut_Lng = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, coordScope, c, tempOut_Lng)); + cd.Lng = tempOut_Lng.get(); + + return cd; + } + + private PerfCounter ReadCounter(Reference row, Reference root) { + PerfCounter pc = new PerfCounter(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("name", out c); + Out tempOut_Name = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_Name)); + pc.Name = tempOut_Name.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("value", out c); + assert c.Type.Immutable; + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out valueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref valueScope, out valueScope) == Result.SUCCESS) { + assert valueScope.Immutable; + assert valueScope.MoveNext(row); + String units; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref valueScope, out units)); + assert valueScope.MoveNext(row); + long metric; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().ReadSparse(row, ref valueScope, + out metric)); + pc.Value = Tuple.Create(units, metric); + } + + // ReSharper disable once StringLiteralTypo + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("minmeanmax", out c); + assert c.Type.Immutable; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out valueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref valueScope, out valueScope) == Result.SUCCESS) { + assert valueScope.Immutable; + assert valueScope.MoveNext(row); + String units; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref valueScope, out units)); + + assert valueScope.MoveNext(row); + TypeArgument mmmType = c.TypeArgs[1]; + Reference tempReference_valueScope = + new Reference(valueScope); + RowCursor mmmScope; + Out tempOut_mmmScope = + new Out(); + ResultAssert.IsSuccess(mmmType.getType().TypeAs().ReadScope(row, tempReference_valueScope, + tempOut_mmmScope)); + mmmScope = tempOut_mmmScope.get(); + valueScope = tempReference_valueScope.get(); + + assert mmmScope.Immutable; + assert mmmScope.MoveNext(row); + Reference tempReference_mmmScope = + new Reference(mmmScope); + long min; + Out tempOut_min = new Out(); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(0).getType().TypeAs().ReadSparse(row, + tempReference_mmmScope, tempOut_min)); + min = tempOut_min.get(); + mmmScope = tempReference_mmmScope.get(); + assert mmmScope.MoveNext(row); + Reference tempReference_mmmScope2 = + new Reference(mmmScope); + long mean; + Out tempOut_mean = new Out(); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(1).getType().TypeAs().ReadSparse(row, + tempReference_mmmScope2, tempOut_mean)); + mean = tempOut_mean.get(); + mmmScope = tempReference_mmmScope2.get(); + assert mmmScope.MoveNext(row); + Reference tempReference_mmmScope3 = + new Reference(mmmScope); + long max; + Out tempOut_max = new Out(); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(2).getType().TypeAs().ReadSparse(row, + tempReference_mmmScope3, tempOut_max)); + max = tempOut_max.get(); + mmmScope = tempReference_mmmScope3.get(); + + pc.MinMaxValue = Tuple.Create(units, Tuple.Create(min, mean, max)); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("coord", out c); + assert c.Type.Immutable; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out valueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref valueScope, out valueScope) == Result.SUCCESS) { + assert valueScope.Immutable; + assert valueScope.MoveNext(row); + String units; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref valueScope, out units)); + + assert valueScope.MoveNext(row); + RowCursor coordScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().ReadScope(row, ref valueScope, + out coordScope)); + Reference tempReference_coordScope = new Reference(coordScope); + pc.Coord = Tuple.Create(units, TupleUnitTests.ReadCoord(row, tempReference_coordScope)); + coordScope = tempReference_coordScope.get(); + } + + return pc; + } + + private static void WriteCoord(Reference row, Reference coordScope, TypeArgumentList typeArgs, Coord cd) { + Layout coordLayout = row.get().resolver().resolve(typeArgs.getSchemaId().clone()); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert coordLayout.TryFind("lat", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, coordScope, c, cd.Lat)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert coordLayout.TryFind("lng", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, coordScope, c, cd.Lng)); + } + + private void WriteCounter(Reference row, Reference root, PerfCounter pc) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.countersLayout.TryFind("name", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, pc.Name)); + + if (pc.Value != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.countersLayout.TryFind("value", out c); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out valueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref valueScope, c.TypeArgs, + out valueScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref valueScope, + pc.Value.Item1)); + assert valueScope.MoveNext(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[1].Type.TypeAs().WriteSparse(row, ref valueScope, + pc.Value.Item2)); + } + + if (pc.MinMaxValue != null) { + // ReSharper disable once StringLiteralTypo + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.countersLayout.TryFind("minmeanmax", out c); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out valueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref valueScope, c.TypeArgs, + out valueScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref valueScope, + pc.MinMaxValue.Item1)); + + assert valueScope.MoveNext(row); + TypeArgument mmmType = c.TypeArgs[1]; + RowCursor mmmScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(mmmType.getType().TypeAs().WriteScope(row, ref valueScope, + mmmType.getTypeArgs().clone(), out mmmScope)); + + Reference tempReference_mmmScope = + new Reference(mmmScope); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(0).getType().TypeAs().WriteSparse(row, + tempReference_mmmScope, pc.MinMaxValue.Item2.Item1)); + mmmScope = tempReference_mmmScope.get(); + + assert mmmScope.MoveNext(row); + Reference tempReference_mmmScope2 = + new Reference(mmmScope); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(1).getType().TypeAs().WriteSparse(row, + tempReference_mmmScope2, pc.MinMaxValue.Item2.Item2)); + mmmScope = tempReference_mmmScope2.get(); + + assert mmmScope.MoveNext(row); + Reference tempReference_mmmScope3 = + new Reference(mmmScope); + ResultAssert.IsSuccess(mmmType.getTypeArgs().get(2).getType().TypeAs().WriteSparse(row, + tempReference_mmmScope3, pc.MinMaxValue.Item2.Item3)); + mmmScope = tempReference_mmmScope3.get(); + } + + if (pc.Coord != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.countersLayout.TryFind("coord", out c); + RowCursor valueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out valueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref valueScope, c.TypeArgs, + out valueScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref valueScope, + pc.Coord.Item1)); + + assert valueScope.MoveNext(row); + TypeArgument mmmType = c.TypeArgs[1]; + Reference tempReference_valueScope = + new Reference(valueScope); + RowCursor coordScope; + Out tempOut_coordScope = + new Out(); + ResultAssert.IsSuccess(mmmType.getType().TypeAs().WriteScope(row, tempReference_valueScope, + mmmType.getTypeArgs().clone(), tempOut_coordScope)); + coordScope = tempOut_coordScope.get(); + valueScope = tempReference_valueScope.get(); + Reference tempReference_coordScope = + new Reference(coordScope); + TupleUnitTests.WriteCoord(row, tempReference_coordScope, mmmType.getTypeArgs().clone(), pc.Coord.Item2); + coordScope = tempReference_coordScope.get(); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class Coord + private final static class Coord { + public long Lat; + public long Lng; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Coord; + Coord coord = tempVar ? (Coord)obj : null; + return tempVar && this.equals(coord); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + return ((new Long(this.Lat)).hashCode() * 397) ^ (new Long(this.Lng)).hashCode(); + } + } + + private boolean equals(Coord other) { + return this.Lat == other.Lat && this.Lng == other.Lng; + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class PerfCounter + private final static class PerfCounter { + // ReSharper disable once MemberHidesStaticFromOuterClass + public Tuple Coord; + public Tuple> MinMaxValue; + public String Name; + public Tuple Value; + + // ReSharper disable once MemberCanBePrivate.Local + public boolean equals(PerfCounter other) { + return this.Name.equals(other.Name) && this.Value.equals(other.Value) && this.MinMaxValue.equals(other.MinMaxValue) && this.Coord.equals(other.Coord); + } + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof PerfCounter; + PerfCounter counter = tempVar ? (PerfCounter)obj : null; + return tempVar && this.equals(counter); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = this.Name == null ? null : this.Name.hashCode() != null ? this.Name.hashCode() : 0; + hashCode = (hashCode * 397) ^ (this.Value == null ? null : this.Value.hashCode() != null ? this.Value.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.MinMaxValue == null ? null : this.MinMaxValue.hashCode() != null ? this.MinMaxValue.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Coord == null ? null : this.Coord.hashCode() != null ? this.Coord.hashCode() : 0); + return hashCode; + } + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedArrayUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedArrayUnitTests.java new file mode 100644 index 0000000..79cf7bd --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedArrayUnitTests.java @@ -0,0 +1,663 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; + +// ReSharper disable StringLiteralTypo +// ReSharper disable IdentifierTypo + + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(TypedArrayUnitTests.SchemaFile, "TestData")] public sealed class +// TypedArrayUnitTests +public final class TypedArrayUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final String SchemaFile = "TestData\\TagSchema.json"; + private Namespace counterSchema; + private Layout layout; + private LayoutResolver resolver; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateTags() + public void CreateTags() { + RowBuffer row = new RowBuffer(TypedArrayUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + Tagged t1 = new Tagged(); + t1.Title = "Thriller"; + t1.Tags = new ArrayList(Arrays.asList("classic", "Post-disco", "funk")); + t1.Options = new ArrayList(Arrays.asList(8, null, 9)); + t1.Ratings = new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(1.2, 3.0)), + new ArrayList(Arrays.asList(4.1, 5.7)), new ArrayList(Arrays.asList(7.3, 8.12, 9.14)))); + SimilarMatch tempVar = new SimilarMatch(); + tempVar.Thumbprint = "TRABACN128F425B784"; + tempVar.Score = 0.87173699999999998; + SimilarMatch tempVar2 = new SimilarMatch(); + tempVar2.Thumbprint = "TRJYGLF12903CB4952"; + tempVar2.Score = 0.75105200000000005; + SimilarMatch tempVar3 = new SimilarMatch(); + tempVar3.Thumbprint = "TRWJMMB128F429D550"; + tempVar3.Score = 0.50866100000000003; + t1.Similars = new ArrayList(Arrays.asList(tempVar, tempVar2, tempVar3)); + t1.Priority = new ArrayList>(Arrays.asList(Tuple.Create("80's", 100L), Tuple.Create( + "classics", 100L), Tuple.Create("pop", 50L))); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteTagged(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Tagged t2 = this.ReadTagged(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert t1 == t2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString(TypedArrayUnitTests.SchemaFile); + this.counterSchema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.counterSchema); + this.layout = this.resolver.Resolve(tangible.ListHelper.find(this.counterSchema.getSchemas(), + x -> x.Name.equals("Tagged")).SchemaId); + } + + private static SimilarMatch ReadSimilarMatch(Reference row, + Reference matchScope) { + Layout matchLayout = matchScope.get().getLayout(); + SimilarMatch m = new SimilarMatch(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("thumbprint", out c); + Out tempOut_Thumbprint = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, matchScope, c, tempOut_Thumbprint)); + m.Thumbprint = tempOut_Thumbprint.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("score", out c); + Out tempOut_Score = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadFixed(row, matchScope, c, tempOut_Score)); + m.Score = tempOut_Score.get(); + return m; + } + + private Tagged ReadTagged(Reference row, Reference root) { + Tagged value = new Tagged(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("title", out c); + Out tempOut_Title = new Out(); + ResultAssert.IsSuccess(c.TypeAs().ReadVariable(row, root, c, tempOut_Title)); + value.Title = tempOut_Title.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("tags", out c); + RowCursor tagsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out tagsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref tagsScope, out tagsScope) == Result.SUCCESS) { + value.Tags = new ArrayList(); + while (tagsScope.MoveNext(row)) { + String item; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref tagsScope, + out item)); + value.Tags.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("options", out c); + RowCursor optionsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out optionsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref optionsScope, out optionsScope) == Result.SUCCESS) { + value.Options = new ArrayList(); + while (optionsScope.MoveNext(row)) { + TypeArgument itemType = c.TypeArgs[0]; + Reference tempReference_optionsScope = + new Reference(optionsScope); + RowCursor nullableScope; + Out tempOut_nullableScope = + new Out(); + ResultAssert.IsSuccess(itemType.getType().TypeAs().ReadScope(row, + tempReference_optionsScope, tempOut_nullableScope)); + nullableScope = tempOut_nullableScope.get(); + optionsScope = tempReference_optionsScope.get(); + + if (nullableScope.MoveNext(row)) { + Reference tempReference_nullableScope = new Reference(nullableScope); + ResultAssert.IsSuccess(LayoutNullable.HasValue(row, tempReference_nullableScope)); + nullableScope = tempReference_nullableScope.get(); + + Reference tempReference_nullableScope2 = new Reference(nullableScope); + int itemValue; + Out tempOut_itemValue = new Out(); + ResultAssert.IsSuccess(itemType.getTypeArgs().get(0).getType().TypeAs().ReadSparse(row, tempReference_nullableScope2, tempOut_itemValue)); + itemValue = tempOut_itemValue.get(); + nullableScope = tempReference_nullableScope2.get(); + + value.Options.add(itemValue); + } else { + Reference tempReference_nullableScope3 = new Reference(nullableScope); + ResultAssert.NotFound(LayoutNullable.HasValue(row, tempReference_nullableScope3)); + nullableScope = tempReference_nullableScope3.get(); + + value.Options.add(null); + } + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("ratings", out c); + RowCursor ratingsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out ratingsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref ratingsScope, out ratingsScope) == Result.SUCCESS) { + value.Ratings = new ArrayList>(); + TypeArgument innerType = c.TypeArgs[0]; + LayoutTypedArray innerLayout = innerType.getType().TypeAs(); + RowCursor innerScope = null; + Reference tempReference_innerScope = + new Reference(innerScope); + while (ratingsScope.MoveNext(row, tempReference_innerScope)) { + innerScope = tempReference_innerScope.get(); + ArrayList item = new ArrayList(); + Reference tempReference_ratingsScope = + new Reference(ratingsScope); + Out tempOut_innerScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(row, tempReference_ratingsScope, tempOut_innerScope)); + innerScope = tempOut_innerScope.get(); + ratingsScope = tempReference_ratingsScope.get(); + while (RowCursors.moveNext(innerScope.clone() + , row)) { + LayoutFloat64 itemLayout = innerType.getTypeArgs().get(0).getType().TypeAs(); + Reference tempReference_innerScope2 + = new Reference(innerScope); + double innerItem; + Out tempOut_innerItem = new Out(); + ResultAssert.IsSuccess(itemLayout.ReadSparse(row, tempReference_innerScope2, tempOut_innerItem)); + innerItem = tempOut_innerItem.get(); + innerScope = tempReference_innerScope2.get(); + item.add(innerItem); + } + + value.Ratings.add(item); + } + innerScope = tempReference_innerScope.get(); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("similars", out c); + RowCursor similarsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out similarsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref similarsScope, out similarsScope) == Result.SUCCESS) { + value.Similars = new ArrayList(); + while (similarsScope.MoveNext(row)) { + TypeArgument innerType = c.TypeArgs[0]; + LayoutUDT innerLayout = innerType.getType().TypeAs(); + Reference tempReference_similarsScope = + new Reference(similarsScope); + RowCursor matchScope; + Out tempOut_matchScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(row, tempReference_similarsScope, tempOut_matchScope)); + matchScope = tempOut_matchScope.get(); + similarsScope = tempReference_similarsScope.get(); + Reference tempReference_matchScope = + new Reference(matchScope); + SimilarMatch item = TypedArrayUnitTests.ReadSimilarMatch(row, tempReference_matchScope); + matchScope = tempReference_matchScope.get(); + value.Similars.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("priority", out c); + RowCursor priorityScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out priorityScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.TypeAs().ReadScope(row, ref priorityScope, out priorityScope) == Result.SUCCESS) { + value.Priority = new ArrayList>(); + RowCursor tupleScope = null; + Reference tempReference_tupleScope = + new Reference(tupleScope); + while (priorityScope.MoveNext(row, tempReference_tupleScope)) { + tupleScope = tempReference_tupleScope.get(); + TypeArgument innerType = c.TypeArgs[0]; + LayoutIndexedScope innerLayout = innerType.getType().TypeAs(); + + Reference tempReference_priorityScope = + new Reference(priorityScope); + Out tempOut_tupleScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(row, tempReference_priorityScope, tempOut_tupleScope)); + tupleScope = tempOut_tupleScope.get(); + priorityScope = tempReference_priorityScope.get(); + assert RowCursors.moveNext(tupleScope.clone() + , row); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + String item1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(innerType.getTypeArgs().get(0).getType().TypeAs().ReadSparse(row, + tempReference_tupleScope2, out item1)); + tupleScope = tempReference_tupleScope2.get(); + + assert RowCursors.moveNext(tupleScope.clone() + , row); + Reference tempReference_tupleScope3 = + new Reference(tupleScope); + long item2; + Out tempOut_item2 = new Out(); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(1).getType().TypeAs().ReadSparse(row, + tempReference_tupleScope3, tempOut_item2)); + item2 = tempOut_item2.get(); + tupleScope = tempReference_tupleScope3.get(); + + value.Priority.add(Tuple.Create(item1, item2)); + } + tupleScope = tempReference_tupleScope.get(); + } + + return value; + } + + private static void WriteSimilarMatch(Reference row, Reference matchScope + , TypeArgumentList typeArgs, SimilarMatch m) { + Layout matchLayout = row.get().resolver().resolve(typeArgs.getSchemaId().clone()); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("thumbprint", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, matchScope, c, m.Thumbprint)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("score", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteFixed(row, matchScope, c, m.Score)); + } + + private void WriteTagged(Reference row, Reference root, Tagged value) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("title", out c); + ResultAssert.IsSuccess(c.TypeAs().WriteVariable(row, root, c, value.Title)); + + if (value.Tags != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("tags", out c); + RowCursor tagsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out tagsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref tagsScope, c.TypeArgs, + out tagsScope)); + for (String item : value.Tags) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(row, ref tagsScope, item)); + assert !tagsScope.MoveNext(row); + } + } + + if (value.Options != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("options", out c); + RowCursor optionsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out optionsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref optionsScope, c.TypeArgs, + out optionsScope)); + for (Integer item : value.Options) { + TypeArgument itemType = c.TypeArgs[0]; + RowCursor nullableScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(itemType.getType().TypeAs().WriteScope(row, ref optionsScope, + itemType.getTypeArgs().clone(), item != null, out nullableScope)); + + if (item != null) { + Reference tempReference_nullableScope = new Reference(nullableScope); + ResultAssert.IsSuccess(itemType.getTypeArgs().get(0).getType().TypeAs().WriteSparse(row, tempReference_nullableScope, item.intValue())); + nullableScope = tempReference_nullableScope.get(); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !optionsScope.MoveNext(row, ref nullableScope); + } + } + + if (value.Ratings != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("ratings", out c); + RowCursor ratingsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out ratingsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref ratingsScope, c.TypeArgs, + out ratingsScope)); + for (ArrayList item : value.Ratings) { + assert item != null; + TypeArgument innerType = c.TypeArgs[0]; + LayoutTypedArray innerLayout = innerType.getType().TypeAs(); + Reference tempReference_ratingsScope = + new Reference(ratingsScope); + RowCursor innerScope; + Out tempOut_innerScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.WriteScope(row, tempReference_ratingsScope, + innerType.getTypeArgs().clone(), tempOut_innerScope)); + innerScope = tempOut_innerScope.get(); + ratingsScope = tempReference_ratingsScope.get(); + for (double innerItem : item) { + LayoutFloat64 itemLayout = innerType.getTypeArgs().get(0).getType().TypeAs(); + Reference tempReference_innerScope = + new Reference(innerScope); + ResultAssert.IsSuccess(itemLayout.WriteSparse(row, tempReference_innerScope, innerItem)); + innerScope = tempReference_innerScope.get(); + assert !innerScope.MoveNext(row); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !ratingsScope.MoveNext(row, ref innerScope); + } + } + + if (value.Similars != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("similars", out c); + RowCursor similarsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out similarsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref similarsScope, c.TypeArgs, + out similarsScope)); + for (SimilarMatch item : value.Similars) { + TypeArgument innerType = c.TypeArgs[0]; + LayoutUDT innerLayout = innerType.getType().TypeAs(); + Reference tempReference_similarsScope = + new Reference(similarsScope); + RowCursor matchScope; + Out tempOut_matchScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.WriteScope(row, tempReference_similarsScope, + innerType.getTypeArgs().clone(), tempOut_matchScope)); + matchScope = tempOut_matchScope.get(); + similarsScope = tempReference_similarsScope.get(); + Reference tempReference_matchScope = + new Reference(matchScope); + TypedArrayUnitTests.WriteSimilarMatch(row, tempReference_matchScope, innerType.getTypeArgs().clone(), item); + matchScope = tempReference_matchScope.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !similarsScope.MoveNext(row, ref matchScope); + } + } + + if (value.Priority != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("priority", out c); + RowCursor priorityScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out priorityScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeAs().WriteScope(row, ref priorityScope, c.TypeArgs, + out priorityScope)); + for (Tuple item : value.Priority) { + TypeArgument innerType = c.TypeArgs[0]; + LayoutIndexedScope innerLayout = innerType.getType().TypeAs(); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(innerLayout.WriteScope(row, ref priorityScope, innerType.getTypeArgs().clone() + , out tupleScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(innerType.getTypeArgs().get(0).getType().TypeAs().WriteSparse(row, + ref tupleScope, item.Item1)); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope = + new Reference(tupleScope); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(1).getType().TypeAs().WriteSparse(row + , tempReference_tupleScope, item.Item2)); + tupleScope = tempReference_tupleScope.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + assert !priorityScope.MoveNext(row, ref tupleScope); + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class SimilarMatch + private final static class SimilarMatch { + public double Score; + public String Thumbprint; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof SimilarMatch; + SimilarMatch match = tempVar ? (SimilarMatch)obj : null; + return tempVar && this.equals(match); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + return (this.Thumbprint.hashCode() * 397) ^ (new Double(this.Score)).hashCode(); + } + } + + private boolean equals(SimilarMatch other) { + // ReSharper disable once CompareOfFloatsByEqualityOperator + return this.Thumbprint.equals(other.Thumbprint) && this.Score == other.Score; + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test + // types.")] private sealed class Tagged + private final static class Tagged { + public ArrayList Options; + public ArrayList> Priority; + public ArrayList> Ratings; + public ArrayList Similars; + public ArrayList Tags; + public String Title; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Tagged; + Tagged tagged = tempVar ? (Tagged)obj : null; + return tempVar && this.equals(tagged); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = this.Title == null ? null : this.Title.hashCode() != null ? this.Title.hashCode() : 0; + hashCode = (hashCode * 397) ^ (this.Tags == null ? null : this.Tags.hashCode() != null ? + this.Tags.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Options == null ? null : this.Options.hashCode() != null ? + this.Options.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Ratings == null ? null : this.Ratings.hashCode() != null ? this.Ratings.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Similars == null ? null : this.Similars.hashCode() != null ? this.Similars.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Priority == null ? null : this.Priority.hashCode() != null ? this.Priority.hashCode() : 0); + return hashCode; + } + } + + private static boolean NestedSequenceEquals(ArrayList> left, ArrayList> right) { + if (left.size() != right.size()) { + return false; + } + + for (int i = 0; i < left.size(); i++) { + //C# TO JAVA CONVERTER WARNING: Java AbstractList 'equals' is not always identical to LINQ 'SequenceEqual': + //ORIGINAL LINE: if (!left[i].SequenceEqual(right[i])) + if (!left.get(i).equals(right.get(i))) { + return false; + } + } + + return true; + } + + private boolean equals(Tagged other) { + //C# TO JAVA CONVERTER WARNING: Java AbstractList 'equals' is not always identical to LINQ 'SequenceEqual': + //ORIGINAL LINE: return string.Equals(this.Title, other.Title) && (object.ReferenceEquals(this.Tags, other.Tags) || ((this.Tags != null) && (other.Tags != null) && this.Tags.SequenceEqual(other.Tags))) && (object.ReferenceEquals(this.Options, other.Options) || ((this.Options != null) && (other.Options != null) && this.Options.SequenceEqual(other.Options))) && (object.ReferenceEquals(this.Ratings, other.Ratings) || ((this.Ratings != null) && (other.Ratings != null) && Tagged.NestedSequenceEquals(this.Ratings, other.Ratings))) && (object.ReferenceEquals(this.Similars, other.Similars) || ((this.Similars != null) && (other.Similars != null) && this.Similars.SequenceEqual(other.Similars))) && (object.ReferenceEquals(this.Priority, other.Priority) || ((this.Priority != null) && (other.Priority != null) && this.Priority.SequenceEqual(other.Priority))); + return this.Title.equals(other.Title) && (this.Tags == other.Tags || ((this.Tags != null) && (other.Tags != null) && this.Tags.equals(other.Tags))) && (this.Options == other.Options || ((this.Options != null) && (other.Options != null) && this.Options.equals(other.Options))) && (this.Ratings == other.Ratings || ((this.Ratings != null) && (other.Ratings != null) && Tagged.NestedSequenceEquals(this.Ratings, other.Ratings))) && (this.Similars == other.Similars || ((this.Similars != null) && (other.Similars != null) && this.Similars.equals(other.Similars))) && (this.Priority == other.Priority || ((this.Priority != null) && (other.Priority != null) && this.Priority.equals(other.Priority))); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedMapUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedMapUnitTests.java new file mode 100644 index 0000000..1dab8ce --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedMapUnitTests.java @@ -0,0 +1,1575 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; + +import java.math.BigDecimal; +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(TypedMapUnitTests.SchemaFile, "TestData")] public sealed class +// TypedMapUnitTests +public final class TypedMapUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final String SchemaFile = "TestData\\MovieSchema.json"; + private Namespace counterSchema; + private Layout layout; + private LayoutResolver resolver; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateMovies() + public void CreateMovies() { + RowBuffer row = new RowBuffer(TypedMapUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + // ReSharper disable StringLiteralTypo + Movie t1 = new Movie(); + t1.Cast = new HashMap(Map.ofEntries(Map.entry("Mark", "Luke"), Map.entry("Harrison", "Han"), + Map.entry("Carrie", "Leia"))); + t1.Stats = new HashMap(Map.ofEntries(Map.entry(UUID.fromString("{4674962B-CE11-4916-81C5" + + "-0421EE36F168}"), 11000000.00), Map.entry(UUID.fromString("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), + 1554475.00))); + t1.Related = new HashMap>(Map.ofEntries(Map.entry("Mark", new HashMap(Map.ofEntries(Map.entry(103359, "Joker"), Map.entry(131646, "Merlin")))), Map.entry("Harrison", + new HashMap(Map.ofEntries(Map.entry(0082971, "Indy"), Map.entry(83658, "Deckard")))))); + Earnings tempVar = new Earnings(); + tempVar.Domestic = new BigDecimal(307263857); + tempVar.Worldwide = new BigDecimal(100000); + Earnings tempVar2 = new Earnings(); + tempVar2.Domestic = new BigDecimal(15476285); + tempVar2.Worldwide = new BigDecimal(200000); + Earnings tempVar3 = new Earnings(); + tempVar3.Domestic = new BigDecimal(138257865); + tempVar3.Worldwide = new BigDecimal(300000); + t1.Revenue = new HashMap(Map.ofEntries(Map.entry(LocalDateTime.parse("05/25/1977"), + tempVar), Map.entry(LocalDateTime.parse("08/13/1982"), tempVar2), + Map.entry(LocalDateTime.parse("01/31/1997"), tempVar3))); + + // ReSharper restore StringLiteralTypo + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteMovie(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Movie t2 = this.ReadMovie(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert t1 == t2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void FindAndDelete() + public void FindAndDelete() { + RowBuffer row = new RowBuffer(TypedMapUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + + ArrayList expected = new ArrayList(Arrays.asList("Mark", "Harrison", "Carrie")); + + for (java.lang.Iterable permutation : expected.Permute()) { + Movie t1 = new Movie(); + t1.Cast = new HashMap(Map.ofEntries(Map.entry("Mark", "Luke"), Map.entry("Harrison", "Han" + ), Map.entry("Carrie", "Leia"))); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + this.WriteMovie(tempReference_row2, root.Clone(out _), t1); + row = tempReference_row2.get(); + + // Attempt to find each item in turn and then delete it. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("cast", out c); + Reference tempReference_row3 = + new Reference(row); + RowCursor mapScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out mapScope).Find(tempReference_row3, c.Path); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row4, ref mapScope, out mapScope)); + row = tempReference_row4.get(); + for (String key : permutation) { + KeyValuePair pair = new KeyValuePair(key, "map lookup matches only on" + + " key"); + Reference tempReference_row5 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row5, Utf8String.Empty); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row6, tempReference_tempCursor, c.TypeArgs, + pair)); + tempCursor = tempReference_tempCursor.get(); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + RowCursor findScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row7, ref mapScope, ref tempCursor, + out findScope)); + row = tempReference_row7.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + TypeArgument tupleType = c.typeAs().FieldType(ref mapScope); + Reference tempReference_row8 = + new Reference(row); + Reference tempReference_findScope = + new Reference(findScope); + ResultAssert.IsSuccess(tupleType.TypeAs().DeleteScope(tempReference_row8, + tempReference_findScope)); + findScope = tempReference_findScope.get(); + row = tempReference_row8.get(); + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void FindInMap() + public void FindInMap() { + RowBuffer row = new RowBuffer(TypedMapUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + + Movie t1 = new Movie(); + t1.Cast = new HashMap(Map.ofEntries(Map.entry("Mark", "Luke"), Map.entry("Harrison", "Han"), + Map.entry("Carrie", "Leia"))); + Reference tempReference_row2 = + new Reference(row); + RowCursor rc1 = RowCursor.create(tempReference_row2); + row = tempReference_row2.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_rc1 = + new Reference(rc1); + this.WriteMovie(tempReference_row3, tempReference_rc1, t1); + rc1 = tempReference_rc1.get(); + row = tempReference_row3.get(); + + // Attempt to find each item in turn. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("cast", out c); + Reference tempReference_row4 = + new Reference(row); + RowCursor mapScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out mapScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row5, ref mapScope, out mapScope)); + row = tempReference_row5.get(); + for (String key : t1.Cast.keySet()) { + KeyValuePair pair = new KeyValuePair(key, "map lookup matches only on key"); + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row7, tempReference_tempCursor, c.TypeArgs, pair)); + tempCursor = tempReference_tempCursor.get(); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + RowCursor findScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row8, ref mapScope, ref tempCursor, + out findScope)); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + Reference tempReference_findScope = + new Reference(findScope); + KeyValuePair foundPair; + Out> tempOut_foundPair = + new Out>(); + ResultAssert.IsSuccess(TypedMapUnitTests.ReadKeyValue(tempReference_row9, tempReference_findScope, c.TypeArgs, + tempOut_foundPair)); + foundPair = tempOut_foundPair.get(); + findScope = tempReference_findScope.get(); + row = tempReference_row9.get(); + Assert.AreEqual(key, foundPair.Key, String.format("Failed to find t1.Cast[%1$s]", key)); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString(TypedMapUnitTests.SchemaFile); + this.counterSchema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.counterSchema); + this.layout = this.resolver.Resolve(tangible.ListHelper.find(this.counterSchema.getSchemas(), + x -> x.Name.equals("Movie")).SchemaId); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void PreventUniquenessViolations() + public void PreventUniquenessViolations() { + RowBuffer row = new RowBuffer(TypedMapUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + + Movie t1 = new Movie(); + t1.Cast = new HashMap(Map.ofEntries(Map.entry("Mark", "Luke"))); + t1.Stats = new HashMap(Map.ofEntries(Map.entry(UUID.fromString("{4674962B-CE11-4916-81C5" + + "-0421EE36F168}"), 11000000.00))); + t1.Related = new HashMap>(Map.ofEntries(Map.entry("Mark", new HashMap(Map.ofEntries(Map.entry(103359, "Joker")))))); + Earnings tempVar = new Earnings(); + tempVar.Domestic = new BigDecimal(307263857); + tempVar.Worldwide = new BigDecimal(100000); + t1.Revenue = new HashMap(Map.ofEntries(Map.entry(LocalDateTime.parse("05/25/1977"), + tempVar))); + + Reference tempReference_row2 = + new Reference(row); + RowCursor rc1 = RowCursor.create(tempReference_row2); + row = tempReference_row2.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_rc1 = + new Reference(rc1); + this.WriteMovie(tempReference_row3, tempReference_rc1, t1); + rc1 = tempReference_rc1.get(); + row = tempReference_row3.get(); + + // Attempt to insert duplicate items in existing sets. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("cast", out c); + Reference tempReference_row4 = + new Reference(row); + RowCursor mapScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out mapScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row5, ref mapScope, out mapScope)); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row7, tempReference_tempCursor, c.TypeArgs, + KeyValuePair.Create("Mark", "Luke"))); + tempCursor = tempReference_tempCursor.get(); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row8, ref mapScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row9, Utf8String.Empty); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + Reference tempReference_tempCursor2 = + new Reference(tempCursor); + KeyValuePair _; + Out> tempOut__ = new Out>(); + ResultAssert.NotFound(TypedMapUnitTests.ReadKeyValue(tempReference_row10, tempReference_tempCursor2, c.TypeArgs, + tempOut__)); + _ = tempOut__.get(); + tempCursor = tempReference_tempCursor2.get(); + row = tempReference_row10.get(); + Reference tempReference_row11 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row11, Utf8String.Empty); + row = tempReference_row11.get(); + Reference tempReference_row12 = + new Reference(row); + Reference tempReference_tempCursor3 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row12, tempReference_tempCursor3, c.TypeArgs, + KeyValuePair.Create("Mark", "Joker"))); + tempCursor = tempReference_tempCursor3.get(); + row = tempReference_row12.get(); + Reference tempReference_row13 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row13, ref mapScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row14, Utf8String.Empty); + row = tempReference_row14.get(); + Reference tempReference_row15 = + new Reference(row); + Reference tempReference_tempCursor4 = + new Reference(tempCursor); + KeyValuePair _; + Out> tempOut__2 = + new Out>(); + ResultAssert.NotFound(TypedMapUnitTests.ReadKeyValue(tempReference_row15, tempReference_tempCursor4, c.TypeArgs, + tempOut__2)); + _ = tempOut__2.get(); + tempCursor = tempReference_tempCursor4.get(); + row = tempReference_row15.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("stats", out c); + Reference tempReference_row16 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out mapScope).Find(tempReference_row16, c.Path); + row = tempReference_row16.get(); + Reference tempReference_row17 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row17, ref mapScope, out mapScope)); + row = tempReference_row17.get(); + KeyValuePair pair = KeyValuePair.Create(UUID.fromString("{4674962B-CE11-4916-81C5-0421EE36F168" + + "}"), 11000000.00); + Reference tempReference_row18 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row18, Utf8String.Empty); + row = tempReference_row18.get(); + Reference tempReference_row19 = + new Reference(row); + Reference tempReference_tempCursor5 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row19, tempReference_tempCursor5, c.TypeArgs, pair)); + tempCursor = tempReference_tempCursor5.get(); + row = tempReference_row19.get(); + Reference tempReference_row20 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row20, ref mapScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row20.get(); + Reference tempReference_row21 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row21, Utf8String.Empty); + row = tempReference_row21.get(); + Reference tempReference_row22 = + new Reference(row); + Reference tempReference_tempCursor6 = + new Reference(tempCursor); + Out> tempOut_pair = new Out>(); + ResultAssert.NotFound(TypedMapUnitTests.ReadKeyValue(tempReference_row22, tempReference_tempCursor6, c.TypeArgs, + tempOut_pair)); + pair = tempOut_pair.get(); + tempCursor = tempReference_tempCursor6.get(); + row = tempReference_row22.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void PreventUpdatesInNonUpdatableScope() + public void PreventUpdatesInNonUpdatableScope() { + RowBuffer row = new RowBuffer(TypedMapUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + + // Write a map and then try to write directly into it. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("cast", out c); + Reference tempReference_row2 = + new Reference(row); + RowCursor mapScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out mapScope).Find(tempReference_row2, c.Path); + row = tempReference_row2.get(); + Reference tempReference_row3 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(tempReference_row3, ref mapScope, c.TypeArgs, + out mapScope)); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + Reference tempReference_mapScope = + new Reference(mapScope); + ResultAssert.InsufficientPermissions(TypedMapUnitTests.WriteKeyValue(tempReference_row4, tempReference_mapScope, + c.TypeArgs, KeyValuePair.Create("Mark", "Joker"))); + mapScope = tempReference_mapScope.get(); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row5, "cast.0"); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row6, tempReference_tempCursor, c.TypeArgs, + KeyValuePair.Create("Mark", "Joker"))); + tempCursor = tempReference_tempCursor.get(); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row7, ref mapScope, ref tempCursor)); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row8, "cast.0"); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + Reference tempReference_tempCursor2 = + new Reference(tempCursor); + KeyValuePair _; + Out> tempOut__ = new Out>(); + ResultAssert.NotFound(TypedMapUnitTests.ReadKeyValue(tempReference_row9, tempReference_tempCursor2, c.TypeArgs, tempOut__)); + _ = tempOut__.get(); + tempCursor = tempReference_tempCursor2.get(); + row = tempReference_row9.get(); + + // Write a map of maps, successfully insert an empty map into it, and then try to write directly to the inner + // map. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("related", out c); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out mapScope).Find(tempReference_row10, c.Path); + row = tempReference_row10.get(); + Reference tempReference_row11 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(tempReference_row11, ref mapScope, c.TypeArgs, + out mapScope)); + row = tempReference_row11.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + LayoutIndexedScope tupleLayout = + c.typeAs().FieldType(ref mapScope).TypeAs(); + Reference tempReference_row12 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row12, "related.0"); + row = tempReference_row12.get(); + Reference tempReference_row13 = + new Reference(row); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(tupleLayout.WriteScope(tempReference_row13, ref tempCursor, c.TypeArgs, out tupleScope)); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row14, ref tupleScope, + "Mark")); + row = tempReference_row14.get(); + Reference tempReference_row15 = + new Reference(row); + assert tupleScope.MoveNext(tempReference_row15); + row = tempReference_row15.get(); + TypeArgument valueType = c.TypeArgs[1]; + LayoutUniqueScope valueLayout = valueType.getType().TypeAs(); + Reference tempReference_row16 = + new Reference(row); + RowCursor innerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(valueLayout.WriteScope(tempReference_row16, ref tupleScope, valueType.getTypeArgs().clone(), + out innerScope)); + row = tempReference_row16.get(); + Reference tempReference_row17 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row17, ref mapScope, ref tempCursor)); + row = tempReference_row17.get(); + Reference tempReference_row18 = + new Reference(row); + assert mapScope.MoveNext(tempReference_row18); + row = tempReference_row18.get(); + Reference tempReference_row19 = + new Reference(row); + Reference tempReference_mapScope2 = + new Reference(mapScope); + Out tempOut_tupleScope = + new Out(); + ResultAssert.IsSuccess(tupleLayout.ReadScope(tempReference_row19, tempReference_mapScope2, tempOut_tupleScope)); + tupleScope = tempOut_tupleScope.get(); + mapScope = tempReference_mapScope2.get(); + row = tempReference_row19.get(); + Reference tempReference_row20 = + new Reference(row); + assert tupleScope.MoveNext(tempReference_row20); + row = tempReference_row20.get(); + + // Skip key. + Reference tempReference_row21 = + new Reference(row); + assert tupleScope.MoveNext(tempReference_row21); + row = tempReference_row21.get(); + Reference tempReference_row22 = + new Reference(row); + Reference tempReference_tupleScope = + new Reference(tupleScope); + Out tempOut_innerScope = + new Out(); + ResultAssert.IsSuccess(valueLayout.ReadScope(tempReference_row22, tempReference_tupleScope, tempOut_innerScope)); + innerScope = tempOut_innerScope.get(); + tupleScope = tempReference_tupleScope.get(); + row = tempReference_row22.get(); + TypeArgument itemType = valueType.getTypeArgs().get(0).clone(); + Reference tempReference_row23 = + new Reference(row); + assert !innerScope.MoveNext(tempReference_row23); + row = tempReference_row23.get(); + Reference tempReference_row24 = + new Reference(row); + Reference tempReference_innerScope = + new Reference(innerScope); + ResultAssert.InsufficientPermissions(itemType.getType().TypeAs().WriteSparse(tempReference_row24, + tempReference_innerScope, 1)); + innerScope = tempReference_innerScope.get(); + row = tempReference_row24.get(); + Reference tempReference_row25 = + new Reference(row); + Reference tempReference_innerScope2 = + new Reference(innerScope); + ResultAssert.InsufficientPermissions(itemType.getType().TypeAs().DeleteSparse(tempReference_row25, + tempReference_innerScope2)); + innerScope = tempReference_innerScope2.get(); + row = tempReference_row25.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void UpdateInMap() + public void UpdateInMap() { + RowBuffer row = new RowBuffer(TypedMapUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row); + row = tempReference_row.get(); + + ArrayList expected = new ArrayList(Arrays.asList("Mark", "Harrison", "Carrie")); + + for (java.lang.Iterable permutation : expected.Permute()) { + Movie t1 = new Movie(); + t1.Cast = new HashMap(Map.ofEntries(Map.entry("Mark", "Luke"), Map.entry("Harrison", "Han" + ), Map.entry("Carrie", "Leia"))); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + this.WriteMovie(tempReference_row2, root.Clone(out _), t1); + row = tempReference_row2.get(); + + // Attempt to find each item in turn and then delete it. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("cast", out c); + Reference tempReference_row3 = + new Reference(row); + RowCursor mapScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out mapScope).Find(tempReference_row3, c.Path); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row4, ref mapScope, out mapScope)); + row = tempReference_row4.get(); + for (String key : permutation) { + // Verify it is already there. + KeyValuePair pair = new KeyValuePair(key, "map lookup matches only on" + + " key"); + Reference tempReference_row5 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row5, Utf8String.Empty); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row6, tempReference_tempCursor, c.TypeArgs, + pair)); + tempCursor = tempReference_tempCursor.get(); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + RowCursor findScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row7, ref mapScope, ref tempCursor, + out findScope)); + row = tempReference_row7.get(); + + // Insert it again with update. + KeyValuePair updatePair = new KeyValuePair(key, "update value"); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row8, Utf8String.Empty); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + Reference tempReference_tempCursor2 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row9, tempReference_tempCursor2, c.TypeArgs, + updatePair)); + tempCursor = tempReference_tempCursor2.get(); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row10, ref mapScope, + ref tempCursor, UpdateOptions.Update)); + row = tempReference_row10.get(); + + // Verify that the value was updated. + Reference tempReference_row11 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row11, Utf8String.Empty); + row = tempReference_row11.get(); + Reference tempReference_row12 = + new Reference(row); + Reference tempReference_tempCursor3 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row12, tempReference_tempCursor3, c.TypeArgs + , pair)); + tempCursor = tempReference_tempCursor3.get(); + row = tempReference_row12.get(); + Reference tempReference_row13 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row13, ref mapScope, ref tempCursor + , out findScope)); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + Reference tempReference_findScope = + new Reference(findScope); + KeyValuePair foundPair; + Out> tempOut_foundPair = + new Out>(); + ResultAssert.IsSuccess(TypedMapUnitTests.ReadKeyValue(tempReference_row14, tempReference_findScope, c.TypeArgs, + tempOut_foundPair)); + foundPair = tempOut_foundPair.get(); + findScope = tempReference_findScope.get(); + row = tempReference_row14.get(); + assert key == foundPair.Key; + assert updatePair.Value == foundPair.Value; + + // Insert it again with upsert. + updatePair = new KeyValuePair(key, "upsert value"); + Reference tempReference_row15 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row15, Utf8String.Empty); + row = tempReference_row15.get(); + Reference tempReference_row16 = + new Reference(row); + Reference tempReference_tempCursor4 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row16, tempReference_tempCursor4, c.TypeArgs + , updatePair)); + tempCursor = tempReference_tempCursor4.get(); + row = tempReference_row16.get(); + + // ReSharper disable once RedundantArgumentDefaultValue + Reference tempReference_row17 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row17, ref mapScope, + ref tempCursor, UpdateOptions.Upsert)); + row = tempReference_row17.get(); + + // Verify that the value was upserted. + Reference tempReference_row18 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row18, Utf8String.Empty); + row = tempReference_row18.get(); + Reference tempReference_row19 = + new Reference(row); + Reference tempReference_tempCursor5 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row19, tempReference_tempCursor5, c.TypeArgs + , pair)); + tempCursor = tempReference_tempCursor5.get(); + row = tempReference_row19.get(); + Reference tempReference_row20 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row20, ref mapScope, ref tempCursor + , out findScope)); + row = tempReference_row20.get(); + Reference tempReference_row21 = + new Reference(row); + Reference tempReference_findScope2 = + new Reference(findScope); + Out> tempOut_foundPair2 = + new Out>(); + ResultAssert.IsSuccess(TypedMapUnitTests.ReadKeyValue(tempReference_row21, tempReference_findScope2, c.TypeArgs, + tempOut_foundPair2)); + foundPair = tempOut_foundPair2.get(); + findScope = tempReference_findScope2.get(); + row = tempReference_row21.get(); + assert key == foundPair.Key; + assert updatePair.Value == foundPair.Value; + + // Insert it again with insert (fail: exists). + updatePair = new KeyValuePair(key, "insert value"); + Reference tempReference_row22 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row22, Utf8String.Empty); + row = tempReference_row22.get(); + Reference tempReference_row23 = + new Reference(row); + Reference tempReference_tempCursor6 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row23, tempReference_tempCursor6, c.TypeArgs + , updatePair)); + tempCursor = tempReference_tempCursor6.get(); + row = tempReference_row23.get(); + Reference tempReference_row24 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row24, ref mapScope, + ref tempCursor, UpdateOptions.Insert)); + row = tempReference_row24.get(); + + // Insert it again with insert at (fail: disallowed). + updatePair = new KeyValuePair(key, "insertAt value"); + Reference tempReference_row25 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row25, Utf8String.Empty); + row = tempReference_row25.get(); + Reference tempReference_row26 = + new Reference(row); + Reference tempReference_tempCursor7 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(tempReference_row26, tempReference_tempCursor7, c.TypeArgs + , updatePair)); + tempCursor = tempReference_tempCursor7.get(); + row = tempReference_row26.get(); + Reference tempReference_row27 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.TypeConstraint(c.typeAs().MoveField(tempReference_row27, ref mapScope, + ref tempCursor, UpdateOptions.InsertAt)); + row = tempReference_row27.get(); + } + } + } + + private static Earnings ReadEarnings(Reference row, Reference udtScope) { + Layout udt = udtScope.get().getLayout(); + Earnings m = new Earnings(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert udt.TryFind("domestic", out c); + Out tempOut_Domestic = new Out(); + ResultAssert.IsSuccess(c.typeAs().ReadFixed(row, udtScope, c, tempOut_Domestic)); + m.Domestic = tempOut_Domestic.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert udt.TryFind("worldwide", out c); + Out tempOut_Worldwide = new Out(); + ResultAssert.IsSuccess(c.typeAs().ReadFixed(row, udtScope, c, tempOut_Worldwide)); + m.Worldwide = tempOut_Worldwide.get(); + return m; + } + + private static Result ReadKeyValue(Reference row, + Reference scope, TypeArgumentList typeArgs, + Out> pair) { + pair.setAndGet(null); + LayoutIndexedScope tupleLayout = LayoutType.TypedTuple; + RowCursor tupleScope; + Out tempOut_tupleScope = + new Out(); + Result r = tupleLayout.ReadScope(row, scope, tempOut_tupleScope); + tupleScope = tempOut_tupleScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + tupleScope.MoveNext(row); + Reference tempReference_tupleScope = + new Reference(tupleScope); + TKey key; + Out tempOut_key = new Out(); + r = typeArgs.get(0).getType().>TypeAs().ReadSparse(row, tempReference_tupleScope, tempOut_key); + key = tempOut_key.get(); + tupleScope = tempReference_tupleScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + tupleScope.MoveNext(row); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + TValue value; + Out tempOut_value = new Out(); + r = typeArgs.get(1).getType().>TypeAs().ReadSparse(row, tempReference_tupleScope2, tempOut_value); + value = tempOut_value.get(); + tupleScope = tempReference_tupleScope2.get(); + if (r != Result.SUCCESS) { + return r; + } + + pair.setAndGet(new KeyValuePair(key, value)); + return Result.SUCCESS; + } + + private Movie ReadMovie(Reference row, Reference root) { + Movie value = new Movie(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("cast", out c); + RowCursor castScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out castScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref castScope, out castScope) == Result.SUCCESS) { + value.Cast = new HashMap(); + while (castScope.MoveNext(row)) { + Reference tempReference_castScope = + new Reference(castScope); + KeyValuePair item; + Out> tempOut_item = + new Out>(); + ResultAssert.IsSuccess(TypedMapUnitTests.ReadKeyValue(row, tempReference_castScope, c.TypeArgs, + tempOut_item)); + item = tempOut_item.get(); + castScope = tempReference_castScope.get(); + value.Cast.put(item.Key, item.Value); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("stats", out c); + RowCursor statsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out statsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref statsScope, out statsScope) == Result.SUCCESS) { + value.Stats = new HashMap(); + while (statsScope.MoveNext(row)) { + Reference tempReference_statsScope = + new Reference(statsScope); + KeyValuePair item; + Out> tempOut_item2 = + new Out>(); + ResultAssert.IsSuccess(TypedMapUnitTests.ReadKeyValue(row, tempReference_statsScope, c.TypeArgs, + tempOut_item2)); + item = tempOut_item2.get(); + statsScope = tempReference_statsScope.get(); + value.Stats.put(item.Key, item.Value); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("related", out c); + RowCursor relatedScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out relatedScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref relatedScope, out relatedScope) == Result.SUCCESS) { + value.Related = new HashMap>(); + TypeArgument keyType = c.TypeArgs[0]; + TypeArgument valueType = c.TypeArgs[1]; + LayoutUtf8 keyLayout = keyType.getType().TypeAs(); + LayoutUniqueScope valueLayout = valueType.getType().TypeAs(); + while (relatedScope.MoveNext(row)) { + LayoutIndexedScope tupleLayout = LayoutType.TypedTuple; + Reference tempReference_relatedScope = + new Reference(relatedScope); + RowCursor tupleScope; + Out tempOut_tupleScope = + new Out(); + ResultAssert.IsSuccess(tupleLayout.ReadScope(row, tempReference_relatedScope, tempOut_tupleScope)); + tupleScope = tempOut_tupleScope.get(); + relatedScope = tempReference_relatedScope.get(); + assert tupleScope.MoveNext(row); + String itemKey; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(keyLayout.ReadSparse(row, ref tupleScope, out itemKey)); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope = + new Reference(tupleScope); + RowCursor itemValueScope; + Out tempOut_itemValueScope = + new Out(); + ResultAssert.IsSuccess(valueLayout.ReadScope(row, tempReference_tupleScope, tempOut_itemValueScope)); + itemValueScope = tempOut_itemValueScope.get(); + tupleScope = tempReference_tupleScope.get(); + HashMap itemValue = new HashMap(); + while (itemValueScope.MoveNext(row)) { + Reference tempReference_itemValueScope = new Reference(itemValueScope); + KeyValuePair innerItem; + Out> tempOut_innerItem = + new Out>(); + ResultAssert.IsSuccess(TypedMapUnitTests.ReadKeyValue(row, tempReference_itemValueScope, + valueType.getTypeArgs().clone(), tempOut_innerItem)); + innerItem = tempOut_innerItem.get(); + itemValueScope = tempReference_itemValueScope.get(); + itemValue.put(innerItem.Key, innerItem.Value); + } + + value.Related.put(itemKey, itemValue); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("revenue", out c); + RowCursor revenueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out revenueScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref revenueScope, out revenueScope) == Result.SUCCESS) { + value.Revenue = new HashMap(); + TypeArgument keyType = c.TypeArgs[0]; + TypeArgument valueType = c.TypeArgs[1]; + LayoutDateTime keyLayout = keyType.getType().TypeAs(); + LayoutUDT valueLayout = valueType.getType().TypeAs(); + while (revenueScope.MoveNext(row)) { + LayoutIndexedScope tupleLayout = LayoutType.TypedTuple; + Reference tempReference_revenueScope = + new Reference(revenueScope); + RowCursor tupleScope; + Out tempOut_tupleScope2 = + new Out(); + ResultAssert.IsSuccess(tupleLayout.ReadScope(row, tempReference_revenueScope, tempOut_tupleScope2)); + tupleScope = tempOut_tupleScope2.get(); + revenueScope = tempReference_revenueScope.get(); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope2 = new Reference(tupleScope); + java.time.LocalDateTime itemKey; + Out tempOut_itemKey = new Out(); + ResultAssert.IsSuccess(keyLayout.ReadSparse(row, tempReference_tupleScope2, tempOut_itemKey)); + itemKey = tempOut_itemKey.get(); + tupleScope = tempReference_tupleScope2.get(); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope3 = new Reference(tupleScope); + RowCursor itemValueScope; + Out tempOut_itemValueScope2 = new Out(); + ResultAssert.IsSuccess(valueLayout.ReadScope(row, tempReference_tupleScope3, tempOut_itemValueScope2)); + itemValueScope = tempOut_itemValueScope2.get(); + tupleScope = tempReference_tupleScope3.get(); + Reference tempReference_itemValueScope2 = new Reference(itemValueScope); + Earnings itemValue = TypedMapUnitTests.ReadEarnings(row, tempReference_itemValueScope2); + itemValueScope = tempReference_itemValueScope2.get(); + + value.Revenue.put(itemKey, itemValue); + } + } + + return value; + } + + private static void WriteEarnings(Reference row, Reference udtScope, TypeArgumentList typeArgs, Earnings m) { + Layout udt = row.get().resolver().resolve(typeArgs.getSchemaId().clone()); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert udt.TryFind("domestic", out c); + ResultAssert.IsSuccess(c.typeAs().WriteFixed(row, udtScope, c, m.Domestic)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert udt.TryFind("worldwide", out c); + ResultAssert.IsSuccess(c.typeAs().WriteFixed(row, udtScope, c, m.Worldwide)); + } + + private static Result WriteKeyValue(Reference row, + Reference scope, TypeArgumentList typeArgs, KeyValuePair pair) { + LayoutIndexedScope tupleLayout = LayoutType.TypedTuple; + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Result r = tupleLayout.WriteScope(row, scope, typeArgs.clone(), out tupleScope); + if (r != Result.SUCCESS) { + return r; + } + + Reference tempReference_tupleScope = + new Reference(tupleScope); + r = typeArgs.get(0).getType().>TypeAs().WriteSparse(row, tempReference_tupleScope, pair.Key); + tupleScope = tempReference_tupleScope.get(); + if (r != Result.SUCCESS) { + return r; + } + + tupleScope.MoveNext(row); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + r = typeArgs.get(1).getType().>TypeAs().WriteSparse(row, tempReference_tupleScope2, pair.Value); + tupleScope = tempReference_tupleScope2.get(); + return r; + } + + private void WriteMovie(Reference row, Reference root, Movie value) { + LayoutColumn c; + + if (value.Cast != null) { + Out tempOut_c = + new Out(); + assert this.layout.TryFind("cast", tempOut_c); + c = tempOut_c.get(); + RowCursor castScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out castScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref castScope, + c.typeArgs().clone(), out castScope)); + for (KeyValuePair item : value.Cast) { + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(row, tempReference_tempCursor, + c.typeArgs().clone(), item)); + tempCursor = tempReference_tempCursor.get(); + Reference tempReference_castScope = + new Reference(castScope); + Reference tempReference_tempCursor2 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_castScope, + tempReference_tempCursor2)); + tempCursor = tempReference_tempCursor2.get(); + castScope = tempReference_castScope.get(); + } + } + + if (value.Stats != null) { + Out tempOut_c2 = + new Out(); + assert this.layout.TryFind("stats", tempOut_c2); + c = tempOut_c2.get(); + RowCursor statsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out statsScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref statsScope, + c.typeArgs().clone(), out statsScope)); + for (KeyValuePair item : value.Stats) { + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + Reference tempReference_tempCursor3 = + new Reference(tempCursor); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(row, tempReference_tempCursor3, + c.typeArgs().clone(), item)); + tempCursor = tempReference_tempCursor3.get(); + Reference tempReference_statsScope = + new Reference(statsScope); + Reference tempReference_tempCursor4 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_statsScope, + tempReference_tempCursor4)); + tempCursor = tempReference_tempCursor4.get(); + statsScope = tempReference_statsScope.get(); + } + } + + if (value.Related != null) { + Out tempOut_c3 = + new Out(); + assert this.layout.TryFind("related", tempOut_c3); + c = tempOut_c3.get(); + RowCursor relatedScoped; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out relatedScoped).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref relatedScoped, + c.typeArgs().clone(), out relatedScoped)); + for (KeyValuePair> item : value.Related) { + assert item.Value != null; + + LayoutIndexedScope tupleLayout = LayoutType.TypedTuple; + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor1).Find(row, "related.0"); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(tupleLayout.WriteScope(row, ref tempCursor1, c.typeArgs().clone(), + out tupleScope)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeArgs().get(0).type().typeAs().WriteSparse(row, + ref tupleScope, item.Key)); + assert tupleScope.MoveNext(row); + TypeArgument valueType = c.typeArgs().get(1).clone(); + LayoutUniqueScope valueLayout = valueType.getType().TypeAs(); + RowCursor innerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(valueLayout.WriteScope(row, ref tupleScope, valueType.getTypeArgs().clone(), + out innerScope)); + for (KeyValuePair innerItem : item.Value) { + RowCursor tempCursor2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword + // - these cannot be converted using the 'Out' helper class unless the method is within the + // code being modified: + root.get().Clone(out tempCursor2).Find(row, "related.0.0"); + Reference tempReference_tempCursor2 + = new Reference(tempCursor2); + ResultAssert.IsSuccess(TypedMapUnitTests.WriteKeyValue(row, tempReference_tempCursor2, + valueType.getTypeArgs().clone(), innerItem)); + tempCursor2 = tempReference_tempCursor2.get(); + Reference tempReference_innerScope = + new Reference(innerScope); + Reference tempReference_tempCursor22 = new Reference(tempCursor2); + ResultAssert.IsSuccess(valueLayout.MoveField(row, tempReference_innerScope, + tempReference_tempCursor22)); + tempCursor2 = tempReference_tempCursor22.get(); + innerScope = tempReference_innerScope.get(); + } + + Reference tempReference_relatedScoped = + new Reference(relatedScoped); + Reference tempReference_tempCursor1 = + new Reference(tempCursor1); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_relatedScoped, + tempReference_tempCursor1)); + tempCursor1 = tempReference_tempCursor1.get(); + relatedScoped = tempReference_relatedScoped.get(); + } + } + + if (value.Revenue != null) { + Out tempOut_c4 = + new Out(); + assert this.layout.TryFind("revenue", tempOut_c4); + c = tempOut_c4.get(); + RowCursor revenueScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out revenueScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref revenueScope, + c.typeArgs().clone(), out revenueScope)); + for (KeyValuePair item : value.Revenue) { + assert item.Value != null; + + LayoutIndexedScope tupleLayout = LayoutType.TypedTuple; + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor1).Find(row, "revenue.0"); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(tupleLayout.WriteScope(row, ref tempCursor1, c.typeArgs().clone(), + out tupleScope)); + Reference tempReference_tupleScope = + new Reference(tupleScope); + ResultAssert.IsSuccess(c.typeArgs().get(0).type().typeAs().WriteSparse(row, + tempReference_tupleScope, item.Key)); + tupleScope = tempReference_tupleScope.get(); + assert tupleScope.MoveNext(row); + TypeArgument valueType = c.typeArgs().get(1).clone(); + LayoutUDT valueLayout = valueType.getType().TypeAs(); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + RowCursor itemScope; + Out tempOut_itemScope = + new Out(); + ResultAssert.IsSuccess(valueLayout.WriteScope(row, tempReference_tupleScope2, + valueType.getTypeArgs().clone(), tempOut_itemScope)); + itemScope = tempOut_itemScope.get(); + tupleScope = tempReference_tupleScope2.get(); + Reference tempReference_itemScope = + new Reference(itemScope); + TypedMapUnitTests.WriteEarnings(row, tempReference_itemScope, valueType.getTypeArgs().clone(), item.Value); + itemScope = tempReference_itemScope.get(); + + Reference tempReference_revenueScope = + new Reference(revenueScope); + Reference tempReference_tempCursor12 = + new Reference(tempCursor1); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_revenueScope, + tempReference_tempCursor12)); + tempCursor1 = tempReference_tempCursor12.get(); + revenueScope = tempReference_revenueScope.get(); + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class Earnings + private final static class Earnings { + public BigDecimal Domestic = new BigDecimal(0); + public BigDecimal Worldwide = new BigDecimal(0); + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Earnings; + Earnings earnings = tempVar ? (Earnings)obj : null; + return tempVar && this.equals(earnings); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + return (this.Domestic.hashCode() * 397) ^ this.Worldwide.hashCode(); + } + } + + private boolean equals(Earnings other) { + return this.Domestic.compareTo(other.Domestic) == 0 && this.Worldwide.compareTo(other.Worldwide) == 0; + } + } + + private static class KeyValuePair { + public static KeyValuePair Create(TKey key, TValue value) { + return new KeyValuePair(key, value); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class Movie + private final static class Movie { + public HashMap Cast; + public HashMap> Related; + public HashMap Revenue; + public HashMap Stats; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Movie; + Movie movie = tempVar ? (Movie)obj : null; + return tempVar && this.equals(movie); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = 0; + hashCode = (hashCode * 397) ^ (this.Cast == null ? null : this.Cast.hashCode() != null ? this.Cast.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Stats == null ? null : this.Stats.hashCode() != null ? this.Stats.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Related == null ? null : this.Related.hashCode() != null ? this.Related.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Revenue == null ? null : this.Revenue.hashCode() != null ? this.Revenue.hashCode() : 0); + return hashCode; + } + } + + private static boolean MapEquals(HashMap left, HashMap right) { + if (left.size() != right.size()) { + return false; + } + + for (KeyValuePair item : left) { + TValue value; + if (!(right.containsKey(item.Key) && (value = right.get(item.Key)) == value)) { + return false; + } + + if (!item.Value.equals(value)) { + return false; + } + } + + return true; + } + + private static boolean NestedMapEquals(HashMap> left, HashMap> right) { + if (left.size() != right.size()) { + return false; + } + + for (KeyValuePair> item : left) { + java.util.HashMap value; + if (!(right.containsKey(item.Key) && (value = right.get(item.Key)) == value)) { + return false; + } + + if (!Movie.MapEquals(item.Value, value)) { + return false; + } + } + + return true; + } + + private boolean equals(Movie other) { + return (this.Cast == other.Cast || ((this.Cast != null) && (other.Cast != null) && Movie.MapEquals(this.Cast, other.Cast))) && (this.Stats == other.Stats || ((this.Stats != null) && (other.Stats != null) && Movie.MapEquals(this.Stats, other.Stats))) && (this.Related == other.Related || ((this.Related != null) && (other.Related != null) && Movie.NestedMapEquals(this.Related, other.Related))) && (this.Revenue == other.Revenue || ((this.Revenue != null) && (other.Revenue != null) && Movie.MapEquals(this.Revenue, other.Revenue))); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedSetUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedSetUnitTests.java new file mode 100644 index 0000000..6f2bd68 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/TypedSetUnitTests.java @@ -0,0 +1,1995 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; + +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass][DeploymentItem(TypedSetUnitTests.SchemaFile, "TestData")] public sealed class +// TypedSetUnitTests +public final class TypedSetUnitTests { + private static final int InitialRowSize = 2 * 1024 * 1024; + private static final String SchemaFile = "TestData\\TodoSchema.json"; + private Namespace counterSchema; + private Layout layout; + private LayoutResolver resolver; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void CreateTodos() + public void CreateTodos() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + Todo t1 = new Todo(); + t1.Attendees = new ArrayList(Arrays.asList("jason", "janice", "joshua")); + t1.Projects = new ArrayList(Arrays.asList(UUID.fromString("{4674962B-CE11-4916-81C5-0421EE36F168}"), + UUID.fromString("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), UUID.fromString("{B7BC39C2-1A2D-4EAF-8F33" + + "-ED976872D876}"), UUID.fromString("{DEA71ABE-3041-4CAF-BBD9-1A46D10832A0}"))); + t1.Checkboxes = new ArrayList(Arrays.asList(true, false)); + t1.Prices = new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(1.2F, 3.0F)), + new ArrayList(Arrays.asList(4.1F, 5.7F)), new ArrayList(Arrays.asList(7.3F, 8.12F, 9.14F)))); + t1.Nested = + new ArrayList>>(Arrays.asList(new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(1, 2)))), new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(3, 4)))), new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(5, 6)))))); + ShoppingItem tempVar = new ShoppingItem(); + tempVar.Label = "milk"; + tempVar.Count = 1; + ShoppingItem tempVar2 = new ShoppingItem(); + tempVar2.Label = "broccoli"; + tempVar2.Count = 2; + ShoppingItem tempVar3 = new ShoppingItem(); + tempVar3.Label = "steak"; + tempVar3.Count = 6; + t1.Shopping = new ArrayList(Arrays.asList(tempVar, tempVar2, tempVar3)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: t1.Work = new List> { Tuple.Create(false, 10000UL), Tuple.Create(true, + // 49053UL), Tuple.Create(false, 53111UL)}; + t1.Work = new ArrayList>(Arrays.asList(Tuple.Create(false, 10000), Tuple.Create(true, + 49053), Tuple.Create(false, 53111))); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteTodo(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + Reference tempReference_row4 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + Todo t2 = this.ReadTodo(tempReference_row3, RowCursor.create(tempReference_row4, out _)); + row = tempReference_row4.get(); + row = tempReference_row3.get(); + assert t1 == t2; + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void FindAndDelete() + public void FindAndDelete() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + ArrayList expected = new ArrayList(Arrays.asList(UUID.fromString("{4674962B-CE11-4916-81C5" + + "-0421EE36F168}"), UUID.fromString("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), UUID.fromString("{B7BC39C2" + + "-1A2D-4EAF-8F33-ED976872D876}"), UUID.fromString("{DEA71ABE-3041-4CAF-BBD9-1A46D10832A0}"))); + + for (java.lang.Iterable permutation : expected.Permute()) { + Todo t1 = new Todo(); + t1.Projects = new ArrayList(permutation); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + this.WriteTodo(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + // Attempt to update each item in turn and then update it with itself. + Reference tempReference_row3 = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("projects", out c); + Reference tempReference_row4 = + new Reference(row); + RowCursor setScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out setScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row5, ref setScope, out setScope)); + row = tempReference_row5.get(); + for (UUID p : t1.Projects) { + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, + ref tempCursor, p)); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + RowCursor findScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row8, ref setScope, ref tempCursor, + out findScope)); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().DeleteSparse(tempReference_row9, + ref findScope)); + row = tempReference_row9.get(); + } + } + + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void FindInSet() + public void FindInSet() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + Todo t1 = new Todo(); + t1.Attendees = new ArrayList(Arrays.asList("jason", "janice", "joshua")); + t1.Prices = new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(1.2F, 3.0F)), + new ArrayList(Arrays.asList(4.1F, 5.7F)), new ArrayList(Arrays.asList(7.3F, 8.12F, 9.14F)))); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteTodo(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + // Attempt to find each item in turn. + Reference tempReference_row3 = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("attendees", out c); + Reference tempReference_row4 = + new Reference(row); + RowCursor setScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row5, ref setScope, out setScope)); + row = tempReference_row5.get(); + for (int i = 0; i < t1.Attendees.size(); i++) { + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, ref tempCursor, + t1.Attendees.get(i))); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + RowCursor findScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row8, ref setScope, ref tempCursor, + out findScope)); + row = tempReference_row8.get(); + Assert.AreEqual(i, findScope.Index, String.format("Failed to find t1.Attendees[%1$s]", i)); + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("prices", out c); + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row9, c.Path); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row10, ref setScope, out setScope)); + row = tempReference_row10.get(); + TypeArgument innerType = c.TypeArgs[0]; + TypeArgument itemType = innerType.getTypeArgs().get(0).clone(); + LayoutUniqueScope innerLayout = innerType.getType().TypeAs(); + for (int i = 0; i < t1.Prices.size(); i++) { + Reference tempReference_row11 = + new Reference(row); + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out tempCursor1).Find(tempReference_row11, Utf8String.Empty); + row = tempReference_row11.get(); + Reference tempReference_row12 = + new Reference(row); + RowCursor innerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(innerLayout.WriteScope(tempReference_row12, ref tempCursor1, + innerType.getTypeArgs().clone(), out innerScope)); + row = tempReference_row12.get(); + for (int j = 0; j < t1.Prices.get(i).size(); j++) { + Reference tempReference_row13 = + new Reference(row); + RowCursor tempCursor2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor2).Find(tempReference_row13, "prices.0.0"); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + Reference tempReference_tempCursor2 = + new Reference(tempCursor2); + ResultAssert.IsSuccess(itemType.getType().TypeAs().WriteSparse(tempReference_row14, + tempReference_tempCursor2, t1.Prices.get(i).get(j))); + tempCursor2 = tempReference_tempCursor2.get(); + row = tempReference_row14.get(); + Reference tempReference_row15 = + new Reference(row); + Reference tempReference_innerScope = + new Reference(innerScope); + Reference tempReference_tempCursor22 = + new Reference(tempCursor2); + ResultAssert.IsSuccess(innerLayout.MoveField(tempReference_row15, tempReference_innerScope, + tempReference_tempCursor22)); + tempCursor2 = tempReference_tempCursor22.get(); + innerScope = tempReference_innerScope.get(); + row = tempReference_row15.get(); + } + + Reference tempReference_row16 = + new Reference(row); + RowCursor findScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row16, ref setScope, ref tempCursor1, + out findScope)); + row = tempReference_row16.get(); + Assert.AreEqual(i, findScope.Index, String.format("Failed to find t1.Prices[%1$s]", i)); + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestInitialize] public void ParseNamespaceExample() + public void ParseNamespaceExample() { + String json = Files.readString(TypedSetUnitTests.SchemaFile); + this.counterSchema = Namespace.Parse(json); + this.resolver = new LayoutResolverNamespace(this.counterSchema); + this.layout = this.resolver.Resolve(tangible.ListHelper.find(this.counterSchema.getSchemas(), + x -> x.Name.equals("Todo")).SchemaId); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void PreventUniquenessViolations() + public void PreventUniquenessViolations() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + Todo t1 = new Todo(); + t1.Attendees = new ArrayList(Arrays.asList("jason")); + t1.Projects = new ArrayList(Arrays.asList(UUID.fromString("{4674962B-CE11-4916-81C5-0421EE36F168}"))); + t1.Prices = new ArrayList>(Arrays.asList(new ArrayList(Arrays.asList(1.2F, 3.0F)))); + ShoppingItem tempVar = new ShoppingItem(); + tempVar.Label = "milk"; + tempVar.Count = 1; + t1.Shopping = new ArrayList(Arrays.asList(tempVar)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: t1.Work = new List> { Tuple.Create(false, 10000UL)}; + t1.Work = new ArrayList>(Arrays.asList(Tuple.Create(false, 10000))); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + this.WriteTodo(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + // Attempt to insert duplicate items in existing sets. + Reference tempReference_row3 = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("attendees", out c); + Reference tempReference_row4 = + new Reference(row); + RowCursor setScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row5, ref setScope, out setScope)); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, ref tempCursor, + t1.Attendees.get(0))); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row8, ref setScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row9, Utf8String.Empty); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row10, ref tempCursor, + t1.Attendees.get(0))); + row = tempReference_row10.get(); + Reference tempReference_row11 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row11, ref setScope, ref tempCursor, out _)); + row = tempReference_row11.get(); + Reference tempReference_row12 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row12, Utf8String.Empty); + row = tempReference_row12.get(); + Reference tempReference_row13 = + new Reference(row); + String _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.NotFound(c.TypeArgs[0].Type.TypeAs().ReadSparse(tempReference_row13, ref tempCursor, out _)); + row = tempReference_row13.get(); + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("projects", out c); + Reference tempReference_row14 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row14, c.Path); + row = tempReference_row14.get(); + Reference tempReference_row15 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row15, ref setScope, out setScope)); + row = tempReference_row15.get(); + Reference tempReference_row16 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row16, Utf8String.Empty); + row = tempReference_row16.get(); + Reference tempReference_row17 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row17, ref tempCursor, + t1.Projects.get(0))); + row = tempReference_row17.get(); + Reference tempReference_row18 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row18, ref setScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row18.get(); + + // Attempt to move a duplicate set into a set of sets. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("prices", out c); + Reference tempReference_row19 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row19, c.Path); + row = tempReference_row19.get(); + Reference tempReference_row20 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row20, ref setScope, out setScope)); + row = tempReference_row20.get(); + TypeArgument innerType = c.TypeArgs[0]; + LayoutUniqueScope innerLayout = innerType.getType().TypeAs(); + Reference tempReference_row21 = + new Reference(row); + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor1).Find(tempReference_row21, Utf8String.Empty); + row = tempReference_row21.get(); + Reference tempReference_row22 = + new Reference(row); + RowCursor innerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(innerLayout.WriteScope(tempReference_row22, ref tempCursor1, innerType.getTypeArgs().clone() + , out innerScope)); + row = tempReference_row22.get(); + for (float innerItem : t1.Prices.get(0)) { + LayoutFloat32 itemLayout = innerType.getTypeArgs().get(0).getType().TypeAs(); + Reference tempReference_row23 = + new Reference(row); + RowCursor tempCursor2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out tempCursor2).Find(tempReference_row23, "prices.0.0"); + row = tempReference_row23.get(); + Reference tempReference_row24 = + new Reference(row); + Reference tempReference_tempCursor2 = + new Reference(tempCursor2); + ResultAssert.IsSuccess(itemLayout.WriteSparse(tempReference_row24, tempReference_tempCursor2, innerItem)); + tempCursor2 = tempReference_tempCursor2.get(); + row = tempReference_row24.get(); + Reference tempReference_row25 = + new Reference(row); + Reference tempReference_innerScope = + new Reference(innerScope); + Reference tempReference_tempCursor22 = + new Reference(tempCursor2); + ResultAssert.IsSuccess(innerLayout.MoveField(tempReference_row25, tempReference_innerScope, tempReference_tempCursor22)); + tempCursor2 = tempReference_tempCursor22.get(); + innerScope = tempReference_innerScope.get(); + row = tempReference_row25.get(); + } + + Reference tempReference_row26 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row26, ref setScope, ref tempCursor1, + UpdateOptions.Insert)); + row = tempReference_row26.get(); + + // Attempt to move a duplicate UDT into a set of UDT. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("shopping", out c); + Reference tempReference_row27 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row27, c.Path); + row = tempReference_row27.get(); + Reference tempReference_row28 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row28, ref setScope, out setScope)); + row = tempReference_row28.get(); + LayoutUDT udtLayout = c.TypeArgs[0].Type.TypeAs(); + Reference tempReference_row29 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row29, Utf8String.Empty); + row = tempReference_row29.get(); + Reference tempReference_row30 = + new Reference(row); + Reference tempReference_tempCursor = + new Reference(tempCursor); + RowCursor udtScope; + Out tempOut_udtScope = + new Out(); + ResultAssert.IsSuccess(udtLayout.WriteScope(tempReference_row30, tempReference_tempCursor, c.TypeArgs[0].TypeArgs, + tempOut_udtScope)); + udtScope = tempOut_udtScope.get(); + tempCursor = tempReference_tempCursor.get(); + row = tempReference_row30.get(); + Reference tempReference_row31 = + new Reference(row); + Reference tempReference_udtScope = + new Reference(udtScope); + TypedSetUnitTests.WriteShoppingItem(tempReference_row31, tempReference_udtScope, c.TypeArgs[0].TypeArgs, + t1.Shopping.get(0)); + udtScope = tempReference_udtScope.get(); + row = tempReference_row31.get(); + Reference tempReference_row32 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row32, ref setScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row32.get(); + + // Attempt to move a duplicate tuple into a set of tuple. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("work", out c); + Reference tempReference_row33 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out setScope).Find(tempReference_row33, c.Path); + row = tempReference_row33.get(); + Reference tempReference_row34 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row34, ref setScope, out setScope)); + row = tempReference_row34.get(); + innerType = c.TypeArgs[0]; + LayoutIndexedScope tupleLayout = innerType.getType().TypeAs(); + Reference tempReference_row35 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.Clone(out tempCursor).Find(tempReference_row35, Utf8String.Empty); + row = tempReference_row35.get(); + Reference tempReference_row36 = + new Reference(row); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(tupleLayout.WriteScope(tempReference_row36, ref tempCursor, innerType.getTypeArgs().clone(), + out tupleScope)); + row = tempReference_row36.get(); + Reference tempReference_row37 = + new Reference(row); + Reference tempReference_tupleScope = + new Reference(tupleScope); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(0).getType().TypeAs().WriteSparse(tempReference_row37, tempReference_tupleScope, t1.Work.get(0).Item1)); + tupleScope = tempReference_tupleScope.get(); + row = tempReference_row37.get(); + Reference tempReference_row38 = + new Reference(row); + assert tupleScope.MoveNext(tempReference_row38); + row = tempReference_row38.get(); + Reference tempReference_row39 = + new Reference(row); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(1).getType().TypeAs().WriteSparse(tempReference_row39, tempReference_tupleScope2, t1.Work.get(0).Item2)); + tupleScope = tempReference_tupleScope2.get(); + row = tempReference_row39.get(); + Reference tempReference_row40 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row40, ref setScope, ref tempCursor, + UpdateOptions.Insert)); + row = tempReference_row40.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void PreventUpdatesInNonUpdatableScope() + public void PreventUpdatesInNonUpdatableScope() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + // Write a set and then try to write directly into it. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("attendees", out c); + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor setScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row, out setScope).Find(tempReference_row2, c.Path); + row = tempReference_row2.get(); + row = tempReference_row.get(); + Reference tempReference_row3 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(tempReference_row3, ref setScope, c.TypeArgs, + out setScope)); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row4, + ref setScope, "foo")); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row5, out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + row = tempReference_row5.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, ref tempCursor, "foo" + )); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row8, ref setScope, ref tempCursor)); + row = tempReference_row8.get(); + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.InsufficientPermissions(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row9, + ref setScope, "foo")); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().DeleteSparse(tempReference_row10, ref setScope)); + row = tempReference_row10.get(); + + // Write a set of sets, successfully insert an empty set into it, and then try to write directly to the inner + // set. + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("prices", out c); + Reference tempReference_row11 = + new Reference(row); + Reference tempReference_row12 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row11, out setScope).Find(tempReference_row12, c.Path); + row = tempReference_row12.get(); + row = tempReference_row11.get(); + Reference tempReference_row13 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(tempReference_row13, ref setScope, c.TypeArgs, + out setScope)); + row = tempReference_row13.get(); + TypeArgument innerType = c.TypeArgs[0]; + TypeArgument itemType = innerType.getTypeArgs().get(0).clone(); + LayoutUniqueScope innerLayout = innerType.getType().TypeAs(); + Reference tempReference_row14 = + new Reference(row); + Reference tempReference_row15 = + new Reference(row); + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row14, out tempCursor1).Find(tempReference_row15, "prices.0"); + row = tempReference_row15.get(); + row = tempReference_row14.get(); + Reference tempReference_row16 = + new Reference(row); + RowCursor innerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(innerLayout.WriteScope(tempReference_row16, ref tempCursor1, innerType.getTypeArgs().clone() + , out innerScope)); + row = tempReference_row16.get(); + Reference tempReference_row17 = + new Reference(row); + Reference tempReference_row18 = + new Reference(row); + RowCursor tempCursor2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + RowCursor.create(tempReference_row17, out tempCursor2).Find(tempReference_row18, "prices.0.0"); + row = tempReference_row18.get(); + row = tempReference_row17.get(); + Reference tempReference_row19 = + new Reference(row); + Reference tempReference_tempCursor2 = + new Reference(tempCursor2); + ResultAssert.IsSuccess(itemType.getType().TypeAs().WriteSparse(tempReference_row19, + tempReference_tempCursor2, 1.0F)); + tempCursor2 = tempReference_tempCursor2.get(); + row = tempReference_row19.get(); + Reference tempReference_row20 = + new Reference(row); + Reference tempReference_innerScope = + new Reference(innerScope); + Reference tempReference_tempCursor22 = + new Reference(tempCursor2); + ResultAssert.IsSuccess(innerLayout.MoveField(tempReference_row20, tempReference_innerScope, tempReference_tempCursor22)); + tempCursor2 = tempReference_tempCursor22.get(); + innerScope = tempReference_innerScope.get(); + row = tempReference_row20.get(); + Reference tempReference_row21 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row21, ref setScope, ref tempCursor1)); + row = tempReference_row21.get(); + Reference tempReference_row22 = + new Reference(row); + assert setScope.MoveNext(tempReference_row22); + row = tempReference_row22.get(); + Reference tempReference_row23 = + new Reference(row); + Reference tempReference_setScope = + new Reference(setScope); + Out tempOut_innerScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(tempReference_row23, tempReference_setScope, tempOut_innerScope)); + innerScope = tempOut_innerScope.get(); + setScope = tempReference_setScope.get(); + row = tempReference_row23.get(); + Reference tempReference_row24 = + new Reference(row); + Reference tempReference_innerScope2 = + new Reference(innerScope); + ResultAssert.InsufficientPermissions(itemType.getType().TypeAs().WriteSparse(tempReference_row24, + tempReference_innerScope2, 1.0F)); + innerScope = tempReference_innerScope2.get(); + row = tempReference_row24.get(); + Reference tempReference_row25 = + new Reference(row); + Reference tempReference_innerScope3 = + new Reference(innerScope); + ResultAssert.InsufficientPermissions(itemType.getType().TypeAs().DeleteSparse(tempReference_row25, + tempReference_innerScope3)); + innerScope = tempReference_innerScope3.get(); + row = tempReference_row25.get(); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void RowWriterTest() + public void RowWriterTest() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + + ArrayList expected = new ArrayList(Arrays.asList(UUID.fromString("{4674962B-CE11-4916-81C5" + + "-0421EE36F168}"), UUID.fromString("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), UUID.fromString("{B7BC39C2" + + "-1A2D-4EAF-8F33-ED976872D876}"), UUID.fromString("{DEA71ABE-3041-4CAF-BBD9-1A46D10832A0}"))); + + for (java.lang.Iterable permutation : expected.Permute()) { + Todo t1 = new Todo(); + t1.Projects = new ArrayList(permutation); + + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + Reference tempReference_row = + new Reference(row); + ResultAssert.IsSuccess(RowWriter.WriteBuffer(tempReference_row, t1, TypedSetUnitTests.SerializeTodo)); + row = tempReference_row.get(); + + // Update the existing Set by updating each item with itself. This ensures that the RowWriter has + // maintained the unique index correctly. + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("projects", out c); + Reference tempReference_row2 = + new Reference(row); + RowCursor root; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + RowCursor.create(tempReference_row2, out root); + row = tempReference_row2.get(); + Reference tempReference_row3 = + new Reference(row); + RowCursor projScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out projScope).Find(tempReference_row3, c.Path); + row = tempReference_row3.get(); + Reference tempReference_row4 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row4, ref projScope, out projScope)); + row = tempReference_row4.get(); + for (UUID item : t1.Projects) { + Reference tempReference_row5 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row5, Utf8String.Empty); + row = tempReference_row5.get(); + Reference tempReference_row6 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row6, + ref tempCursor, item)); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row7, ref projScope, + ref tempCursor)); + row = tempReference_row7.get(); + } + + Reference tempReference_row8 = + new Reference(row); + Reference tempReference_row9 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + Todo t2 = this.ReadTodo(tempReference_row8, RowCursor.create(tempReference_row9, out _)); + row = tempReference_row9.get(); + row = tempReference_row8.get(); + assert t1 == t2; + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void UpdateInSet() + public void UpdateInSet() { + RowBuffer row = new RowBuffer(TypedSetUnitTests.InitialRowSize); + row.initLayout(HybridRowVersion.V1, this.layout, this.resolver); + + ArrayList expected = new ArrayList(Arrays.asList(UUID.fromString("{4674962B-CE11-4916-81C5" + + "-0421EE36F168}"), UUID.fromString("{7499C40E-7077-45C1-AE5F-3E384966B3B9}"), UUID.fromString("{B7BC39C2" + + "-1A2D-4EAF-8F33-ED976872D876}"), UUID.fromString("{DEA71ABE-3041-4CAF-BBD9-1A46D10832A0}"))); + + for (java.lang.Iterable permutation : expected.Permute()) { + Todo t1 = new Todo(); + t1.Projects = new ArrayList(permutation); + + Reference tempReference_row = + new Reference(row); + Reference tempReference_row2 = + new Reference(row); + RowCursor _; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + this.WriteTodo(tempReference_row, RowCursor.create(tempReference_row2, out _), t1); + row = tempReference_row2.get(); + row = tempReference_row.get(); + + // Attempt to find each item in turn and then delete it. + Reference tempReference_row3 = + new Reference(row); + RowCursor root = RowCursor.create(tempReference_row3); + row = tempReference_row3.get(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert this.layout.TryFind("projects", out c); + Reference tempReference_row4 = + new Reference(row); + RowCursor setScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.Clone(out setScope).Find(tempReference_row4, c.Path); + row = tempReference_row4.get(); + Reference tempReference_row5 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().ReadScope(tempReference_row5, ref setScope, out setScope)); + row = tempReference_row5.get(); + for (UUID elm : t1.Projects) { + // Verify it is already there. + Reference tempReference_row6 = + new Reference(row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row6, Utf8String.Empty); + row = tempReference_row6.get(); + Reference tempReference_row7 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row7, + ref tempCursor, elm)); + row = tempReference_row7.get(); + Reference tempReference_row8 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: C# to Java Converter could not resolve the named parameters in the + // following line: + //ORIGINAL LINE: ResultAssert.IsSuccess(c.TypeAs().Find(ref row, ref setScope, ref + // tempCursor, value: out RowCursor _)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().Find(tempReference_row8, ref setScope, ref tempCursor, + value: + out RowCursor _)) + row = tempReference_row8.get(); + + // Insert it again with update. + Reference tempReference_row9 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row9, Utf8String.Empty); + row = tempReference_row9.get(); + Reference tempReference_row10 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row10, + ref tempCursor, elm)); + row = tempReference_row10.get(); + Reference tempReference_row11 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row11, ref setScope, + ref tempCursor, UpdateOptions.Update)); + row = tempReference_row11.get(); + + // Insert it again with upsert. + Reference tempReference_row12 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row12, Utf8String.Empty); + row = tempReference_row12.get(); + Reference tempReference_row13 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row13, + ref tempCursor, elm)); + row = tempReference_row13.get(); + Reference tempReference_row14 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeAs().MoveField(tempReference_row14, ref setScope, + ref tempCursor)); + row = tempReference_row14.get(); + + // Insert it again with insert (fail: exists). + Reference tempReference_row15 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row15, Utf8String.Empty); + row = tempReference_row15.get(); + Reference tempReference_row16 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row16, + ref tempCursor, elm)); + row = tempReference_row16.get(); + Reference tempReference_row17 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.Exists(c.typeAs().MoveField(tempReference_row17, ref setScope, + ref tempCursor, UpdateOptions.Insert)); + row = tempReference_row17.get(); + + // Insert it again with insert at (fail: disallowed). + Reference tempReference_row18 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.Clone(out tempCursor).Find(tempReference_row18, Utf8String.Empty); + row = tempReference_row18.get(); + Reference tempReference_row19 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().WriteSparse(tempReference_row19, + ref tempCursor, elm)); + row = tempReference_row19.get(); + Reference tempReference_row20 = + new Reference(row); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.TypeConstraint(c.typeAs().MoveField(tempReference_row20, ref setScope, + ref tempCursor, UpdateOptions.InsertAt)); + row = tempReference_row20.get(); + } + } + } + + private static ShoppingItem ReadShoppingItem(Reference row, Reference matchScope) { + Layout matchLayout = matchScope.get().getLayout(); + ShoppingItem m = new ShoppingItem(); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("label", out c); + Out tempOut_Label = new Out(); + ResultAssert.IsSuccess(c.typeAs().ReadVariable(row, matchScope, c, tempOut_Label)); + m.Label = tempOut_Label.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("count", out c); + Out tempOut_Count = new Out(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ResultAssert.IsSuccess(c.TypeAs().ReadFixed(ref row, ref matchScope, c, out m.Count)); + ResultAssert.IsSuccess(c.typeAs().ReadFixed(row, matchScope, c, tempOut_Count)); + m.Count = tempOut_Count.get(); + return m; + } + + private Todo ReadTodo(Reference row, Reference root) { + Todo value = new Todo(); + + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("attendees", out c); + RowCursor tagsScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out tagsScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref tagsScope, out tagsScope) == Result.SUCCESS) { + value.Attendees = new ArrayList(); + while (tagsScope.MoveNext(row)) { + String item; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref tagsScope, + out item)); + value.Attendees.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("projects", out c); + RowCursor projScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out projScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref projScope, out projScope) == Result.SUCCESS) { + value.Projects = new ArrayList(); + while (projScope.MoveNext(row)) { + java.util.UUID item; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref projScope, + out item)); + value.Projects.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("checkboxes", out c); + RowCursor checkboxScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out checkboxScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref checkboxScope, out checkboxScope) == Result.SUCCESS) { + value.Checkboxes = new ArrayList(); + while (checkboxScope.MoveNext(row)) { + boolean item; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.TypeArgs[0].Type.TypeAs().ReadSparse(row, ref checkboxScope, + out item)); + value.Checkboxes.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("prices", out c); + RowCursor pricesScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out pricesScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref pricesScope, out pricesScope) == Result.SUCCESS) { + value.Prices = new ArrayList>(); + TypeArgument innerType = c.TypeArgs[0]; + LayoutUniqueScope innerLayout = innerType.getType().TypeAs(); + while (pricesScope.MoveNext(row)) { + ArrayList item = new ArrayList(); + Reference tempReference_pricesScope = + new Reference(pricesScope); + RowCursor innerScope; + Out tempOut_innerScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(row, tempReference_pricesScope, tempOut_innerScope)); + innerScope = tempOut_innerScope.get(); + pricesScope = tempReference_pricesScope.get(); + while (innerScope.MoveNext(row)) { + LayoutFloat32 itemLayout = innerType.getTypeArgs().get(0).getType().TypeAs(); + Reference tempReference_innerScope = + new Reference(innerScope); + float innerItem; + Out tempOut_innerItem = new Out(); + ResultAssert.IsSuccess(itemLayout.ReadSparse(row, tempReference_innerScope, tempOut_innerItem)); + innerItem = tempOut_innerItem.get(); + innerScope = tempReference_innerScope.get(); + item.add(innerItem); + } + + value.Prices.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("nested", out c); + RowCursor nestedScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out nestedScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref nestedScope, out nestedScope) == Result.SUCCESS) { + value.Nested = new ArrayList>>(); + TypeArgument in2Type = c.TypeArgs[0]; + LayoutUniqueScope in2Layout = in2Type.getType().TypeAs(); + while (nestedScope.MoveNext(row)) { + ArrayList> item = new ArrayList>(); + Reference tempReference_nestedScope = + new Reference(nestedScope); + RowCursor in2Scope; + Out tempOut_in2Scope = + new Out(); + ResultAssert.IsSuccess(in2Layout.ReadScope(row, tempReference_nestedScope, tempOut_in2Scope)); + in2Scope = tempOut_in2Scope.get(); + nestedScope = tempReference_nestedScope.get(); + while (in2Scope.MoveNext(row)) { + TypeArgument in3Type = in2Type.getTypeArgs().get(0).clone(); + LayoutUniqueScope in3Layout = in3Type.getType().TypeAs(); + ArrayList item2 = new ArrayList(); + Reference tempReference_in2Scope = + new Reference(in2Scope); + RowCursor in3Scope; + Out tempOut_in3Scope = + new Out(); + ResultAssert.IsSuccess(in3Layout.ReadScope(row, tempReference_in2Scope, tempOut_in3Scope)); + in3Scope = tempOut_in3Scope.get(); + in2Scope = tempReference_in2Scope.get(); + while (in3Scope.MoveNext(row)) { + LayoutInt32 itemLayout = in3Type.getTypeArgs().get(0).getType().TypeAs(); + Reference tempReference_in3Scope = new Reference(in3Scope); + int innerItem; + Out tempOut_innerItem2 = new Out(); + ResultAssert.IsSuccess(itemLayout.ReadSparse(row, tempReference_in3Scope, tempOut_innerItem2)); + innerItem = tempOut_innerItem2.get(); + in3Scope = tempReference_in3Scope.get(); + item2.add(innerItem); + } + + item.add(item2); + } + + value.Nested.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("shopping", out c); + RowCursor shoppingScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out shoppingScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref shoppingScope, out shoppingScope) == Result.SUCCESS) { + value.Shopping = new ArrayList(); + while (shoppingScope.MoveNext(row)) { + TypeArgument innerType = c.TypeArgs[0]; + LayoutUDT innerLayout = innerType.getType().TypeAs(); + Reference tempReference_shoppingScope = + new Reference(shoppingScope); + RowCursor matchScope; + Out tempOut_matchScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(row, tempReference_shoppingScope, tempOut_matchScope)); + matchScope = tempOut_matchScope.get(); + shoppingScope = tempReference_shoppingScope.get(); + Reference tempReference_matchScope = + new Reference(matchScope); + ShoppingItem item = TypedSetUnitTests.ReadShoppingItem(row, tempReference_matchScope); + matchScope = tempReference_matchScope.get(); + value.Shopping.add(item); + } + } + + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert this.layout.TryFind("work", out c); + RowCursor workScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + root.get().Clone(out workScope).Find(row, c.Path); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these cannot be converted using the 'Ref' helper class unless the method is within the code being modified: + if (c.typeAs().ReadScope(row, ref workScope, out workScope) == Result.SUCCESS) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: value.Work = new List>(); + value.Work = new ArrayList>(); + while (workScope.MoveNext(row)) { + TypeArgument innerType = c.TypeArgs[0]; + LayoutIndexedScope innerLayout = innerType.getType().TypeAs(); + + Reference tempReference_workScope = new Reference(workScope); + RowCursor tupleScope; + Out tempOut_tupleScope = new Out(); + ResultAssert.IsSuccess(innerLayout.ReadScope(row, tempReference_workScope, tempOut_tupleScope)); + tupleScope = tempOut_tupleScope.get(); + workScope = tempReference_workScope.get(); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope = new Reference(tupleScope); + boolean item1; + Out tempOut_item1 = new Out(); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(0).getType().TypeAs().ReadSparse(row, tempReference_tupleScope, tempOut_item1)); + item1 = tempOut_item1.get(); + tupleScope = tempReference_tupleScope.get(); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope2 = new Reference(tupleScope); + long item2; + Out tempOut_item2 = new Out(); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: ResultAssert.IsSuccess(innerType.TypeArgs[1].Type.TypeAs().ReadSparse(ref row, ref tupleScope, out ulong item2)); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(1).getType().TypeAs().ReadSparse(row, tempReference_tupleScope2, tempOut_item2)); + item2 = tempOut_item2.get(); + tupleScope = tempReference_tupleScope2.get(); + value.Work.add(Tuple.Create(item1, item2)); + } + } + + return value; + } + + private static Result SerializeTodo(Reference writer, TypeArgument typeArg, Todo value) { + if (value.Projects != null) { + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + assert writer.get().getLayout().TryFind("projects", out c); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are + // not converted by C# to Java Converter: + Result r = writer.get().WriteScope("projects", c.TypeArg, value.Projects, (ref RowWriter writer2, + TypeArgument typeArg2, ArrayList value2) -> + { + for (UUID item : value2) { + ResultAssert.IsSuccess(writer2.WriteGuid(null, item)); + } + + return Result.SUCCESS; + }); + return r; + } + + return Result.SUCCESS; + } + + private static void WriteShoppingItem(Reference row, Reference matchScope, TypeArgumentList typeArgs, ShoppingItem m) { + Layout matchLayout = row.get().resolver().resolve(typeArgs.getSchemaId().clone()); + LayoutColumn c; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("label", out c); + ResultAssert.IsSuccess(c.typeAs().WriteVariable(row, matchScope, c, m.Label)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these cannot be converted using the 'Out' helper class unless the method is within the code being modified: + assert matchLayout.TryFind("count", out c); + ResultAssert.IsSuccess(c.typeAs().WriteFixed(row, matchScope, c, m.Count)); + } + + private void WriteTodo(Reference row, Reference root, Todo value) { + LayoutColumn c; + + if (value.Attendees != null) { + Out tempOut_c = + new Out(); + assert this.layout.TryFind("attendees", tempOut_c); + c = tempOut_c.get(); + RowCursor attendScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out attendScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref attendScope, + c.typeArgs().clone(), out attendScope)); + for (String item : value.Attendees) { + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(c.typeArgs().get(0).type().typeAs().WriteSparse(row, + ref tempCursor, item)); + Reference tempReference_attendScope = + new Reference(attendScope); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_attendScope, + tempReference_tempCursor)); + tempCursor = tempReference_tempCursor.get(); + attendScope = tempReference_attendScope.get(); + } + } + + if (value.Projects != null) { + Out tempOut_c2 = + new Out(); + assert this.layout.TryFind("projects", tempOut_c2); + c = tempOut_c2.get(); + RowCursor projScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out projScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref projScope, + c.typeArgs().clone(), out projScope)); + for (UUID item : value.Projects) { + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + Reference tempReference_tempCursor2 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeArgs().get(0).type().typeAs().WriteSparse(row, + tempReference_tempCursor2, item)); + tempCursor = tempReference_tempCursor2.get(); + Reference tempReference_projScope = + new Reference(projScope); + Reference tempReference_tempCursor3 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_projScope, + tempReference_tempCursor3)); + tempCursor = tempReference_tempCursor3.get(); + projScope = tempReference_projScope.get(); + } + } + + if (value.Checkboxes != null) { + Out tempOut_c3 = + new Out(); + assert this.layout.TryFind("checkboxes", tempOut_c3); + c = tempOut_c3.get(); + RowCursor checkboxScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out checkboxScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref checkboxScope, + c.typeArgs().clone(), out checkboxScope)); + for (boolean item : value.Checkboxes) { + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + Reference tempReference_tempCursor4 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeArgs().get(0).type().typeAs().WriteSparse(row, + tempReference_tempCursor4, item)); + tempCursor = tempReference_tempCursor4.get(); + Reference tempReference_checkboxScope = + new Reference(checkboxScope); + Reference tempReference_tempCursor5 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_checkboxScope, + tempReference_tempCursor5)); + tempCursor = tempReference_tempCursor5.get(); + checkboxScope = tempReference_checkboxScope.get(); + } + } + + if (value.Prices != null) { + Out tempOut_c4 = + new Out(); + assert this.layout.TryFind("prices", tempOut_c4); + c = tempOut_c4.get(); + RowCursor pricesScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out pricesScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref pricesScope, + c.typeArgs().clone(), out pricesScope)); + for (ArrayList item : value.Prices) { + assert item != null; + TypeArgument innerType = c.typeArgs().get(0).clone(); + LayoutUniqueScope innerLayout = innerType.getType().TypeAs(); + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor1).Find(row, "prices.0"); + RowCursor innerScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(innerLayout.WriteScope(row, ref tempCursor1, innerType.getTypeArgs().clone(), + out innerScope)); + for (float innerItem : item) { + LayoutFloat32 itemLayout = innerType.getTypeArgs().get(0).getType().TypeAs(); + RowCursor tempCursor2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword + // - these cannot be converted using the 'Out' helper class unless the method is within the + // code being modified: + root.get().Clone(out tempCursor2).Find(row, "prices.0.0"); + Reference tempReference_tempCursor2 + = new Reference(tempCursor2); + ResultAssert.IsSuccess(itemLayout.WriteSparse(row, tempReference_tempCursor2, innerItem)); + tempCursor2 = tempReference_tempCursor2.get(); + Reference tempReference_innerScope = + new Reference(innerScope); + Reference tempReference_tempCursor22 = new Reference(tempCursor2); + ResultAssert.IsSuccess(innerLayout.MoveField(row, tempReference_innerScope, tempReference_tempCursor22)); + tempCursor2 = tempReference_tempCursor22.get(); + innerScope = tempReference_innerScope.get(); + } + + Reference tempReference_pricesScope = + new Reference(pricesScope); + Reference tempReference_tempCursor1 = + new Reference(tempCursor1); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_pricesScope, + tempReference_tempCursor1)); + tempCursor1 = tempReference_tempCursor1.get(); + pricesScope = tempReference_pricesScope.get(); + } + } + + if (value.Nested != null) { + Out tempOut_c5 = + new Out(); + assert this.layout.TryFind("nested", tempOut_c5); + c = tempOut_c5.get(); + RowCursor nestedScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out nestedScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref nestedScope, + c.typeArgs().clone(), out nestedScope)); + for (ArrayList> item : value.Nested) { + assert item != null; + TypeArgument in2Type = c.typeArgs().get(0).clone(); + LayoutUniqueScope in2Layout = in2Type.getType().TypeAs(); + RowCursor tempCursor1; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor1).Find(row, "prices.0"); + RowCursor in2Scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(in2Layout.WriteScope(row, ref tempCursor1, in2Type.getTypeArgs().clone(), + out in2Scope)); + for (ArrayList item2 : item) { + assert item2 != null; + TypeArgument in3Type = in2Type.getTypeArgs().get(0).clone(); + LayoutUniqueScope in3Layout = in3Type.getType().TypeAs(); + RowCursor tempCursor2; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword + // - these cannot be converted using the 'Out' helper class unless the method is within the + // code being modified: + root.get().Clone(out tempCursor2).Find(row, "prices.0.0"); + RowCursor in3Scope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword + // - these cannot be converted using the 'Out' helper class unless the method is within the + // code being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword + // - these cannot be converted using the 'Ref' helper class unless the method is within the + // code being modified: + ResultAssert.IsSuccess(in3Layout.WriteScope(row, ref tempCursor2, in3Type.getTypeArgs().clone(), + out in3Scope)); + for (int innerItem : item2) { + LayoutInt32 itemLayout = in3Type.getTypeArgs().get(0).getType().TypeAs(); + RowCursor tempCursor3; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' + // keyword - these cannot be converted using the 'Out' helper class unless the method + // is within the code being modified: + root.get().Clone(out tempCursor3).Find(row, "prices.0.0.0"); + Reference tempReference_tempCursor3 = new Reference(tempCursor3); + ResultAssert.IsSuccess(itemLayout.WriteSparse(row, tempReference_tempCursor3, innerItem)); + tempCursor3 = tempReference_tempCursor3.get(); + Reference tempReference_in3Scope = new Reference(in3Scope); + Reference tempReference_tempCursor32 = new Reference(tempCursor3); + ResultAssert.IsSuccess(in3Layout.MoveField(row, tempReference_in3Scope, tempReference_tempCursor32)); + tempCursor3 = tempReference_tempCursor32.get(); + in3Scope = tempReference_in3Scope.get(); + } + + Reference tempReference_in2Scope = + new Reference(in2Scope); + Reference tempReference_tempCursor23 = new Reference(tempCursor2); + ResultAssert.IsSuccess(in2Layout.MoveField(row, tempReference_in2Scope, tempReference_tempCursor23)); + tempCursor2 = tempReference_tempCursor23.get(); + in2Scope = tempReference_in2Scope.get(); + } + + Reference tempReference_nestedScope = + new Reference(nestedScope); + Reference tempReference_tempCursor12 = + new Reference(tempCursor1); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_nestedScope, + tempReference_tempCursor12)); + tempCursor1 = tempReference_tempCursor12.get(); + nestedScope = tempReference_nestedScope.get(); + } + } + + if (value.Shopping != null) { + Out tempOut_c6 = + new Out(); + assert this.layout.TryFind("shopping", tempOut_c6); + c = tempOut_c6.get(); + RowCursor shoppingScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out shoppingScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref shoppingScope, + c.typeArgs().clone(), out shoppingScope)); + for (ShoppingItem item : value.Shopping) { + TypeArgument innerType = c.typeArgs().get(0).clone(); + LayoutUDT innerLayout = innerType.getType().TypeAs(); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + Reference tempReference_tempCursor6 = + new Reference(tempCursor); + RowCursor itemScope; + Out tempOut_itemScope = + new Out(); + ResultAssert.IsSuccess(innerLayout.WriteScope(row, tempReference_tempCursor6, + innerType.getTypeArgs().clone(), tempOut_itemScope)); + itemScope = tempOut_itemScope.get(); + tempCursor = tempReference_tempCursor6.get(); + Reference tempReference_itemScope = + new Reference(itemScope); + TypedSetUnitTests.WriteShoppingItem(row, tempReference_itemScope, innerType.getTypeArgs().clone(), item); + itemScope = tempReference_itemScope.get(); + Reference tempReference_shoppingScope = + new Reference(shoppingScope); + Reference tempReference_tempCursor7 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_shoppingScope, + tempReference_tempCursor7)); + tempCursor = tempReference_tempCursor7.get(); + shoppingScope = tempReference_shoppingScope.get(); + } + } + + if (value.Work != null) { + Out tempOut_c7 = + new Out(); + assert this.layout.TryFind("work", tempOut_c7); + c = tempOut_c7.get(); + RowCursor workScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + root.get().Clone(out workScope).Find(row, c.path()); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + ResultAssert.IsSuccess(c.typeAs().WriteScope(row, ref workScope, + c.typeArgs().clone(), out workScope)); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: foreach (Tuple item in value.Work) + for (Tuple item : value.Work) { + TypeArgument innerType = c.typeArgs().get(0).clone(); + LayoutIndexedScope innerLayout = innerType.getType().TypeAs(); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + root.get().Clone(out tempCursor).Find(row, Utf8String.Empty); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - + // these cannot be converted using the 'Out' helper class unless the method is within the code + // being modified: + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - + // these cannot be converted using the 'Ref' helper class unless the method is within the code + // being modified: + ResultAssert.IsSuccess(innerLayout.WriteScope(row, ref tempCursor, innerType.getTypeArgs().clone(), + out tupleScope)); + Reference tempReference_tupleScope = + new Reference(tupleScope); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(0).getType().TypeAs().WriteSparse(row, tempReference_tupleScope, item.Item1)); + tupleScope = tempReference_tupleScope.get(); + assert tupleScope.MoveNext(row); + Reference tempReference_tupleScope2 = + new Reference(tupleScope); + ResultAssert.IsSuccess(innerType.getTypeArgs().get(1).getType().TypeAs().WriteSparse(row, tempReference_tupleScope2, item.Item2)); + tupleScope = tempReference_tupleScope2.get(); + Reference tempReference_workScope = + new Reference(workScope); + Reference tempReference_tempCursor8 = + new Reference(tempCursor); + ResultAssert.IsSuccess(c.typeAs().MoveField(row, tempReference_workScope, + tempReference_tempCursor8)); + tempCursor = tempReference_tempCursor8.get(); + workScope = tempReference_workScope.get(); + } + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class ShoppingItem + private final static class ShoppingItem { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public byte Count; + public byte Count; + public String Label; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof ShoppingItem; + ShoppingItem shoppingItem = tempVar ? (ShoppingItem)obj : null; + return tempVar && this.equals(shoppingItem); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: return (this.Label.GetHashCode() * 397) ^ this.Count.GetHashCode(); + return (this.Label.hashCode() * 397) ^ (new Byte(this.Count)).hashCode(); + } + } + + private boolean equals(ShoppingItem other) { + return this.Label.equals(other.Label) && this.Count == other.Count; + } + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1401", Justification = "Test types.")] private sealed class Todo + private final static class Todo { + public ArrayList Attendees; + public ArrayList Checkboxes; + public ArrayList>> Nested; + public ArrayList> Prices; + public ArrayList Projects; + public ArrayList Shopping; + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: public List> Work; + public ArrayList> Work; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + boolean tempVar = obj instanceof Todo; + Todo todo = tempVar ? (Todo)obj : null; + return tempVar && this.equals(todo); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = 0; + hashCode = (hashCode * 397) ^ (this.Attendees == null ? null : this.Attendees.hashCode() != null ? this.Attendees.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Projects == null ? null : this.Projects.hashCode() != null ? this.Projects.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Checkboxes == null ? null : this.Checkboxes.hashCode() != null ? this.Checkboxes.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Prices == null ? null : this.Prices.hashCode() != null ? this.Prices.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Nested == null ? null : this.Nested.hashCode() != null ? this.Nested.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Shopping == null ? null : this.Shopping.hashCode() != null ? this.Shopping.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Work == null ? null : this.Work.hashCode() != null ? this.Work.hashCode() : 0); + return hashCode; + } + } + + private static boolean NestedNestedSetEquals(ArrayList>> left, ArrayList>> right) { + if (left.size() != right.size()) { + return false; + } + + for (int i = 0; i < left.size(); i++) { + if (!Todo.NestedSetEquals(left.get(i), right.get(i))) { + return false; + } + } + + return true; + } + + private static boolean NestedSetEquals(ArrayList> left, ArrayList> right) { + if (left.size() != right.size()) { + return false; + } + + for (int i = 0; i < left.size(); i++) { + if (!Todo.SetEquals(left.get(i), right.get(i))) { + return false; + } + } + + return true; + } + + private static boolean SetEquals(ArrayList left, ArrayList right) { + if (left.size() != right.size()) { + return false; + } + + for (T item : left) { + if (!right.contains(item)) { + return false; + } + } + + return true; + } + + private boolean equals(Todo other) { + return (this.Attendees == other.Attendees || ((this.Attendees != null) && (other.Attendees != null) && Todo.SetEquals(this.Attendees, other.Attendees))) && (this.Projects == other.Projects || ((this.Projects != null) && (other.Projects != null) && Todo.SetEquals(this.Projects, other.Projects))) && (this.Checkboxes == other.Checkboxes || ((this.Checkboxes != null) && (other.Checkboxes != null) && Todo.SetEquals(this.Checkboxes, other.Checkboxes))) && (this.Prices == other.Prices || ((this.Prices != null) && (other.Prices != null) && Todo.NestedSetEquals(this.Prices, other.Prices))) && (this.Nested == other.Nested || ((this.Nested != null) && (other.Nested != null) && Todo.NestedNestedSetEquals(this.Nested, other.Nested))) && (this.Shopping == other.Shopping || ((this.Shopping != null) && (other.Shopping != null) && Todo.SetEquals(this.Shopping, other.Shopping))) && (this.Work == other.Work || ((this.Work != null) && (other.Work != null) && Todo.SetEquals(this.Work, other.Work))); + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/UpdateOptionsUnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/UpdateOptionsUnitTests.java new file mode 100644 index 0000000..7e98583 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/UpdateOptionsUnitTests.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.serialization.hybridrow.RowOptions; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public class UpdateOptionsUnitTests +public class UpdateOptionsUnitTests { + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [TestMethod][Owner("jthunter")] public void UpdateOptionsTest() + public final void UpdateOptionsTest() { + assert RowOptions.NONE.value() == UpdateOptions.None.getValue(); + assert RowOptions.UPDATE.value() == UpdateOptions.Update.getValue(); + assert RowOptions.INSERT.value() == UpdateOptions.Insert.getValue(); + assert RowOptions.UPSERT.value() == UpdateOptions.Upsert.getValue(); + assert RowOptions.INSERT_AT.value() == UpdateOptions.InsertAt.getValue(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/WriteRowDispatcher.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/WriteRowDispatcher.java new file mode 100644 index 0000000..003ed7e --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/WriteRowDispatcher.java @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedArray; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; + +import java.util.List; +import java.util.UUID; + +//C# TO JAVA CONVERTER WARNING: Java does not allow user-defined value types. The behavior of this class may differ +// from the original: +//ORIGINAL LINE: internal struct WriteRowDispatcher : IDispatcher +public final class WriteRowDispatcher implements IDispatcher { + + public , TValue> void Dispatch(Reference dispatcher, Reference field, LayoutColumn col, LayoutType t) { + Dispatch(dispatcher, field, col, t, null); + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public void Dispatch(ref RowOperationDispatcher dispatcher, ref RowCursor + // field, LayoutColumn col, LayoutType t, TValue value = default) where TLayout : LayoutType + public , TValue> void Dispatch(Reference dispatcher, Reference field, LayoutColumn col, LayoutType t, TValue value) { + switch (col == null ? null : col.getStorage()) { + case Fixed: + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().writeFixed(tempReference_Row, field, col, value)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + break; + case Variable: + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().writeVariable(tempReference_Row2, field, col, value)); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + break; + default: + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + ResultAssert.IsSuccess(t.typeAs().writeSparse(tempReference_Row3, field, value)); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + break; + } + } + + public void DispatchArray(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor arrayScope; + Out tempOut_arrayScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().WriteScope(tempReference_Row, scope, typeArgs.clone(), + tempOut_arrayScope)); + arrayScope = tempOut_arrayScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + List items = (List)value; + for (Object item : items) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref arrayScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), item); + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + arrayScope.MoveNext(tempReference_Row2); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + } + } + + public void DispatchMap(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 2); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor mapScope; + Out tempOut_mapScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().WriteScope(tempReference_Row, scope, typeArgs.clone(), + tempOut_mapScope)); + mapScope = tempOut_mapScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + Reference tempReference_mapScope = + new Reference(mapScope); + TypeArgument fieldType = t.typeAs().FieldType(tempReference_mapScope).clone(); + mapScope = tempReference_mapScope.get(); + List pairs = (List)value; + for (Object pair : pairs) { + String elmPath = UUID.NewGuid().toString(); + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + RowCursor.createForAppend(tempReference_Row2, out tempCursor); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref tempCursor, elmPath, fieldType.getType(), + fieldType.getTypeArgs().clone(), pair); + + // Move item into the map. + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + Reference tempReference_mapScope2 = + new Reference(mapScope); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(t.typeAs().MoveField(tempReference_Row3, tempReference_mapScope2, + tempReference_tempCursor)); + tempCursor = tempReference_tempCursor.get(); + mapScope = tempReference_mapScope2.get(); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + } + } + + public void DispatchNullable(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor nullableScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(t.typeAs().WriteScope(tempReference_Row, scope, typeArgs.clone(), + value != null, out nullableScope)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + if (value != null) { + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref nullableScope, null, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), value); + } + } + + public void DispatchObject(Reference dispatcher, + Reference scope) { + } + + public void DispatchSet(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() == 1); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor setScope; + Out tempOut_setScope = + new Out(); + ResultAssert.IsSuccess(t.typeAs().WriteScope(tempReference_Row, scope, typeArgs.clone(), + tempOut_setScope)); + setScope = tempOut_setScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + List items = (List)value; + for (Object item : items) { + String elmPath = UUID.NewGuid().toString(); + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + RowCursor tempCursor; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being + // modified: + RowCursor.createForAppend(tempReference_Row2, out tempCursor); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref tempCursor, elmPath, typeArgs.get(0).type(), + typeArgs.get(0).typeArgs().clone(), item); + + // Move item into the set. + Reference tempReference_Row3 = + new Reference(dispatcher.get().Row); + Reference tempReference_setScope = + new Reference(setScope); + Reference tempReference_tempCursor = + new Reference(tempCursor); + ResultAssert.IsSuccess(t.typeAs().MoveField(tempReference_Row3, tempReference_setScope, + tempReference_tempCursor)); + tempCursor = tempReference_tempCursor.get(); + setScope = tempReference_setScope.get(); + dispatcher.get().argValue.Row = tempReference_Row3.get(); + } + } + + public void DispatchTuple(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + checkArgument(typeArgs.count() >= 2); + + Reference tempReference_Row = + new Reference(dispatcher.get().Row); + RowCursor tupleScope; + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'out' keyword - these + // cannot be converted using the 'Out' helper class unless the method is within the code being modified: + ResultAssert.IsSuccess(t.typeAs().WriteScope(tempReference_Row, scope, typeArgs.clone(), + out tupleScope)); + dispatcher.get().argValue.Row = tempReference_Row.get(); + + for (int i = 0; i < typeArgs.count(); i++) { + PropertyInfo valueAccessor = value.getClass().GetProperty(String.format("Item%1$s", i + 1)); + // TODO: C# TO JAVA CONVERTER: The following method call contained an unresolved 'ref' keyword - these + // cannot be converted using the 'Ref' helper class unless the method is within the code being + // modified: + dispatcher.get().LayoutCodeSwitch(ref tupleScope, null, typeArgs.get(i).type(), + typeArgs.get(i).typeArgs().clone(), valueAccessor.GetValue(value)); + Reference tempReference_Row2 = + new Reference(dispatcher.get().Row); + tupleScope.MoveNext(tempReference_Row2); + dispatcher.get().argValue.Row = tempReference_Row2.get(); + } + } + + public void DispatchUDT(Reference dispatcher, + Reference scope, LayoutType t, TypeArgumentList typeArgs, + Object value) { + Reference tempReference_Row = new Reference(dispatcher.get().Row); + RowCursor udtScope; + Out tempOut_udtScope = new Out(); + ResultAssert.IsSuccess(t.typeAs().WriteScope(tempReference_Row, scope, typeArgs.clone(), tempOut_udtScope)); + udtScope = tempOut_udtScope.get(); + dispatcher.get().argValue.Row = tempReference_Row.get(); + IDispatchable valueDispatcher = value instanceof IDispatchable ? (IDispatchable)value : null; + assert valueDispatcher != null; + Reference tempReference_udtScope = new Reference(udtScope); + valueDispatcher.Dispatch(dispatcher, tempReference_udtScope); + udtScope = tempReference_udtScope.get(); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Address.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Address.java new file mode 100644 index 0000000..1886840 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Address.java @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.customerschema; + +import azure.data.cosmos.serialization.hybridrow.unit.*; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +public final class Address { + public String City; + public PostalCode PostalCode; + public String State; + public String Street; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + return obj instanceof Address && this.equals((Address)obj); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = this.Street != null ? this.Street.hashCode() : 0; + hashCode = (hashCode * 397) ^ (this.City != null ? this.City.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.State != null ? this.State.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.PostalCode != null ? this.PostalCode.hashCode() : 0); + return hashCode; + } + } + + private boolean equals(Address other) { + return this.Street.equals(other.Street) && this.City.equals(other.City) && this.State.equals(other.State) && this.PostalCode.equals(other.PostalCode); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/AddressSerializer.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/AddressSerializer.java new file mode 100644 index 0000000..dc3777f --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/AddressSerializer.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.customerschema; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import azure.data.cosmos.serialization.hybridrow.unit.*; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; + +public final class AddressSerializer { + public static Result Read(Reference reader, Out
obj) { + obj.setAndGet(new Address()); + while (reader.get().read()) { + Result r; + switch (reader.get().path()) { + case "street": + Out tempOut_Street = new Out(); + r = reader.get().readUtf8String(tempOut_Street); + obj.get().argValue.Street = tempOut_Street.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "city": + Out tempOut_City = new Out(); + r = reader.get().readUtf8String(tempOut_City); + obj.get().argValue.City = tempOut_City.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "state": + Out tempOut_State = new Out(); + r = reader.get().readUtf8String(tempOut_State); + obj.get().argValue.State = tempOut_State.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "postal_code": + Reference tempReference_child = + new Reference(child); + Out tempOut_PostalCode = new Out(); + // TODO: C# TO JAVA CONVERTER: The following lambda contained an unresolved 'ref' keyword - these are not converted by C# to Java Converter: + r = reader.get().readScope(obj.get(), (RowReader RowReader child, Address parent) -> PostalCodeSerializer.Read(tempReference_child, tempOut_PostalCode)); + parent.PostalCode = tempOut_PostalCode.get(); + child = tempReference_child.get(); + + if (r != Result.SUCCESS) { + return r; + } + + break; + } + } + + return Result.SUCCESS; + } + + public static Result Write(Reference writer, TypeArgument typeArg, Address obj) { + Result r; + if (obj.Street != null) { + r = writer.get().WriteString("street", obj.Street); + if (r != Result.SUCCESS) { + return r; + } + } + + if (obj.City != null) { + r = writer.get().WriteString("city", obj.City); + if (r != Result.SUCCESS) { + return r; + } + } + + if (obj.State != null) { + r = writer.get().WriteString("state", obj.State); + if (r != Result.SUCCESS) { + return r; + } + } + + if (obj.PostalCode != null) { + r = writer.get().WriteScope("postal_code", PostalCodeSerializer.TypeArg, obj.PostalCode, + PostalCodeSerializer.Write); + return r; + } + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Guest.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Guest.java new file mode 100644 index 0000000..9652290 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Guest.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.customerschema; + +import azure.data.cosmos.serialization.hybridrow.unit.*; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +public final class Guest { + public Map Addresses; + public String ConfirmNumber; + public Set Emails; + public String FirstName; + public UUID Id; + public String LastName; + public List PhoneNumbers; + public String Title; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + return obj instanceof Guest && this.equals((Guest)obj); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = this.Id.hashCode(); + hashCode = (hashCode * 397) ^ (this.FirstName != null ? this.FirstName.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.LastName != null ? this.LastName.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Title != null ? this.Title.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Emails != null ? this.Emails.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.PhoneNumbers != null ? this.PhoneNumbers.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Addresses != null ? this.Addresses.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.ConfirmNumber != null ? this.ConfirmNumber.hashCode() : 0); + return hashCode; + } + } + + private static boolean DictionaryEquals(Map left, Map right) { + if (left == right) { + return true; + } + + if ((left == null) || (right == null)) { + return false; + } + + if (left.size() != right.size()) { + return false; + } + + for (Map.Entry p : left.entrySet()) { + TValue value; + if (!(right.containsKey(p.getKey()) && (value = right.get(p.getKey())) == value)) { + return false; + } + + if (!p.getValue().equals(value)) { + return false; + } + } + + return true; + } + + private boolean equals(Guest other) { + //C# TO JAVA CONVERTER WARNING: Java AbstractList 'equals' is not always identical to LINQ 'SequenceEqual': + //ORIGINAL LINE: return this.Id.Equals(other.Id) && string.Equals(this.FirstName, other.FirstName) && string + // .Equals(this.LastName, other.LastName) && string.Equals(this.Title, other.Title) && string.Equals(this + // .ConfirmNumber, other.ConfirmNumber) && ((this.Emails == other.Emails) || ((this.Emails != null) && (other + // .Emails != null) && this.Emails.SetEquals(other.Emails))) && ((this.PhoneNumbers == other.PhoneNumbers) || + // ((this.PhoneNumbers != null) && (other.PhoneNumbers != null) && this.PhoneNumbers.SequenceEqual(other + // .PhoneNumbers))) && Guest.DictionaryEquals(this.Addresses, other.Addresses); + return this.Id.equals(other.Id) && this.FirstName.equals(other.FirstName) && this.LastName.equals(other.LastName) && this.Title.equals(other.Title) && this.ConfirmNumber.equals(other.ConfirmNumber) && ((this.Emails == other.Emails) || ((this.Emails != null) && (other.Emails != null) && this.Emails.equals(other.Emails))) && ((this.PhoneNumbers == other.PhoneNumbers) || ((this.PhoneNumbers != null) && (other.PhoneNumbers != null) && this.PhoneNumbers.equals(other.PhoneNumbers))) && Guest.DictionaryEquals(this.Addresses, other.Addresses); + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Hotel.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Hotel.java new file mode 100644 index 0000000..3dabf8e --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/Hotel.java @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.customerschema; + +import azure.data.cosmos.serialization.hybridrow.unit.*; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +public final class Hotel { + public Address Address; + public String Id; + public String Name; + public String Phone; + + public boolean equals(Hotel other) { + return this.Id.equals(other.Id) && this.Name.equals(other.Name) && this.Phone.equals(other.Phone) && this.Address.equals(other.Address); + } + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + return obj instanceof Hotel && this.equals((Hotel)obj); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + int hashCode = this.Id == null ? null : this.Id.hashCode() != null ? this.Id.hashCode() : 0; + hashCode = (hashCode * 397) ^ (this.Name == null ? null : this.Name.hashCode() != null ? + this.Name.hashCode() : 0); + hashCode = (hashCode * 397) ^ (this.Phone == null ? null : this.Phone.hashCode() != null ? + this.Phone.hashCode() : 0); + int tempVar = this.Address.GetHashCode(); + hashCode = (hashCode * 397) ^ (this.Address == null ? null : tempVar != null ? tempVar : 0); + return hashCode; + } + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCode.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCode.java new file mode 100644 index 0000000..458a72b --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCode.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.customerschema; + +import azure.data.cosmos.serialization.hybridrow.unit.*; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +public final class PostalCode { + public Short Plus4; + public int Zip; + + @Override + public boolean equals(Object obj) { + if (null == obj) { + return false; + } + + if (this == obj) { + return true; + } + + return obj instanceof PostalCode && this.equals((PostalCode)obj); + } + + @Override + public int hashCode() { + // TODO: C# TO JAVA CONVERTER: There is no equivalent to an 'unchecked' block in Java: + unchecked + { + return (this.Zip * 397) ^ this.Plus4.hashCode(); + } + } + + private boolean equals(PostalCode other) { + return this.Zip == other.Zip && this.Plus4 == other.Plus4; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCodeSerializer.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCodeSerializer.java new file mode 100644 index 0000000..9810b50 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/customerschema/PostalCodeSerializer.java @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.customerschema; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Reference; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; +import azure.data.cosmos.serialization.hybridrow.unit.*; + +// TODO: C# TO JAVA CONVERTER: There is no preprocessor in Java: +///#pragma warning disable SA1401 // Fields should be private + + +public final class PostalCodeSerializer { + public static TypeArgument TypeArg = new TypeArgument(LayoutType.UDT, new TypeArgumentList(new SchemaId(1))); + + public static Result Read(Reference reader, Out obj) { + obj.setAndGet(new PostalCode()); + while (reader.get().read()) { + Result r; + switch (reader.get().path()) { + case "zip": + Out tempOut_Zip = new Out(); + r = reader.get().readInt32(tempOut_Zip); + obj.get().argValue.Zip = tempOut_Zip.get(); + if (r != Result.SUCCESS) { + return r; + } + + break; + case "plus4": + short value; + Out tempOut_value = new Out(); + r = reader.get().readInt16(tempOut_value); + value = tempOut_value.get(); + if (r != Result.SUCCESS) { + return r; + } + + obj.get().Plus4 = value; + break; + } + } + + return Result.SUCCESS; + } + + public static Result Write(Reference writer, TypeArgument typeArg, PostalCode obj) { + Result r; + r = writer.get().writeInt32("zip", obj.Zip); + if (r != Result.SUCCESS) { + return r; + } + + if (obj.Plus4.HasValue) { + r = writer.get().writeInt16("plus4", obj.Plus4.Value); + return r; + } + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/internal/MurmurHash3UnitTests.java b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/internal/MurmurHash3UnitTests.java new file mode 100644 index 0000000..c3ee6e0 --- /dev/null +++ b/java/exclusions/test/java/com/azure/data/cosmos/serialization/hybridrow/unit/internal/MurmurHash3UnitTests.java @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.unit.internal; + +import com.azure.data.cosmos.serialization.hybridrow.internal.Murmur3Hash; + +import java.util.Random; + +// TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: +//ORIGINAL LINE: [TestClass] public class MurmurHash3UnitTests +public class MurmurHash3UnitTests { + + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: private static readonly(ulong low, ulong high)[] Expected = new[] { (0x56F1549659CBEE1AUL, + // 0xCEB3EE124C3E3855UL), (0xFE84B58886F9D717UL, 0xD24C5DE024F5EA6BUL), (0x89F6250648BB11BFUL, + // 0x95595FB9D4CF58B0UL), (0xC76AFDB39EDC6262UL, 0xB9286AF4FADAF497UL), (0xC2CB4D9B3C9C247EUL, + // 0xB465D40116B8B7A2UL), (0x317178F5B26D0B35UL, 0x1D564F53E2E468ADUL), (0xE8D75F7C05F43F09UL, + // 0xA81CEA052AE92D6FUL), (0x8F837665508C08A8UL, 0x2A74E6E47E5497BCUL), (0x609778FDA1AFD731UL, + // 0x3EB1A0E3BFC653E4UL), (0x0F59B8965FA49D1AUL, 0xCB3BC158243A5DEEUL), (0x7A6D0AC9C98F5908UL, + // 0xBC93D3042C3E7178UL), (0x863FE5AEBA9A3DFAUL, 0xDF42416658CB87C5UL), (0xDB4C82337C8FB216UL, + // 0xCA7616B64ABF6B3DUL), (0x0049223177425B48UL, 0x25510D7246BC3C2CUL), (0x31AC129B24F82CABUL, + // 0xCD7174C2040E9834UL), (0xCE39465288116345UL, 0x1CE6A26BA2E9E67DUL), (0xD2BE55791E13DB17UL, + // 0xCF30BF3D93B3A9FAUL), (0x43E323DD0F079145UL, 0xF06721555571ABBAUL), (0xB0CE9F170A96F5BCUL, + // 0x18EE95960369D702UL), (0xBFFAF6BEBC84A2A9UL, 0xE0612B6FC0C9D502UL), (0x33E2D699697BC2DAUL, + // 0xB7E9CD6313DE05EEUL), (0xCBFD7D8DA2A962BFUL, 0xCF4C281A7750E88AUL), (0xBD8D863F83863088UL, + // 0x01AFFBDE3D405D35UL), (0xBA2E05DF3328C7DBUL, 0x9620867ADDFE6579UL), (0xC57BD1FB63CA0947UL, + // 0xE1391F8454D4EA9FUL), (0x6AB710460A5BF9BAUL, 0x11D7E13FBEF63775UL), (0x55C2C7C95F41C483UL, + // 0xA4DCC9F547A89563UL), (0x8AA5A2031027F216UL, 0x1653FC7AD6CC6104UL), (0xAD8A899FF093D9A5UL, + // 0x0EB26F6D1CCEB258UL), (0xA3B6D57EBEB965D1UL, 0xE8078FCC5D8C2E3EUL), (0x91ABF587B38224F6UL, + // 0x35899665A8A9252CUL), (0xF05B1AF0487EE2D4UL, 0x5D7496C1665DDE12UL)}; + + private static final Murmur3Hash.HashCode128[] EXPECTED_VALUES = new Murmur3Hash.HashCode128[] { + new Murmur3Hash.HashCode128(0x56F1549659CBEE1AL, 0xCEB3EE124C3E3855L), + new Murmur3Hash.HashCode128(0xFE84B58886F9D717L, 0xD24C5DE024F5EA6BL), + new Murmur3Hash.HashCode128(0x89F6250648BB11BFL, 0x95595FB9D4CF58B0L), + new Murmur3Hash.HashCode128(0xC76AFDB39EDC6262L, 0xB9286AF4FADAF497L), + new Murmur3Hash.HashCode128(0xC2CB4D9B3C9C247EL, 0xB465D40116B8B7A2L), + new Murmur3Hash.HashCode128(0x317178F5B26D0B35L, 0x1D564F53E2E468ADL), + new Murmur3Hash.HashCode128(0xE8D75F7C05F43F09L, 0xA81CEA052AE92D6FL), + new Murmur3Hash.HashCode128(0x8F837665508C08A8L, 0x2A74E6E47E5497BCL), + new Murmur3Hash.HashCode128(0x609778FDA1AFD731L, 0x3EB1A0E3BFC653E4L), + new Murmur3Hash.HashCode128(0x0F59B8965FA49D1AL, 0xCB3BC158243A5DEEL), + new Murmur3Hash.HashCode128(0x7A6D0AC9C98F5908L, 0xBC93D3042C3E7178L), + new Murmur3Hash.HashCode128(0x863FE5AEBA9A3DFAL, 0xDF42416658CB87C5L), + new Murmur3Hash.HashCode128(0xDB4C82337C8FB216L, 0xCA7616B64ABF6B3DL), + new Murmur3Hash.HashCode128(0x0049223177425B48L, 0x25510D7246BC3C2CL), + new Murmur3Hash.HashCode128(0x31AC129B24F82CABL, 0xCD7174C2040E9834L), + new Murmur3Hash.HashCode128(0xCE39465288116345L, 0x1CE6A26BA2E9E67DL), + new Murmur3Hash.HashCode128(0xD2BE55791E13DB17L, 0xCF30BF3D93B3A9FAL), + new Murmur3Hash.HashCode128(0x43E323DD0F079145L, 0xF06721555571ABBAL), + new Murmur3Hash.HashCode128(0xB0CE9F170A96F5BCL, 0x18EE95960369D702L), + new Murmur3Hash.HashCode128(0xBFFAF6BEBC84A2A9L, 0xE0612B6FC0C9D502L), + new Murmur3Hash.HashCode128(0x33E2D699697BC2DAL, 0xB7E9CD6313DE05EEL), + new Murmur3Hash.HashCode128(0xCBFD7D8DA2A962BFL, 0xCF4C281A7750E88AL), + new Murmur3Hash.HashCode128(0xBD8D863F83863088L, 0x01AFFBDE3D405D35L), + new Murmur3Hash.HashCode128(0xBA2E05DF3328C7DBL, 0x9620867ADDFE6579L), + new Murmur3Hash.HashCode128(0xC57BD1FB63CA0947L, 0xE1391F8454D4EA9FL), + new Murmur3Hash.HashCode128(0x6AB710460A5BF9BAL, 0x11D7E13FBEF63775L), + new Murmur3Hash.HashCode128(0x55C2C7C95F41C483L, 0xA4DCC9F547A89563L), + new Murmur3Hash.HashCode128(0x8AA5A2031027F216L, 0x1653FC7AD6CC6104L), + new Murmur3Hash.HashCode128(0xAD8A899FF093D9A5L, 0x0EB26F6D1CCEB258L), + new Murmur3Hash.HashCode128(0xA3B6D57EBEB965D1L, 0xE8078FCC5D8C2E3EL), + new Murmur3Hash.HashCode128(0x91ABF587B38224F6L, 0x35899665A8A9252CL), + new Murmur3Hash.HashCode128(0xF05B1AF0487EE2D4L, 0x5D7496C1665DDE12L) }; + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + // ORIGINAL LINE: + // [TestMethod][Owner("jthunter")] public void Hash128Check() + public final void Hash128Check() { + // Generate deterministic data for which the Murmur3Hash is known (see Expected). + Random rand = new Random(42); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: byte[][] samples = new byte[MurmurHash3UnitTests.Expected.Length][]; + byte[][] samples = new byte[MurmurHash3UnitTests.EXPECTED_VALUES.length][]; + for (int i = 0; i < samples.length; i++) { + int sampleLength = rand.nextInt(10 * 1024); + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: samples[i] = new byte[sampleLength]; + samples[i] = new byte[sampleLength]; + rand.nextBytes(samples[i]); + } + + // Warm up the loop and verify correctness. + for (int i = 0; i < samples.length; i++) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: byte[] sample = samples[i]; + byte[] sample = samples[i]; + // TODO: C# TO JAVA CONVERTER: Java has no equivalent to C# deconstruction declarations: + ( long low, long high) = Murmur3Hash.Hash128(sample, (0, 0)) + System.out.println(String.format("(0x%016XUL, 0x%1.16XUL),", high, low)); + assert MurmurHash3UnitTests.EXPECTED_VALUES[i].high == high; + assert MurmurHash3UnitTests.EXPECTED_VALUES[i].low == low; + } + + // Measure performance. + long ticks = MurmurHash3UnitTests.MeasureLoop(samples); + System.out.println(String.format("Murmur3Hash: %1$s", ticks)); + } + + // TODO: C# TO JAVA CONVERTER: Java annotations will not correspond to .NET attributes: + //ORIGINAL LINE: [MethodImpl(MethodImplOptions.NoInlining)][SuppressMessage("Microsoft.Reliability", + // "CA2001:Avoid calling problematic methods", Justification = "Perf Benchmark")] private static long MeasureLoop + // (byte[][] samples) + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: [MethodImpl(MethodImplOptions.NoInlining)][SuppressMessage("Microsoft.Reliability", + // "CA2001:Avoid calling problematic methods", Justification = "Perf Benchmark")] private static long MeasureLoop + // (byte[][] samples) + private static long MeasureLoop(byte[][] samples) { + final int outerLoopCount = 10000; + System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); + + System.gc(); + watch.Start(); + for (int j = 0; j < outerLoopCount; j++) { + //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + //ORIGINAL LINE: foreach (byte[] sample in samples) + for (byte[] sample : samples) { + Murmur3Hash.Hash128(sample, (0, 0)) + } + } + + watch.Stop(); + return watch.ElapsedTicks; + } +} \ No newline at end of file diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 0000000..00df7f3 --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,293 @@ + + + + 4.0.0 + + com.azure.data + azure-cosmos-serialization + 2.9.5-SNAPSHOT + jar + + Microsoft Azure Cosmos Serialization API + This package contains Microsoft Azure Serialization API for Azure Cosmos DB + https://github.com/microsoft/HybridRow + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + + + + + microsoft + Microsoft Corporation + + + + + + azure-cosmos-serialization + default + dev-azure-com-azure-cosmos-java-azure-cosmos-serialization + https://pkgs.dev.azure.com/azure-cosmos-java/_packaging/azure-cosmos-serialization/maven/v1 + + + azure-java-build-docs + ${site.url}/site/${project.artifactId} + + + + + + dev-azure-com-azure-cosmos-java-azure-cosmos-serialization + https://pkgs.dev.azure.com/azure-cosmos-java/_packaging/azure-cosmos-serialization/maven/v1 + + true + + + true + + + + + + https://github.com/microsoft/HybridRow + + + + ${project.basedir}/target/collectedArtifactsForRelease + + UTF-8 + UTF-8 + + unit + + 8.3.0 + 28.0-jre + 2.9.9 + 1.10.19 + 3.11.0 + 4.1.42.Final + 3.9.1 + 1.7.28 + 7.0.0 + + + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + com.google.guava + guava + ${guava.version} + + + + com.google.protobuf + protobuf-java + ${protobuf.version} + test + + + + com.google.protobuf + protobuf-java-util + ${protobuf.version} + test + + + + io.netty + netty-buffer + ${netty.version} + + + + it.unimi.dsi + fastutil + ${fastutil.version} + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.mongodb + bson + ${mongodb.version} + test + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + org.testng + testng + 7.0.0 + test + + + + + + + + unit + + default + unit + + + true + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + + + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + unit + + %regex[.*] + + + + surefire.testng.verbose + 2 + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + %regex[.*] + + + + surefire.testng.verbose + 2 + + + ${test.groups} + + + + + integration-test + verify + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.10 + + + + org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8 + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.1.1 + + + true + false + ${javadoc.opts} + + **/internal/**/*.java + **/*BridgeInternal.java + + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.1.0 + + + attach-sources + + jar-no-fork + + + + + + + + false + ${project.basedir}/../schemas + + SystemSchema.json + + + + + + + + diff --git a/java/src/main/java/com/azure/data/cosmos/core/Json.java b/java/src/main/java/com/azure/data/cosmos/core/Json.java new file mode 100644 index 0000000..b2dc491 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/Json.java @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import com.fasterxml.jackson.core.JsonFactory; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.SerializationFeature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Optional; + +import static com.google.common.base.Strings.lenientFormat; + +public final class Json { + + private static final Logger logger = LoggerFactory.getLogger(Json.class); + + private static final ObjectMapper mapper = new ObjectMapper(new JsonFactory() + .enable(JsonParser.Feature.ALLOW_COMMENTS)); + + private static final ObjectReader reader = mapper.reader() + .withFeatures(DeserializationFeature.READ_ENUMS_USING_TO_STRING); + + private static final ObjectWriter writer = mapper.writer() + .withFeatures(SerializationFeature.WRITE_ENUMS_USING_TO_STRING); + + private Json() { + } + + public static Optional parse(File file, Class type) { + try { + return Optional.of(reader.forType(type).readValue(file)); + } catch (IOException error) { + logger.error("failed to parse {} due to ", type.getName(), error); + return Optional.empty(); + } + } + + public static Optional parse(InputStream stream, Class type) { + try { + return Optional.of(reader.forType(type).readValue(stream)); + } catch (IOException error) { + logger.error("failed to parse {} due to ", type.getName(), error); + return Optional.empty(); + } + } + + public static Optional parse(String value, Class type) { + try { + return Optional.of(reader.forType(type).readValue(value)); + } catch (IOException error) { + logger.error("", error); + return Optional.empty(); + } + } + + public static String toString(Object object) { + try { + return writer.writeValueAsString(object); + } catch (JsonProcessingException error) { + return lenientFormat("{\"error\": \"%s\"}", error); + } + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/core/Out.java b/java/src/main/java/com/azure/data/cosmos/core/Out.java new file mode 100644 index 0000000..676786b --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/Out.java @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import java.util.Objects; + +/** + * A container object which may or may not contain a non-null value + * + * This is a value-based class and as such use of identity-sensitive operations--including reference equality + * ({@code ==}), identity hash code, or synchronization--on instances of {@code Out} may have unpredictable results and + * should be avoided. + * + * @param type of the referent. + */ +public final class Out { + + private volatile T value; + + public T get() { + return this.value; + } + + public void set(T value) { + this.value = value; + } + + public T setAndGet(T value) { + return this.value = value; + } + + /** + * {@code true} if there is a value present, otherwise {@code false} + *

+ * This is equivalent to evaluating the expression {@code out.get() == null}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return this.value != null; + } + + /** + * Indicates whether some other object is equal to this {@link Out} value. + *

+ * The other object is considered equal if: + *

    + *
  • it is also an {@link Out} and; + *
  • both instances have no value present or; + *
  • the present values are equal to each other as determined by {@code T.equals(Object)}}. + *
+ * + * @param other an object to be tested for equality + * @return {code true} if the other object is equal to this object; otherwise {@code false} + */ + @Override + public boolean equals(Object other) { + + if (this == other) { + return true; + } + + if (other.getClass() != Out.class) { + return false; + } + + return Objects.equals(this.value, ((Out)other).value); + } + + /** + * Returns the hash code value of the present value, if any, or 0 (zero) if + * no value is present. + * + * @return hash code value of the present value or 0 if no value is present + */ + @Override + public int hashCode() { + return Objects.hashCode(this.value); + } + + @Override + public String toString() { + return this.value == null ? "null" : this.value.toString(); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/core/Reference.java b/java/src/main/java/com/azure/data/cosmos/core/Reference.java new file mode 100644 index 0000000..cede38a --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/Reference.java @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import java.util.Objects; + +/** + * A container object which may or may not contain a non-null value. + * + * This is a value-based class and as such use of identity-sensitive operations--including reference equality + * ({@code ==}), identity hash code, or synchronization--on instances of {@link Reference} may have unpredictable + * results and should be avoided. + * + * @param type of the referent. + */ +public final class Reference { + + private volatile T value; + + public Reference(T value) { + this.setAndGet(value); + } + + public T get() { + return this.value; + } + + public void set(T value) { + this.value = value; + } + public T setAndGet(T value) { + return this.value = value; + } + + /** + * {@code true} if there is a value present, otherwise {@code false}. + * + * This is equivalent to evaluating the expression {@code ref.get() == null}. + * + * @return {@code true} if there is a value present, otherwise {@code false} + */ + public boolean isPresent() { + return this.value != null; + } + + /** + * Indicates whether some other object is equal to this {@link Reference} value. + *

+ * The other object is considered equal if: + *

    + *
  • it is also an {@link Reference} and; + *
  • both instances have no value present or; + *
  • the present values are equal to each other as determined by {@code T.equals(Object)}}. + *
+ * + * @param other an object to be tested for equality + * @return {code true} if the other object is equal to this object; otherwise {@code false} + */ + @Override + public boolean equals(Object other) { + + if (this == other) { + return true; + } + + if (other.getClass() != Reference.class) { + return false; + } + + return Objects.equals(this.value, ((Reference)other).value); + } + + + @Override + public String toString() { + return this.value == null ? "null" : this.value.toString(); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java b/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java new file mode 100644 index 0000000..b020e1e --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/Utf8String.java @@ -0,0 +1,1422 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.node.JsonNodeType; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.google.common.base.Objects; +import com.google.common.base.Suppliers; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufHolder; +import io.netty.buffer.Unpooled; +import io.netty.util.ByteProcessor; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.PrimitiveIterator; +import java.util.Spliterator; +import java.util.function.Consumer; +import java.util.function.IntConsumer; +import java.util.function.Supplier; +import java.util.stream.IntStream; +import java.util.stream.StreamSupport; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.lenientFormat; +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * The {@link Utf8String} class represents UTF-8 encoded character strings. + * + * @see RFC 3629: UTF-8, a transformation format of ISO 10646 + */ +@JsonDeserialize(using = Utf8String.JsonDeserializer.class) +@JsonSerialize(using = Utf8String.JsonSerializer.class) +public final class Utf8String implements ByteBufHolder, CharSequence, Comparable { + + // region Fields + + public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER); + public static final Utf8String NULL = new Utf8String(); + + private final ByteBuf buffer; + private final Supplier utf16String; + private final Supplier utf16StringLength; + + // endregion Fields + + // region Constructors + + private Utf8String() { + this.buffer = null; + this.utf16String = Suppliers.memoize(() -> null); + this.utf16StringLength = Suppliers.memoize(() -> -1); + } + + private Utf8String(@Nonnull final ByteBuf buffer) { + + if (buffer.writerIndex() == 0) { + this.buffer = Unpooled.EMPTY_BUFFER; + this.utf16String = Suppliers.memoize(() -> ""); + this.utf16StringLength = Suppliers.memoize(() -> 0); + return; + } + + this.buffer = buffer.readerIndex(0); // required to ensure proper hashCode computation by ByteBuf.hashCode + + this.utf16String = Suppliers.memoize(() -> { + + final int length = this.buffer.writerIndex(); + final UTF16Converter converter = new UTF16Converter(length); + final int index = this.buffer.forEachByte(0, length, converter); + + assert index == -1 : lenientFormat("index: %s, length: %s", index, length); + return converter.value(); + }); + + this.utf16StringLength = Suppliers.memoize(() -> { + + final UTF16CodeUnitCounter counter = new UTF16CodeUnitCounter(); + final int length = this.buffer.writerIndex(); + final int index = this.buffer.forEachByte(0, length, counter); + + assert index == -1 : lenientFormat("index: %s, length: %s", index, length); + return counter.charCount(); + }); + } + + private Utf8String(@Nonnull String value) { + + if (value.length() == 0) { + this.buffer = Unpooled.EMPTY_BUFFER; + this.utf16String = Suppliers.memoize(() -> ""); + this.utf16StringLength = Suppliers.memoize(() -> 0); + return; + } + + this.buffer = Unpooled.wrappedBuffer(value.getBytes(UTF_8)); + this.utf16String = Suppliers.memoize(() -> value); + this.utf16StringLength = Suppliers.memoize(value::length); + } + + // endregion + + // region Methods + + /** + * {@code true} if the length of this instance is zero. + * + * @return {@code true} if the length of this instance is zero. + */ + public final boolean isEmpty() { + return this == EMPTY; + } + + /** + * {@code true} if this instance is {@code null}. + * + * @return {@code true} if this instance is {@code null}. + */ + public final boolean isNull() { + return this == NULL; + } + + /** + * Returns the {@code char} value at the specified index. + *

+ * An index is expressed in UTF-16 code units, not UTF-8 code units as required by the {@link CharSequence} + * contract. An index ranges from zero to {@code length() - 1}. The first {@code char} value of the sequence is at + * index zero, the next at index one, and so on, as for array indexing. + *

+ * If the {@code char} value specified by the index is a + * surrogate, the surrogate value is returned. + *

+ * Use this method judiciously as indexing a {@link Utf8String} in UTF-16 code units incurs an O(n) time cost. + * Use {@link #chars} for sequential access to UTF-16 code units. Consider converting this {@link Utf8String} to + * a {@link String}, if random access to {@code char} values is required. The time cost incurred by + * {@link String#charAt} is O(1). + * + * @param index the index of the {@code char} value to be returned. + * @return the {@code char} value at the specified {@code index}. + * @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than {@link #length}. + */ + @Override + public char charAt(final int index) { + + if (index < 0) { + throw new IndexOutOfBoundsException(); + } + + UTF16CodeUnitIterator iterator = new UTF16CodeUnitIterator(this.buffer); + int countdown = index; + + while (iterator.hasNext()) { + if (--countdown < 0) { + return (char) iterator.nextInt(); + } + } + + throw new IndexOutOfBoundsException(); + } + + /** + * Returns a stream of {@code int} zero-extending the {@code char} values in this {@link Utf8String}. + *

+ * Any char which maps to a surrogate code point is passed + * through uninterpreted. + *

+ * No additional string space is allocated. + * + * @return a stream of {@code int} zero-extending the {@code char} values in this {@link Utf8String}. + */ + @Override + public IntStream chars() { + return this == NULL || this == EMPTY + ? IntStream.empty() + : StreamSupport.intStream(new UTF16CodeUnitSpliterator(this.buffer), false); + } + + /** + * Returns a stream of code point values from this {@link Utf8String}. + *

+ * Any surrogate pairs in the sequence are combined as if by {@link Character#toCodePoint Character.toCodePoint} and + * the result is passed to the stream. Any other code units, including ordinary BMP characters, unpaired surrogates, + * and undefined code units, are zero-extended to {@code int} values which are then passed to the stream. + *

+ * No additional string space is allocated. + * + * @return a stream of {@code int} code point values from this {@link Utf8String}. + */ + public final IntStream codePoints() { + return this == NULL || this == EMPTY + ? IntStream.empty() + : StreamSupport.intStream(new CodePointSpliterator(this.buffer), false); + } + + /** + * Compares the contents of this {@link Utf8String} to another {@link Utf8String} lexicographically. + *

+ * The comparison is based on the Unicode value of each of the characters in the strings. + * + * @param other the {@link Utf8String} to be compared. + * @return the value 0 if the argument {@code string} is equal to this {@link Utf8String}; a value less than 0 if + * this {@link Utf8String} is lexicographically less than the {@code string} argument; and a value greater than 0 + * if this {@link Utf8String} is lexicographically greater than the {@code string} argument. + */ + public final int compareTo(@Nonnull final Utf8String other) { + + checkNotNull(other, "expected non-null other"); + + if (other.buffer == this.buffer) { + return 0; + } + + if (other.buffer == null) { + return 1; + } + + if (this.buffer == null) { + return -1; + } + + return this.buffer.compareTo(other.buffer); + } + + /** + * Compares the contents of a {@link String} to this {@link Utf8String} lexicographically. + *

+ * The comparison is based on the Unicode value of each of the characters in the strings. This method takes + * advantage of the UTF-8 encoding mechanism which is cleverly designed so that if you sort by looking at the + * numeric value of each 8-bit encoded byte, you will get the same result as if you first decoded the string + * into Unicode and compared the numeric values of each code point. + * + * @param string the {@link String} to be compared. + * @return the value 0 if the argument {@code string} is equal to this {@link Utf8String}; a value less than 0 if + * this {@link Utf8String} is lexicographically less than the {@code string} argument; and a value greater than 0 + * if this {@link Utf8String} is lexicographically greater than the {@code string} argument. + */ + public final int compareTo(final String string) { + + if (null == string) { + return null == this.buffer ? 0 : 1; + } + + if (NULL == this) { + return -1; + } + + PrimitiveIterator.OfInt thisIterator = new CodePointIterator(this.buffer); + PrimitiveIterator.OfInt thatIterator = string.codePoints().iterator(); + + while (thisIterator.hasNext() && thatIterator.hasNext()) { + final int compare = thisIterator.nextInt() - thatIterator.nextInt(); + if (compare != 0) { + return compare; + } + } + + return this.length() - string.length(); + } + + /** + * Returns a reference to the read-only {@link ByteBuf} holding the content of this {@link Utf8String}. + *

+ * A value of {@code null} is returned, if this {@link Utf8String} is {@code null}. + * + * @return reference to the read-only {@link ByteBuf} holding the content of this {@link Utf8String}, or + * {@code null} if this {@link Utf8String} is null. + */ + @Nullable + public ByteBuf content() { + return this.buffer; + } + + /** + * Creates a deep copy of this {@link Utf8String}. + *

+ * A value of {@link #NULL} or {@link #EMPTY} is returned, if this {@link Utf8String} is null or empty. + * + * @return a deep copy of this {@link Utf8String}, or a value of {@link #NULL} or {@link #EMPTY}, if this + * {@link Utf8String} is null or empty. + */ + @Override + public Utf8String copy() { + return this == NULL || this == EMPTY ? this : fromUnsafe(this.buffer.copy()); + } + + /** + * Duplicates this {@link Utf8String}. + *

+ * A value of {@link #NULL} or {@link #EMPTY} is returned, if this {@link Utf8String} is null or empty. Be aware + * that this will not automatically call {@link #retain()}. + * + * @return a duplicate of this {@link Utf8String}, or a value of {@link #NULL} or {@link #EMPTY}, if this + * {@link Utf8String} is null or empty. + */ + @Override + public Utf8String duplicate() { + return this == NULL || this == EMPTY ? this : fromUnsafe(this.buffer.duplicate()); + } + + /** + * Encoded length of this {@link Utf8String}. + *

+ * This is the same value as would be returned by {@link String#getBytes()}{@code .length()} with no time or space + * overhead. + * + * @return encoded length of this {@link Utf8String} + */ + public final int encodedLength() { + return this == NULL || this == EMPTY ? 0 : this.buffer.writerIndex(); + } + + /** + * Compares the contents of a {@link ByteBuf} to the contents of this {@link Utf8String}. + *

+ * The result is {@code true} if and only if the given {@link ByteBuf} is not {@code null} and contains the same + * sequence of 8-bit code units as this {@link Utf8String}. + * + * @param other the {@link String} to compare against. + * @return {@code true} if the given {@link String} represents the same sequence of characters as this + * {@link Utf8String}, {@code false} otherwise. + */ + public final boolean equals(ByteBuf other) { + return Objects.equal(this.buffer, other); + } + + /** + * Compares the contents of a {@link String} to the contents of this {@link Utf8String}. + *

+ * The result is {@code true} if and only if the argument is not {@code null} and represents the same sequence of + * characters as this {@link Utf8String}. + * + * @param other the {@link String} to compare against. + * @return {@code true} if the given {@link String} represents the same sequence of characters as this + * {@link Utf8String}, {@code false} otherwise. + */ + public final boolean equals(String other) { + if (other == null) { + return false; + } + return this.compareTo(other) == 0; + } + + /** + * Compares this {@link Utf8String} to another {@link Utf8String}. + *

+ * The result is {@code true} if and only if the argument is not {@code null} and is a {@link Utf8String} that + * represents the same sequence of characters as this {@link Utf8String}. + * + * @param other the {@link Utf8String} to compare against. + * @return {@code true} if the given {@link Utf8String} represents the same sequence of characters as this + * {@link Utf8String}, {@code false} otherwise. + */ + public final boolean equals(Utf8String other) { + if (this == other) { + return true; + } + if (null == other) { + return false; + } + return Objects.equal(this.buffer, other.buffer); + } + + /** + * Compares this {@link Utf8String} to another object. + *

+ * The result is {@code true} if and only if the argument is not {@code null} and is a {@link Utf8String} that + * represents the same sequence of characters as this {@link Utf8String}. + * + * @param other the object to compare to this {@link Utf8String}. + * @return {@code true} if the given object represents a {@link Utf8String} equivalent to this {@link Utf8String}, + * {@code false} otherwise. + */ + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (null == other || this.getClass() != other.getClass()) { + return false; + } + Utf8String that = (Utf8String) other; + return Objects.equal(this.buffer, that.buffer); + } + + /** + * Creates a new {@link Utf8String} from a {@link ByteBuf} with UTF-8 character validation. + *

+ * The {@link Utf8String} created assumes ownership of the {@link ByteBuf} but does not retain it. Thus no data is + * transferred and the {@link ByteBuf}'s reference count is not increased. + *

+ * If the {@link ByteBuf}'s content, reader index, or writer index are modified following a call to this method, the + * behavior of the {@link Utf8String} created is undefined. + * + * @param buffer the {@link ByteBuf} to validate and assign to the {@link Utf8String} created. + * @return a {@link Utf8String} instance, if the @{code buffer} validates or a value of @{link Optional#empty} + * otherwise. + */ + @Nonnull + public static Optional from(@Nonnull final ByteBuf buffer) { + + checkNotNull(buffer, "expected non-null buffer"); + + if (buffer.writerIndex() == 0) { + return Optional.of(EMPTY); + } + + int index = buffer.forEachByte(0, buffer.writerIndex(), new CodePointValidator()); + return index >= 0 ? Optional.empty() : Optional.of(new Utf8String(buffer)); + } + + /** + * Creates a new {@link Utf8String} from a {@link ByteBuf} without UTF-8 character validation. + *

+ * The {@link Utf8String} created assumes ownership of the {@link ByteBuf} but does not retain it. Thus no data is + * transferred and the {@link ByteBuf}'s reference count is not increased. + *

+ * If the {@link ByteBuf}'s content, reader index, or writer index are modified following a call to this method, the + * behavior of the {@link Utf8String} created is undefined. + * + * @param buffer a {@link ByteBuf} to assign to the {@link Utf8String} created. + * @return a new {@link Utf8String} + */ + @Nonnull + public static Utf8String fromUnsafe(@Nonnull ByteBuf buffer) { + checkNotNull(buffer, "expected non-null buffer"); + return buffer.writerIndex() == 0 ? EMPTY : new Utf8String(buffer); + } + + /** + * Returns a hash code calculated from the content of this {@link Utf8String}. + *

+ * If there's a {@link Utf8String} that is {@linkplain #equals(Object) equal to} this {@link Utf8String}, both + * strings will return the same value. + * + * @return a hash code value for this {@link Utf8String}. + */ + @Override + public int hashCode() { + // CONFIRMED: ByteBuf.hashCode returns 1 for empty buffers and a non-zero value for all other buffers + return this == NULL ? 0 : (this == EMPTY ? 1 : this.buffer.hashCode()); + } + + /** + * Returns the length of this {@link Utf8String}. + *

+ * The length is the number of UTF-16 code units in this {@link Utf8String}. This is the same value as would be + * returned by {@link Utf8String#toUtf16()}{@code .length()} with no space overhead. + * + * @return the length of this {@link Utf8String}. + */ + public final int length() { + return this.utf16StringLength.get(); + } + + /** + * Returns the reference count of this {@link Utf8String}. + *

+ * If {@code 0}, it means the content of this {@link Utf8String} has been deallocated. + * + * @return the reference count of this {@link Utf8String}. + */ + @Override + public int refCnt() { + return this == NULL ? 0 : this.buffer.refCnt(); + } + + /** + * Decreases the reference count of this {@link Utf8String} by {@code 1}. + *

+ * The underlying storage for this instance is deallocated, if the reference count reaches {@code 0}. + * + * @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated. + */ + @Override + public boolean release() { + return this == NULL || this.buffer.release(); + } + + /** + * Decreases the reference count of this {@link Utf8String} by the specified {@code decrement}. + *

+ * The underlying storage for this instance is deallocated, if the reference count reaches {@code 0}. + * + * @param decrement the value to subtract from the reference count. + * @return {@code true} if and only if the reference count became {@code 0}. + */ + @Override + public boolean release(final int decrement) { + return this == NULL || this.buffer.release(decrement); + } + + /** + * Returns a new {@link Utf8String} which contains the specified {@code content}. + * + * @param content text of the {@link Utf8String} to be created. + * @return the {@link Utf8String} created. + */ + @Override + public Utf8String replace(final ByteBuf content) { + return fromUnsafe(content); + } + + @Override + public Utf8String retain() { + if (this != NULL) { + this.buffer.retain(); + } + return this; + } + + @Override + public Utf8String retain(final int increment) { + if (this != NULL) { + this.buffer.retain(increment); + } + return this; + } + + /** + * Duplicates this {@link Utf8String}. + *

+ * This method returns a retained duplicate unlike {@link #duplicate()}. + * + * @see ByteBuf#retainedDuplicate() + */ + @Override + public Utf8String retainedDuplicate() { + return this == NULL || this == EMPTY ? this : fromUnsafe(this.buffer.retainedDuplicate()); + } + + /** + * Returns a {@link CharSequence} that is a subsequence of this sequence. + *

+ * The subsequence starts with the {@code char} value at the specified {@code start} index and ends with the + * {@code char} value at index {@code end - 1}. The length in {@code char}s of the returned sequence is + * {@code end - start}, so if {@code start == end} then an empty sequence is returned. + * + * @param start the start index, inclusive. + * @param end the end index, exclusive. + * @return the specified subsequence + * @throws IllegalArgumentException if the values of {@code start} or {@code end} would cause a code point to be + * split into a surrogate pair. This exception will only be thrown on sequences + * containing 4-byte UTF-8 encodings. Whether the exception is thrown on sequences + * containing 4-byte UTF-8 encodings depends on the values of {@code start} and + * {@code end}. To avoid this exception at the cost of data conversion and memory + * allocation, convert this {@link Utf8String} to a {@link String} and call + * {@link String#subSequence}. + * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code end} is greater than + * {@link #length()}, {@code start} is greater than {@code end}, or + * {@link #isNull()} is {@code true}. + */ + @Nonnull + @Override + public CharSequence subSequence(final int start, final int end) { + + final int length = this.length(); + + if (start < 0 || end < 0 || start > end || end > length) { + String message = lenientFormat("start: %s, end: %s, length: %s", start, end, length); + throw new IndexOutOfBoundsException(message); + } + + if (start == end) { + return EMPTY; + } + + if (start == 0 && end == length) { + return this; + } + + final int encodedLength = this.buffer.writerIndex(); + final int i, n; + + if (start == 0) { + i = 0; + n = encodedLength; + } else { + + final UTF16CodeUnitCounter counter = new UTF16CodeUnitCounter(start); + i = this.buffer.forEachByte(0, encodedLength, counter); + n = encodedLength - i; + + checkArgument(counter.charIndex() == counter.charLimit(), "start: %s, end: %s, counter: %s", + start, end, counter + ); + } + + final int j; + + if (end == length) { + j = encodedLength; + } else { + + final UTF16CodeUnitCounter counter = new UTF16CodeUnitCounter(end - start); + j = this.buffer.forEachByte(i, n, counter); + + checkArgument(counter.charIndex() == counter.charLimit(), "start: %s, end: %s, counter: %s", + start, end, counter + ); + } + + assert i >= 0 && j >= 0 : lenientFormat("i: %s, j: %s", i, j); + return fromUnsafe(this.buffer.slice(i, j - i)); + } + + @Override + @Nonnull + public String toString() { + return Json.toString(this.toUtf16()); + } + + @Nullable + public String toUtf16() { + return this.utf16String.get(); + } + + @Override + public Utf8String touch() { + if (this != NULL) { + this.buffer.touch(); + } + return this; + } + + @Override + public Utf8String touch(final Object hint) { + if (this != NULL) { + this.buffer.touch(hint); + } + return this; + } + + /** + * Creates a {@link Utf8String} from a UTF16 encoding string. + *

+ * This method must transcode the UTF-16 into UTF-8 which requires allocation and is a size of data operation. + * + * @param string a UTF-16 encoded string or {@code null}. + * @return a new {@link Utf8String}, {@link #EMPTY}, if {@code string} is empty, or {@link #NULL}, if {@code string} + * is {@code null}. + */ + @Nonnull + public static Utf8String transcodeUtf16(@Nullable final String string) { + if (string == null) { + return NULL; + } + if (string.isEmpty()) { + return EMPTY; + } + return new Utf8String(string); + } + + // endregion + + // region Privates + + private static int toCodePoint(final int utf8ByteSequence) { + + if ((utf8ByteSequence & 0b11111000_00000000_00000000_00000000) == 0b11110000_00000000_00000000_00000000) { + + // Map 4-byte UTF-8 encoding to code point in the [0x10000, 0x0FFFF] range + // + // UTF-8 encodings in this range have this bit pattern: + // + // Bits 24-31 = 0b11110VVV (byte 1) + // Bits 16-23 = 0b10ZZZZZZ (byte 2) + // Bits 08-15 = 0b10YYYYYY (byte 3) + // Bits 00-07 = 0b10XXXXXX (byte 4) + // + // The corresponding code point can be viewed as a 21-bit integer, 0bVVVZZZZZZYYYYYYXXXXXX. Hence, we map + // the UTF-8 code units into 3 bytes with the first 3 bits coming from the first (high order) byte, the + // next 6 bits from the second byte, the next 6 bits from the third byte, and the last 6 bits from the + // fourth (low order) byte. + + final int b1 = utf8ByteSequence & 0b00000111_00000000_00000000_00000000; + final int b2 = utf8ByteSequence & 0b00000000_00111111_00000000_00000000; + final int b3 = utf8ByteSequence & 0b00000000_00000000_00111111_00000000; + final int b4 = utf8ByteSequence & 0b00000000_00000000_00000000_00111111; + + return (b1 >> 6) | (b2 >> 4) | (b3 >> 2) | b4; + } + + if ((utf8ByteSequence & 0b11111111_11110000_00000000_00000000) == 0b00000000_11100000_00000000_00000000) { + + // Map 3-byte UTF-8 encoding to code point in the [0x0800, 0xFFFF] range + // + // UTF-8 encodings in this range have this bit pattern: + // + // Bits 24-31 = 0b00000000 + // Bits 16-23 = 0b1110ZZZZ (byte 1) + // Bits 08-15 = 0b10YYYYYY (byte 2) + // Bits 00-07 = 0b10XXXXXX (byte 3) + // + // The corresponding code point can be viewed as a 16-bit integer, 0bZZZZYYYYYYXXXXXX. Hence, we map the + // UTF-8 code units into 2 bytes with the first 3 bits coming from the first (high order) byte, the next 6 + // bits from the second (mid order) byte, and the last 6 bits from the third (low order) byte. + + final int b1 = utf8ByteSequence & 0b000011110000000000000000; + final int b2 = utf8ByteSequence & 0b000000000011111100000000; + final int b3 = utf8ByteSequence & 0b000000000000000000111111; + + return (b1 >> 4) | (b2 >> 2) | b3; + } + + if ((utf8ByteSequence & 0b11111111_11111111_11100000_00000000) == 0b00000000_00000000_11000000_00000000) { + + // Map 2-byte UTF-8 character encoding to code point in the [0x0080, 0x07FF] range + // + // UTF-8 Encodings in this this range have this bit pattern: + // + // Bits 24-31 = 0b00000000 + // Bits 16-23 = 0b00000000 + // Bits 08-15 = 0b110YYYYY (byte 1) + // Bits 00-07 = 0b10XXXXXX (byte 2) + // + // The corresponding code point can be viewed as an 11-bit integer, 0bYYYYYXXXXXX. Hence, we map the UTF-8 + // code units into 1 byte with the first 5 bits coming from the first (high order) byte and the final 6 + // bits coming from the second (low order) byte. + + final int b1 = utf8ByteSequence & 0b0001111100000000; + final int b2 = utf8ByteSequence & 0b0000000000111111; + + return (b1 >> 2) | b2; + } + + return -1; + } + + // endregion + + // region Types + + /** + * Enables a {@link Utf8String} to be deserialized by Jackson + */ + static final class JsonDeserializer extends StdDeserializer { + + private JsonDeserializer() { + super(Utf8String.class); + } + + @Override + public Utf8String deserialize(final JsonParser parser, final DeserializationContext context) throws IOException { + + final JsonNode node = parser.getCodec().readTree(parser); + final JsonNodeType type = node.getNodeType(); + + switch (type) { + case STRING: + return Utf8String.transcodeUtf16(node.textValue()); + case NULL: + return null; + default: { + String message = lenientFormat("expected string value or null, not %s", type.name().toLowerCase()); + throw new JsonParseException(parser, message); + } + } + } + } + + /** + * Enables a {@link Utf8String} to be serialized by Jackson + */ + static final class JsonSerializer extends StdSerializer { + + private JsonSerializer() { + super(Utf8String.class); + } + + @Override + public void serialize(final Utf8String value, final JsonGenerator generator, final SerializerProvider provider) throws IOException { + generator.writeString(value.toUtf16()); + } + } + + /** + * A {@link ByteProcessor} used to read a UTF-8 encoded string one code point at a time. + *

+ * This {@link #process(byte)} method reads a single code point at a time. The first byte read following + * construction of an instance of this class must be a leading byte. This is used to determine the number of + * UTF-8 code units (i.e., bytes) in the code point. + *

+ * Code points are validated. The {@link #process(byte)} method returns the Unicode + * Replacement Character + * when an undefined code point is encountered. + */ + private static class CodePointGetter implements ByteProcessor { + + private static final int REPLACEMENT_CHARACTER = 0xFFFD; + + private int codePoint = -1; + private int shift = -1; + + /** + * Processes the next byte in a UTF-8 encoded code point sequence. + * + * @param value the next byte in a UTF-8 encoded code point sequence. + * @return {@code true} if additional bytes must be read to complete the code point; otherwise, if the code + * point is complete, a value of {@code false} is returned. + */ + @Override + public boolean process(final byte value) { + + switch (this.shift) { + + default: { + + // Next unit (byte) of multi-byte code point sequence + + this.codePoint |= ((value & 0xFF) << this.shift); + this.shift -= Byte.SIZE; + return true; + } + case 0: { + + // End of multi-byte code point sequence + + this.shift = -1; + this.codePoint |= (value & 0xFF); + this.codePoint = toCodePoint(this.codePoint); + + if (!Character.isDefined(this.codePoint)) { + this.codePoint = REPLACEMENT_CHARACTER; + } + + return false; + } + case -1: { + + // Start of code point sequence + + final int leadingByte = value & 0xFF; + + if (leadingByte < 0x7F) { + // UTF-8-1 = 0x00-7F + this.codePoint = leadingByte; + return false; + } + + if (0xC2 <= leadingByte && leadingByte <= 0xDF) { + // UTF8-8-2 = 0xC2-DF UTF8-tail + this.codePoint = leadingByte << Byte.SIZE; + this.shift = 0; + return true; + } + + if (0xE0 <= leadingByte && leadingByte <= 0xEF) { + // UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2(UTF8-tail) + this.codePoint = leadingByte << 2 * Byte.SIZE; + this.shift = Byte.SIZE; + return true; + } + + if (0xF0 <= leadingByte && leadingByte <= 0xF4) { + // UTF-8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail ) + this.codePoint = leadingByte << (3 * Byte.SIZE); + this.shift = 2 * Byte.SIZE; + return true; + } + + this.codePoint = REPLACEMENT_CHARACTER; + return false; + } + } + } + + /** + * Returns the value of the most-recently read code point. + * + * @return value of the most-recently read code point. + */ + int codePoint() { + return this.codePoint; + } + } + + /** + * An iterator for enumerating the code points in a UTF-8 encoded {@link ByteBuf}. + */ + private static class CodePointIterator extends CodePointGetter implements PrimitiveIterator.OfInt { + + private final ByteBuf buffer; + private int start, length; + + CodePointIterator(final ByteBuf buffer) { + this.buffer = buffer; + this.start = 0; + this.length = buffer.writerIndex(); + } + + /** + * Returns {@code true} if there is another code point in the iteration. + * + * @return {@code true} if there is another code point in the iteration. + */ + @Override + public boolean hasNext() { + return this.start < this.length; + } + + /** + * Returns the next {@code int} code point in the iteration. + * + * @return the next {@code int} code point in the iteration. + * @throws NoSuchElementException if the iteration has no more code points. + */ + @Override + public int nextInt() { + + final int length = this.length - this.start; + + if (length <= 0) { + throw new NoSuchElementException(); + } + + final int index = this.buffer.forEachByte(this.start, length, this); + assert index >= 0; + this.start = index + 1; + + return this.codePoint(); + } + } + + /** + * A spliterator for enumerating the code points in a UTF-8 encoded {@link ByteBuf}. + *

+ * This class supports the {@link Utf8String#codePoints} method. + */ + private static final class CodePointSpliterator extends CodePointIterator implements Spliterator.OfInt { + + CodePointSpliterator(final ByteBuf buffer) { + super(buffer); + } + + @Override + public int characteristics() { + return Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED; + } + + @Override + public long estimateSize() { + return Long.MAX_VALUE; + } + + @Override + public void forEachRemaining(IntConsumer action) { + super.forEachRemaining(action); + } + + @Override + public void forEachRemaining(Consumer action) { + super.forEachRemaining(action); + } + + @Override + public boolean tryAdvance(IntConsumer action) { + checkNotNull(action, "expected non-null action"); + if (this.hasNext()) { + action.accept(this.nextInt()); + return true; + } + return false; + } + + @Override + public Spliterator.OfInt trySplit() { + return null; // Utf8String doesn't support parallel processing and so this method does not attempt a split + } + } + + /** + * A {@link ByteProcessor} used to validate the code point sequences in a UTF-8 encoded string. + *

+ * This {@link #process(byte)} method reads a single code point at a time. The first byte read following + * construction of an instance of this class must be a leading byte. This is used to determine the number of + * single-byte UTF-8 code units in the code point. The {@link #process(byte)} method returns {@code false} when + * an undefined code point is encountered as determined by {@link Character#isDefined(int)}}. + * + * @see RFC 3629: UTF-8, a transformation format of ISO 10646 + */ + private static class CodePointValidator implements ByteProcessor { + + private int codePoint = -1; + private int shift = -1; + + /** + * Processes the next byte in a UTF-8 encoded code point sequence. + * + * @param value a {@code byte} representing the next code unit in a UTF-8 code point sequence. + * + * @return {@code false} if the current code unit signals the end of an undefined code point; otherwise, a value + * of {@code true}. + */ + @Override + public boolean process(final byte value) { + + switch (this.shift) { + + default: { + + // Next unit (byte) of multi-byte code point sequence + + this.codePoint |= ((value & 0xFF) << this.shift); + this.shift -= Byte.SIZE; + return true; + } + case 0: { + + // End of multi-byte code point sequence + + this.codePoint |= (value & 0xFF); + this.shift = -1; + this.codePoint = toCodePoint(this.codePoint); + + return Character.isDefined(this.codePoint); + } + case -1: { + + // Start of code point sequence + + final int leadingByte = (value & 0xFF); + + if (leadingByte < 0x7F) { + // UTF-8-1 = 0x00-7F + this.codePoint = leadingByte; + return true; + } + + if (0xC2 <= leadingByte && leadingByte <= 0xDF) { + // UTF8-8-2 = 0xC2-DF UTF8-tail + this.codePoint = leadingByte << Byte.SIZE; + this.shift = 0; + return true; + } + + if (0xE0 <= leadingByte && leadingByte <= 0xEF) { + // UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2(UTF8-tail) + this.codePoint = leadingByte << 2 * Byte.SIZE; + this.shift = Byte.SIZE; + return true; + } + + if (0xF0 <= leadingByte && leadingByte <= 0xF4) { + // UTF8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail ) + this.codePoint = leadingByte << 3 * Byte.SIZE; + this.shift = 2 * Byte.SIZE; + return true; + } + + return false; + } + } + } + + /** + * Returns the value of the most-recently read code point. + * + * @return value of the most-recently read code point. + */ + int codePoint() { + return this.codePoint; + } + } + + /** + * A {@link ByteProcessor} used to count the number of UTF-16 code units in a UTF-8 encoded string. + *

+ * This class makes use of the fact that code points that UTF-16 encodes with two 16-bit code units, UTF-8 encodes + * with 4 8-bit code units, and vice versa. Lead bytes are identified and counted. All other bytes are skipped. + * Code points are not validated. + *

+ * The {@link #process} method counts undefined leading bytes as an undefined UTF-16 code unit to be replaced. + * + * @see RFC 3629: UTF-8, a transformation format of ISO 10646 + */ + private static final class UTF16CodeUnitCounter implements ByteProcessor { + + @JsonProperty + private final int charLimit; + + @JsonProperty + private int charCount = 0; + + @JsonProperty + private int charIndex = 0; + + @JsonProperty + private int skip = 0; + + public UTF16CodeUnitCounter() { + this(Integer.MAX_VALUE); + } + + public UTF16CodeUnitCounter(int charLimit) { + checkArgument(charLimit >= 0); + this.charLimit = charLimit; + } + + /** + * Number of UTF-16 code units processed. + * + * @return number of {@code char}'s processed. + */ + public int charCount() { + return this.charCount; + } + + /** + * {@code char} index of the most-recently processed code point. + * + * This is the value that would be used to address the {@code char} after converting the UTF-8 code point + * sequence to a {@link String}. + * + * @return {@code char} index of the most-recently processed code point. + */ + public int charIndex() { + return this.charIndex; + } + + /** + * Maximum number of UTF-16 code units to process. + * + * @return maximum number of UTF-16 code units to process. + */ + public int charLimit() { + return this.charLimit; + } + + /** + * Processes the next byte in a UTF-8 encoded code point sequence. + *

+ * The value of {@link #charCount} is increased at the end of each UTF-8 encoded code point that is encountered. + * The magnitude of the increase depends on the length of the code point. Code points of length 1-3 increase the + * {@link #charCount} by 1. Code points of length 4 increase {@link #charCount} by 2. + * + * @param value a {@code byte} representing the next code unit in a UTF-8 encoded code point sequence. + * @return {@code true} unless {@link #charLimit} is reached. + */ + @Override + public boolean process(final byte value) { + + if (this.skip > 0) { + this.skip--; + return true; + } + + final int leadingByte = value & 0xFF; + this.charIndex = this.charCount; + + if (leadingByte < 0x7F) { + // UTF-8-1 = 0x00-7F + this.skip = 0; + this.charCount++; + } else if (0xC2 <= leadingByte && leadingByte <= 0xDF) { + // UTF8-8-2 = 0xC2-DF UTF8-tail + this.skip = 1; + this.charCount++; + } else if (0xE0 <= leadingByte && leadingByte <= 0xEF) { + // UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2 + // (UTF8-tail) + this.skip = 2; + this.charCount++; + } else if (0xF0 <= leadingByte && leadingByte <= 0xF4) { + // UTF8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail ) + this.skip = 3; + this.charCount += 2; + } else { + this.skip = 0; + this.charCount++; + } + + return this.charCount <= this.charLimit; + } + + /** + * Represents this {@link UTF16CodeUnitCounter} as a JSON string. + * + * @return JSON string representation of this {@link UTF16CodeUnitCounter}. + */ + @Override + public String toString() { + return Json.toString(this); + } + } + + /** + * An iterator for enumerating the UTF-16 code units in a UTF-8 encoded {@link ByteBuf}. + *

+ * This class supports the {@link Utf8String#charAt} method. + */ + private static class UTF16CodeUnitIterator extends CodePointGetter implements PrimitiveIterator.OfInt { + + private final ByteBuf buffer; + private int lowSurrogate; + private int start, length; + + UTF16CodeUnitIterator(final ByteBuf buffer) { + this.buffer = buffer; + this.length = buffer.writerIndex(); + this.lowSurrogate = 0; + this.start = 0; + } + + /** + * Returns {@code true} if there is another UTF-16 code unit in the iteration. + * + * @return {@code true} if there is another UTF-16 code unit in the iteration. + */ + @Override + public boolean hasNext() { + return this.lowSurrogate != 0 || this.start < this.length; + } + + /** + * Returns the next {@code int} UTF-16 code unit in the iteration. + * + * @return the next {@code int} UTF-16 code unit in the iteration. + * @throws NoSuchElementException if the iteration has no more UTF-16 code units. + */ + @Override + public int nextInt() { + + if (this.lowSurrogate != 0) { + int codeUnit = this.lowSurrogate; + this.lowSurrogate = 0; + return codeUnit; + } + + final int length = this.length - this.start; + + if (length <= 0) { + throw new NoSuchElementException(); + } + + final int index = this.buffer.forEachByte(this.start, length, this); + assert index >= 0; + this.start = index + 1; + + final int codePoint = this.codePoint(); + + if ((codePoint & 0xFFFF0000) == 0) { + return codePoint; + } + + this.lowSurrogate = Character.lowSurrogate(codePoint); + return Character.highSurrogate(codePoint); + } + } + + /** + * A spliterator for enumerating the UTF-16 code units in a UTF-8 encoded {@link ByteBuf}. + *

+ * This class supports the {@link Utf8String#chars} method. + */ + private static final class UTF16CodeUnitSpliterator extends UTF16CodeUnitIterator implements Spliterator.OfInt { + + UTF16CodeUnitSpliterator(final ByteBuf buffer) { + super(buffer); + } + + @Override + public int characteristics() { + return Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED; + } + + @Override + public long estimateSize() { + return Long.MAX_VALUE; + } + + @Override + public void forEachRemaining(IntConsumer action) { + super.forEachRemaining(action); + } + + @Override + public void forEachRemaining(Consumer action) { + super.forEachRemaining(action); + } + + @Override + public boolean tryAdvance(IntConsumer action) { + checkNotNull(action, "expected non-null action"); + if (this.hasNext()) { + action.accept(this.nextInt()); + return true; + } + return false; + } + + @Override + public Spliterator.OfInt trySplit() { + return null; // Utf8String doesn't support parallel processing and so this method does not attempt a split + } + } + + /** + * A {@link ByteProcessor} used to convert a UTF-8 byte sequence to a {@link String}. + *

+ * This {@link #process(byte)} method accumulates a single code point at a time. Invalid code points are changed to + * Replacement Characters + */ + private static class UTF16Converter implements ByteProcessor { + + private static final int REPLACEMENT_CHARACTER = 0xFFFD; + + private final StringBuilder builder; + private int codePoint = -1; + private int shift = -1; + + UTF16Converter(final int capacity) { + this.builder = new StringBuilder(capacity); + } + + /** + * Processes the next byte in a UTF-8 encoded code point sequence. + * + * Characters are appended to the result value at the end of each code point sequence that is encountered. + * + * @param value the next byte in a UTF-8 encoded code point sequence. + * @return {@code true}. + */ + @Override + public boolean process(final byte value) { + + switch (this.shift) { + + default: { + + // Next unit (byte) of multi-byte code point sequence + + this.codePoint |= ((value & 0xFF) << this.shift); + this.shift -= Byte.SIZE; + return true; + } + case 0: { + + // End of multi-byte code point sequence + + this.codePoint = toCodePoint(this.codePoint | (value & 0xFF)); + + if (this.codePoint < 0) { + this.builder.append((char)REPLACEMENT_CHARACTER); + } else if (Character.isBmpCodePoint(this.codePoint)) { + this.builder.append((char)this.codePoint); + } else { + this.builder.append(Character.highSurrogate(this.codePoint)); + this.builder.append(Character.lowSurrogate(this.codePoint)); + } + + this.shift = -1; + return true; + } + case -1: { + + // Start of code point sequence + + final int leadingByte = value & 0xFF; + + if (leadingByte < 0x7F) { + // UTF-8-1 = 0x00-7F + this.builder.append((char)leadingByte); + return true; + } + + if (0xC2 <= leadingByte && leadingByte <= 0xDF) { + // UTF8-8-2 = 0xC2-DF UTF8-tail + this.codePoint = leadingByte << Byte.SIZE; + this.shift = 0; + return true; + } + + if (0xE0 <= leadingByte && leadingByte <= 0xEF) { + // UTF-8-3 = 0xE0 0xA0-BF UTF8-tail / 0xE1-EC 2(UTF8-tail) / 0xED 0x80-9F UTF8-tail / 0xEE-EF 2(UTF8-tail) + this.codePoint = leadingByte << 2 * Byte.SIZE; + this.shift = Byte.SIZE; + return true; + } + + if (0xF0 <= leadingByte && leadingByte <= 0xF4) { + // UTF-8-4 = 0xF0 0x90-BF 2( UTF8-tail ) / 0xF1-F3 3( UTF8-tail ) / 0xF4 0x80-8F 2( UTF8-tail ) + this.codePoint = leadingByte << (3 * Byte.SIZE); + this.shift = 2 * Byte.SIZE; + return true; + } + + this.builder.append((char)REPLACEMENT_CHARACTER); + return true; + } + } + } + + /** + * Returns the converted {@link String} value. + * + * A new {@link String} is allocated on each call to this method. + * + * @return the converted {@link String} value. + */ + String value() { + return this.builder.toString(); + } + } + + // endregion +} diff --git a/java/src/main/java/com/azure/data/cosmos/core/UtfAnyString.java b/java/src/main/java/com/azure/data/cosmos/core/UtfAnyString.java new file mode 100644 index 0000000..cfadd65 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/core/UtfAnyString.java @@ -0,0 +1,309 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import javax.annotation.Nonnull; + +import static com.azure.data.cosmos.core.Utf8String.transcodeUtf16; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A string whose memory representation may be either UTF-8 or UTF-16. + *

+ * This type supports polymorphic use of {@link String} and {@link Utf8String} when equality, hashing, and comparison + * are needed against either encoding. An API leveraging {@link UtfAnyString} can avoid separate method overloads + * while still accepting either encoding without imposing additional allocations. + */ +public final class UtfAnyString implements CharSequence, Comparable { + + public static final UtfAnyString EMPTY = new UtfAnyString(""); + public static final UtfAnyString NULL = new UtfAnyString(); + + private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381); + + private CharSequence buffer; + + public UtfAnyString(final String value) { + this.buffer = value; + } + + public UtfAnyString(final Utf8String value) { + this.buffer = value; + } + + private UtfAnyString() { + } + + private UtfAnyString(final CharSequence sequence) { + this.buffer = sequence; + } + + /** + * {@code true} if the {@link UtfAnyString} is empty. + * + * @return {@code true} if the {@link UtfAnyString} is empty. + */ + public boolean isEmpty() { + return this.buffer != null && this.buffer.length() == 0; + } + + /** + * {@code true} if the {@link UtfAnyString} is {@code null}. + * + * @return {@code true} if the {@link UtfAnyString} is {@code null}. + */ + public boolean isNull() { + return null == this.buffer; + } + + /** + * {@code true} if the underlying representation of the {@link UtfAnyString} is a {@link String}. + * + * @return {@code true} if the underlying representation of the {@link UtfAnyString} is a {@link String}. + */ + public boolean isUtf16() { + return this.buffer instanceof String; + } + + /** + * {@code true} if the underlying representation of the {@link UtfAnyString} is a {@link Utf8String}. + * + * @return {@code true} if the underlying representation of the {@link UtfAnyString} is a {@link Utf8String}. + */ + public boolean isUtf8() { + return this.buffer instanceof Utf8String; + } + + /** + * Returns the {@code char} value at the specified {@code index}. + *

+ * An index ranges from zero to {@link UtfAnyString#length()} minus one. The first {@code char} value of the + * sequence is at index zero, the next at index one, and so on, as for array indexing. If the {@code char} + * value specified by the {@code index} is a surrogate, the surrogate (not the surrogate pair) is returned. + * + * @param index the index of the {@code char} value to be returned. + * @return the specified {@code char} value + * @throws IndexOutOfBoundsException if the {@code index} argument is negative or not less than + * {@link UtfAnyString#length()} + * @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}. + */ + @Override + public char charAt(final int index) { + if (this.buffer == null) { + throw new UnsupportedOperationException("String is null"); + } + return this.buffer.charAt(index); + } + + public int compareTo(@Nonnull final String other) { + + checkNotNull(other, "expected non-null other"); + + if (other == this.buffer) { + return 0; + } + + if (this.buffer == null) { + return -1; + } + + return this.buffer instanceof String + ? ((String) this.buffer).compareTo(other) + : ((Utf8String) this.buffer).compareTo(other); + } + + public int compareTo(@Nonnull final Utf8String other) { + + checkNotNull(other, "expected non-null other"); + + if (other == this.buffer) { + return 0; + } + + if (this.buffer == null) { + return -1; + } + + return this.buffer instanceof String + ? -other.compareTo((String) this.buffer) + : ((Utf8String) this.buffer).compareTo(other); + } + + @Override + public int compareTo(@Nonnull final UtfAnyString other) { + + checkNotNull(other, "expected non-null other"); + + if (other.buffer == this.buffer) { + return 0; + } + + if (other.buffer == null) { + return 1; + } + + if (this.buffer == null) { + return -1; + } + + if (this.buffer instanceof String) { + return other.buffer instanceof String + ? ((String) this.buffer).compareTo((String) other.buffer) + : -((Utf8String) other.buffer).compareTo((String) this.buffer); + } + + return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer); + } + + public static UtfAnyString empty() { + return EMPTY; + } + + @Override + public boolean equals(final Object other) { + + if (other == null) { + return false; + } + + if (other instanceof String) { + return this.equals((String) other); + } + + if (other instanceof Utf8String) { + return this.equals((Utf8String) other); + } + + if (other instanceof UtfAnyString) { + return this.equals((UtfAnyString) other); + } + + return false; + } + + public boolean equals(final String other) { + + if (null == this.buffer) { + return null == other; + } + + if (this.buffer instanceof String) { + return other.contentEquals(this.buffer); // skips the type check that String.equals performs + } + + return ((Utf8String) this.buffer).equals(other); + } + + public boolean equals(final Utf8String other) { + + if (null == other) { + return null == this.buffer; + } + + return other.equals(this.buffer); + } + + public boolean equals(final UtfAnyString other) { + + if (null == other) { + return false; + } + + if (null == this.buffer) { + return null == other.buffer; + } + + return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer); + } + + @Override + public int hashCode() { + + final long[] hash = { 5_381, 5_381 }; + + if (this.buffer == null) { + return NULL_HASHCODE; + } + + if (this.buffer instanceof String) { + + final int ignored = ((String) this.buffer).codePoints().reduce(0, (index, codePoint) -> { + if (index % 2 == 0) { + hash[0] = ((hash[0] << 5) + hash[0]) ^ codePoint; + } else { + hash[1] = ((hash[1] << 5) + hash[1]) ^ codePoint; + } + return index; + }); + + return reduceHashCode(hash[0], hash[1]); + } + + return this.buffer.hashCode(); + } + + /** + * Returns the length of this character sequence. + *

+ * The length is the number of 16-bit {@code char}s in the sequence. + * + * @return the number of {@code char}s in this sequence. + * @throws UnsupportedOperationException if this {@link UtfAnyString} is {@code null}. + */ + @Override + public int length() { + if (this.buffer == null) { + throw new UnsupportedOperationException("String is null"); + } + return this.buffer.length(); + } + + /** + * Returns a {@code CharSequence} that is a subsequence of this sequence. + *

+ * The subsequence starts with the {@code char} value at the specified index and ends with the{@code char} value at + * index {@code end - 1}. The length (in {@code char}s) of the returned sequence is {@code end - start}, so if + * {@code start == end}, an empty sequence is returned. + * + * @param start the start index, inclusive + * @param end the end index, exclusive + * @return the specified subsequence + * @throws IndexOutOfBoundsException if {@code start} or {@code end} are negative, {@code end} is greater than + * {@link UtfAnyString#length()}, or {@code start} is greater than {@code + * end}. + * @throws UnsupportedOperationException if string is {@code null} + */ + @Override + @Nonnull + public CharSequence subSequence(final int start, final int end) { + if (this.buffer == null) { + throw new UnsupportedOperationException("String is null"); + } + return this.buffer.subSequence(start, end); + } + + @Override + @Nonnull + public String toString() { + return String.valueOf(this.buffer); + } + + public String toUtf16() { + if (null == this.buffer) { + return null; + } + return this.buffer instanceof String ? (String) this.buffer : this.buffer.toString(); + } + + public Utf8String toUtf8() { + if (null == this.buffer) { + return null; + } + return this.buffer instanceof String ? transcodeUtf16((String) this.buffer) : (Utf8String) this.buffer; + } + + private static int reduceHashCode(final long h1, final long h2) { + return Long.valueOf(h1 + (h2 * 1_566_083_941L)).intValue(); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java new file mode 100644 index 0000000..aeb75d4 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Float128.java @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +/** + * Represents an IEEE 754-2008 128-bit decimal floating point number. + *

+ * The {@link Float128} represents an IEEE 754-2008 floating point number as a pair of {@code long} values: + * {@link #high()} and {@link #low()}. + * + * @see decimal128 floating-point format + * @see 754-2008: IEEE Standard for Floating-Point Arithmetic + * @see Decimal Arithmetic Encodings Version 1.01 – 7 Apr 2009 + */ +public final class Float128 { + + /** + * The size (in bytes) of a {@link Float128}. + */ + public static final int BYTES = 2 * Long.BYTES; + public static final Float128 ZERO = new Float128(0L, 0L); + + private final long high; + private final long low; + + /** + * Initializes a new instance of the {@link Float128} struct. + * + * @param high the high-order 64 bits. + * @param low the low-order 64 bits. + */ + public Float128(long high, long low) { + this.high = high; + this.low = low; + } + + /** + * The high-order 64 bits of the IEEE 754-2008 128-bit decimal floating point, using the BID encoding scheme. + * + * @return the high-order 64 bits of the IEEE 754-2008 128-bit floating point number represented by this object. + */ + public long high() { + return this.high; + } + + /** + * The low-order 64 bits of the IEEE 754-2008 128-bit decimal floating point, using the BID encoding scheme. + * + * @return the low-order 64 bits of the IEEE 754-2008 128-bit floating point number represented by this object. + */ + public long low() { + return this.low; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java new file mode 100644 index 0000000..085c130 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HashCode128.java @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.Immutable; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * An immutable 128-bit hash code. + * + * The hash code is represented by two {@code long} values: {@link #low()} and {@link #high()}. + */ +@Immutable +public class HashCode128 { + + private final long high; + private final long low; + + private HashCode128(final long low, final long high) { + this.low = low; + this.high = high; + } + + private HashCode128(ByteBuf buffer) { + this.low = buffer.readLongLE(); + this.high = buffer.readLongLE(); + } + + public long high() { + return this.high; + } + + public long low() { + return this.low; + } + + @Nonnull + public static HashCode128 from(@Nonnull final byte[] buffer) { + + checkNotNull(buffer, "expected non-null buffer"); + checkArgument(buffer.length >= 2 * Long.BYTES, "expected buffer length >= 16, not %s", buffer.length); + + return new HashCode128(Unpooled.wrappedBuffer(buffer)); + } + + /** + * Reads a {@link HashCode128} from a {@link ByteBuf}. + *

+ * The hash code is read as a pair of long values serialized in little-endian format. The values are read from the + * buffer's current reader index which is advanced by 16 bytes: the length of two long values. + * + * @param buffer The buffer from which to read the hash code. + * @return The hash code read. + */ + @Nonnull + public static HashCode128 from(@Nonnull final ByteBuf buffer) { + + checkNotNull(buffer, "expected non-null buffer"); + + final int length = buffer.writerIndex() - buffer.readerIndex(); + checkArgument(length >= 2 * Long.BYTES, "expected at least 16 readable bytes in buffer, not %s", length); + + return new HashCode128(buffer); + } + + @Nonnull + public static HashCode128 of(long low, long high) { + return new HashCode128(low, high); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java new file mode 100644 index 0000000..df3b078 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowHeader.java @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Describes the header that precedes all valid Hybrid Rows. + */ +public final class HybridRowHeader { + /** + * Size (in bytes) of a serialized header. + */ + public static final int BYTES = HybridRowVersion.BYTES + SchemaId.BYTES; + + private final SchemaId schemaId; + private final HybridRowVersion version; + + /** + * Initializes a new instance of a {@link HybridRowHeader}. + * + * @param version The version of the HybridRow library used to write this row. + * @param schemaId The unique identifier of the schema whose layout was used to write this row. + */ + public HybridRowHeader(@Nonnull final HybridRowVersion version, @Nonnull SchemaId schemaId) { + + checkNotNull(version, "expected non-null version"); + checkNotNull(schemaId, "expected non-null schemaId"); + + this.version = version; + this.schemaId = schemaId; + } + + /** + * The unique identifier of the schema whose layout was used to write this {@link HybridRowHeader}. + * + * @return unique identifier of the schema whose layout was used to write this {@link HybridRowHeader}. + */ + @Nonnull + public SchemaId schemaId() { + return this.schemaId; + } + + /** + * The version of the HybridRow serialization library used to write this {@link HybridRowHeader}. + * + * @return version of the HybridRow serialization library used to write this {@link HybridRowHeader}. + */ + @Nonnull + public HybridRowVersion version() { + return this.version; + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..f60b370 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/HybridRowVersion.java @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +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. + *

+ * A version from this list MUST be inserted in the version BOM at the beginning of all rows. + */ +public enum HybridRowVersion { + + INVALID((byte)0), + + /** + * Initial version of the HybridRow format. + */ + V1((byte)0x81); + + public static final int BYTES = Byte.BYTES; + + 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); + }); + + private final byte value; + + HybridRowVersion(final byte value) { + this.value = value; + } + + public static HybridRowVersion from(final byte value) { + return mappings.get().get(value); + } + + public byte value() { + return this.value; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/NullValue.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/NullValue.java new file mode 100644 index 0000000..f2b9294 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/NullValue.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +/** + * The literal null value. + *

+ * May be stored hybrid row to indicate the literal null value. Typically this value should not be used and the + * corresponding column should be absent from the row. + */ +public final class NullValue { + /** + * The default null literal. + * This is the same value as default({@link NullValue}). + */ + public static final NullValue DEFAULT = new NullValue(); + + /** + * Returns true if this is the same value as {@code other}. + * + * @param other The value to compare against. + * @return True if the two values are the same. + */ + public boolean equals(NullValue other) { + return true; + } + + @Override + public boolean equals(Object other) { + if (null == other) { + return false; + } + return other instanceof NullValue && this.equals((NullValue)other); + } + + @Override + public int hashCode() { + return 42; + } +} \ 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 new file mode 100644 index 0000000..50843a2 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/Result.java @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +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 { + + SUCCESS(0), + FAILURE(1), + NOT_FOUND(2), + EXISTS(3), + TOO_BIG(4), + + /** + * The type of an existing field does not match the expected type for this operation. + */ + TYPE_MISMATCH(5), + + /** + * An attempt to write in a read-only scope. + */ + INSUFFICIENT_PERMISSIONS(6), + + /** + * An attempt to write a field that did not match its (optional) type constraints. + */ + TYPE_CONSTRAINT(7), + + /** + * The byte sequence could not be parsed as a valid row. + */ + INVALID_ROW(8), + + /** + * The byte sequence was too short for the requested action. + */ + INSUFFICIENT_BUFFER(9), + + /** + * The operation was cancelled. + */ + CANCELED(10); + + public static final int BYTES = Integer.BYTES; + + 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; + } + + public static Result from(int value) { + return mappings.get().get(value); + } + + public int value() { + return this.value; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java new file mode 100644 index 0000000..03b21ac --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowBuffer.java @@ -0,0 +1,3761 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.codecs.DateTimeCodec; +import com.azure.data.cosmos.serialization.hybridrow.codecs.DecimalCodec; +import com.azure.data.cosmos.serialization.hybridrow.codecs.Float128Codec; +import com.azure.data.cosmos.serialization.hybridrow.codecs.GuidCodec; +import com.azure.data.cosmos.serialization.hybridrow.io.RowWriter; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutArray; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBinary; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBit; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBoolean; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutDecimal; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutEndScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat128; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutGuid; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt16; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutMongoDbObjectId; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutNull; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutNullable; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutObject; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTagged; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTagged2; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTuple; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypeScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedArray; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedMap; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedSet; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedTuple; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypes; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUDT; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt16; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUtf8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutVarInt; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutVarUInt; +import com.azure.data.cosmos.serialization.hybridrow.layouts.StringToken; +import com.azure.data.cosmos.serialization.hybridrow.layouts.StringTokenizer; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; +import com.azure.data.cosmos.serialization.hybridrow.layouts.UpdateOptions; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.lenientFormat; + +// import com.azure.data.cosmos.serialization.hybridrow.RowBuffer.UniqueIndexItem; + +//import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypes.MongoDbObjectId; + +/** + * Manages a sequence of bytes representing a Hybrid Row. + *

+ * A Hybrid Row begins in the 0-th byte of the {@link RowBuffer}. The sequence of bytes is defined by the Hybrid Row + * grammar. + */ +public final class RowBuffer { + + private final ByteBuf buffer; + private LayoutResolver resolver; + + /** + * Initializes a new instance of a {@link RowBuffer}. + * + * @param capacity Initial buffer capacity. + */ + public RowBuffer(int capacity) { + this(capacity, ByteBufAllocator.DEFAULT); + } + + /** + * Initializes a new instance of a {@link RowBuffer}. + * + * @param capacity Initial buffer capacity + * @param allocator A buffer allocator + */ + public RowBuffer(final int capacity, @Nonnull final ByteBufAllocator allocator) { + checkArgument(capacity > 0, "capacity: %s", capacity); + checkNotNull(allocator, "expected non-null allocator"); + this.buffer = allocator.buffer(capacity); + this.resolver = null; + } + + /** + * Initializes a new instance of a {@link RowBuffer} from an existing buffer. + * + * @param buffer An existing {@link ByteBuf} containing a Hybrid Row. This instance takes ownership of the buffer. + * Hence, the caller should not maintain a reference to the buffer or mutate the buffer after this + * call returns. + * @param version The version of the Hybrid Row format to use for encoding the buffer. + * @param resolver The resolver for UDTs. + */ + public RowBuffer( + @Nonnull final ByteBuf buffer, + @Nonnull final HybridRowVersion version, + @Nonnull final LayoutResolver resolver) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(version, "expected non-null version"); + checkNotNull(resolver, "expected non-null resolver"); + + final int length = buffer.writerIndex(); + + checkArgument(length >= HybridRowHeader.BYTES, + "expected buffer with at least %s, not %s bytes", HybridRowHeader.BYTES, length); + + this.buffer = buffer; + this.resolver = resolver; + + final Item item = this.read(this::readHeader, 0); + final HybridRowHeader header = item.value(); + checkState(header.version() == version, "expected header version %s, not %s", version, header.version()); + + final Layout layout = resolver.resolve(header.schemaId()); + checkState(header.schemaId().equals(layout.schemaId())); + checkState(HybridRowHeader.BYTES + layout.size() <= this.length()); + } + + /** + * Compute the byte offset from the beginning of the row for a given variable's value. + * + * @param layout The (optional) layout of the current scope. + * @param scopeOffset The zero-based offset to the beginning of the scope's value. + * @param varIndex The zero-based index of the variable within the variable segment. + * @return The byte offset from the beginning of the row where the variable's value should be located. + */ + public int computeVariableValueOffset(@Nullable final Layout layout, final int scopeOffset, final int varIndex) { + + checkArgument(scopeOffset >= 0, "expected non-negative scopeOffset, not %s", scopeOffset); + checkArgument(varIndex >= 0, "expected non-negative varIndex, not %s", varIndex); + + if (layout == null) { + return scopeOffset; + } + + final List columns = layout.columns(); + final int index = layout.numFixed() + varIndex; + checkState(index <= columns.size()); + + int offset = scopeOffset + layout.size(); + + for (int i = layout.numFixed(); i < index; i++) { + + LayoutColumn column = columns.get(i); + + if (this.readBit(scopeOffset, column.nullBit())) { + Item item = this.read(this::read7BitEncodedUInt, offset); + if (column.type().isVarint()) { + offset += item.length(); + } else { + offset += item.length() + item.value(); + } + } + } + + return offset; + } + + /** + * Compute the number of bytes necessary to store the unsigned 32-bit integer value using the varuint encoding. + * + * @param value the value to be encoded + * @return the number of bytes needed to store the varuint encoding of {@code value} + */ + public static int count7BitEncodedUInt(long value) { + checkArgument(0 <= value && value <= 0x00000000FFFFFFFFL, "value: %s", value); + int i = 0; + while (value >= 0x80L) { + i++; + value >>>= 7; + } + i++; + return i; + } + + /** + * Decrement the unsigned 32-bit integer value at the given {@code offset} in this {@link RowBuffer}. + * + * @param offset offset of a 32-bit unsigned integer value in this {@link RowBuffer}. + * @param decrement the decrement value. + */ + public void decrementUInt32(int offset, long decrement) { + long value = this.buffer.getUnsignedIntLE(offset); + this.buffer.setIntLE(offset, (int) (value - decrement)); + } + + /** + * Delete the sparse field at the specified cursor position. + * + * @param edit identifies the field to delete + */ + public void deleteSparse(@Nonnull final RowCursor edit) { + + checkNotNull(edit, "expected non-null edit"); + + if (!edit.exists()) { + return; // do nothing + } + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(0, edit, edit.cellType(), edit.cellTypeArgs(), RowOptions.DELETE, metaBytes, spaceNeeded, shift); + + checkState(this.length() == priorLength + shift.get()); + } + + /** + * Delete the variable-length field at a specified {@code offset}. + *

+ * The field is interpreted as either a variable-length integer or a variable-length sequence of bytes as indicated + * by the value of {@code isVarint}. + * + * @param offset index of the field in this {@link RowBuffer} + * @param isVarint {@code true}, if the field should be interpreted as a variable-length integer value; + * {@code false}, if the field should be interpreted as a variable-length sequence of bytes. + */ + public void deleteVariable(final int offset, final boolean isVarint) { + + final Item item = this.read(this::read7BitEncodedUInt, offset); + + final int source = isVarint + ? offset + item.length() // because this is a varint value + : offset + item.length() + item.value().intValue(); // because this is a variable-length sequence of bytes + + final int length = this.buffer.writerIndex() - source; + + this.buffer.setBytes(offset, this.buffer, source, length); + this.buffer.writerIndex(this.buffer.writerIndex() - length); + } + + /** + * The root header of this {@link RowBuffer}. + * + * @return root header of this {@link RowBuffer}. + */ + public HybridRowHeader header() { + return this.readHeader(); + } + + // TODO: DANOBLE: ressurrect this method + // public void WriteSparseMongoDbObjectId(@Nonnull final RowCursor edit, MongoDbObjectId value, + // UpdateOptions options) { + // int numBytes = MongoDbObjectId.Size; + // int metaBytes; + // final Out metaBytes = new Out<>(); + // int spaceNeeded; + // final Out spaceNeeded = new Out<>(); + // int shift; + // final Out shift = new Out<>(); + // this.ensureSparse(numBytes, edit, MongoDbObjectId, TypeArgumentList.EMPTY, options, + // metaBytes, spaceNeeded, shift); + // this.writeSparseMetadata(edit, MongoDbObjectId, TypeArgumentList.EMPTY, metaBytes); + // this.WriteMongoDbObjectId(edit.valueOffset(), value.clone()); + // checkState(spaceNeeded == metaBytes + MongoDbObjectId.Size); + // edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + // this.buffer.writerIndex(this.length() + shift); + // } + + /** + * Decrement the unsigned 32-bit integer value at the given {@code offset} in this {@link RowBuffer}. + * + * @param offset offset of a 32-bit unsigned integer value in this {@link RowBuffer}. + * @param increment the increment value. + */ + public void incrementUInt32(final int offset, final long increment) { + final long value = this.buffer.getUnsignedIntLE(offset); + this.buffer.setIntLE(offset, (int) (value + increment)); + } + + /** + * Initializes a row to the minimal size for the given layout. + * + * @param version The version of the Hybrid Row format to use for encoding this row. + * @param layout The layout that describes the column layout of the row. + * @param resolver The resolver for UDTs. + *

+ * The row is initialized to default row for the given layout. All fixed columns have their + * default values. All variable columns are null. No sparse columns are present. The row is + * valid. + */ + public void initLayout(HybridRowVersion version, Layout layout, LayoutResolver resolver) { + + checkNotNull(version, "expected non-null version"); + checkNotNull(layout, "expected non-null layout"); + checkNotNull(resolver, "expected non-null resolver"); + + this.writeHeader(new HybridRowHeader(version, layout.schemaId())); + this.buffer.writeZero(layout.size()); + this.resolver = resolver; + } + + /** + * The length of this {@link RowBuffer} in bytes. + * + * @return The length of this {@link RowBuffer} in bytes. + */ + public int length() { + return this.buffer.writerIndex(); + } + + /** + * Compute the byte offsets from the beginning of the row for a given sparse field insertion. + * into a set/map. + * + * @param scope The sparse scope to insert into. + * @param srcEdit The field to move into the set/map. + * @return The prepared edit context. + */ + @Nonnull + public RowCursor prepareSparseMove(@Nonnull final RowCursor scope, @Nonnull final RowCursor srcEdit) { + + checkNotNull(srcEdit, "expected non-null srcEdit"); + checkNotNull(scope, "expected non-null scope"); + checkArgument(scope.index() == 0); + checkArgument(scope.scopeType().isUniqueScope()); + + RowCursor dstEdit = scope.clone().metaOffset(scope.valueOffset()); + int srcSize = this.sparseComputeSize(srcEdit); + int srcBytes = srcSize - (srcEdit.valueOffset() - srcEdit.metaOffset()); + + while (dstEdit.index() < dstEdit.count()) { + + this.readSparseMetadata(dstEdit); + checkState(dstEdit.pathOffset() == 0); + + int elmSize = -1; // defer calculating the full size until needed + int cmp; + + if (scope.scopeType() instanceof LayoutTypedMap) { + cmp = this.compareKeyValueFieldValue(srcEdit, dstEdit); + } else { + elmSize = this.sparseComputeSize(dstEdit); + int elmBytes = elmSize - (dstEdit.valueOffset() - dstEdit.metaOffset()); + cmp = this.compareFieldValue(srcEdit, srcBytes, dstEdit, elmBytes); + } + + if (cmp <= 0) { + dstEdit.exists(cmp == 0); + return dstEdit; + } + + elmSize = elmSize == -1 ? this.sparseComputeSize(dstEdit) : elmSize; + dstEdit.index(dstEdit.index() + 1); + dstEdit.metaOffset(dstEdit.metaOffset() + elmSize); + } + + dstEdit.exists(false); + dstEdit.cellType(LayoutTypes.END_SCOPE); + dstEdit.valueOffset(dstEdit.metaOffset()); + + return dstEdit; + } + + /** + * Read the value of a bit within the bit field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a bit field within this {@link RowBuffer}. + * @param bit the bit to read. + * @return {@code true} if the {@code bit} is set, otherwise {@code false}. + */ + public boolean readBit(final int offset, @Nonnull final LayoutBit bit) { + + checkNotNull(bit, "expected non-null bit"); + + if (bit.isInvalid()) { + return true; + } + + Item item = this.read(() -> (this.buffer.readByte() & (byte) (1 << bit.bit())) != 0, bit.offset(offset)); + return item.value(); + } + + /** + * Read the value of the {@code DateTime} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code DateTime} field within this {@link RowBuffer}. + * @return the {@code DateTime} value read. + */ + public OffsetDateTime readDateTime(int offset) { + Item item = this.read(() -> DateTimeCodec.decode(this.buffer), offset); + return item.value(); + } + + // TODO: DANOBLE: resurrect this method + // public MongoDbObjectId ReadMongoDbObjectId(int offset) { + // return MemoryMarshal.Read(this.buffer.Slice(offset)); + // } + + /** + * Read the value of the {@code Decimal} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Decimal} field within this {@link RowBuffer}. + * @return the {@code Decimal} value read. + */ + public BigDecimal readDecimal(int offset) { + Item item = this.read(() -> DecimalCodec.decode(this.buffer), offset); + return item.value(); + } + + /** + * Read the value of a {@code FixedBinary} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code FixedBinary} field within this {@link RowBuffer}. + * @param length number of bytes to read. + * @return the {@code FixedBinary} value read. + */ + public ByteBuf readFixedBinary(int offset, int length) { + Item item = this.read(() -> this.buffer.readSlice(length), offset); + return item.value(); + } + + /** + * Read the value of a {@code FixedString} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code FixedString} field within this {@link RowBuffer}. + * @param length number of bytes in the {@code FixedString} field. + * @return the {@code FixedString} value read. + */ + public Utf8String readFixedString(int offset, int length) { + Item item = this.read(this::readFixedString, offset, length); + return item.value(); + } + + /** + * Read the value of a {@code Float128} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Float128} field within this {@link RowBuffer}. + * @return the {@code Float128} value read. + */ + public Float128 readFloat128(int offset) { + Item item = this.read(this::readFloat128, offset); + return item.value(); + } + + /** + * Read the value of a {@code Float32} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Float32} field within this {@link RowBuffer}. + * @return the {@code Float32} value read. + */ + public float readFloat32(int offset) { + Item item = this.read(this.buffer::readFloatLE, offset); + return item.value(); + } + + /** + * Read the value of a {@code Float64} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Float64} field within this {@link RowBuffer}. + * @return the {@code Float64} value read. + */ + public double readFloat64(int offset) { + Item item = this.read(this.buffer::readDoubleLE, offset); + return item.value(); + } + + // TODO: DANOBLE: resurrect this method + // public MongoDbObjectId ReadSparseMongoDbObjectId(Reference edit) { + // this.readSparsePrimitiveTypeCode(edit, MongoDbObjectId); + // edit.endOffset = edit.valueOffset() + MongoDbObjectId.Size; + // return this.ReadMongoDbObjectId(edit.valueOffset()).clone(); + // } + + /** + * Reads in the contents of the current {@link RowBuffer} from an {@link InputStream}. + *

+ * The {@link RowBuffer} is initialized with the associated layout and row {@code version}. + * + * @param inputStream the stream from which the contents of the current {@link RowBuffer} should be read + * @param byteCount the number of bytes to be read from the {@code inputStream} + * @param version the {@link HybridRowVersion} to be assigned to the current {@link RowBuffer} + * @param resolver the layout resolver to be used in parsing the {@code inputStream} + * @return {@code true} if the read succeeded; otherwise, if the {@link InputStream} was corrupted, {@code false} + */ + public boolean readFrom( + @Nonnull final InputStream inputStream, final int byteCount, @Nonnull final HybridRowVersion version, + @Nonnull final LayoutResolver resolver) { + + checkNotNull(inputStream, "expected non-null inputStream"); + checkNotNull(resolver, "expected non-null resolver"); + checkNotNull(version, "expected non-null version"); + checkState(byteCount >= HybridRowHeader.BYTES, "expected byteCount >= %s, not %s", HybridRowHeader.BYTES, + byteCount); + + this.reset(); + this.ensure(byteCount); + this.resolver = resolver; + + final int bytesRead; + + try { + bytesRead = this.buffer.writeBytes(inputStream, byteCount); + } catch (IOException error) { + return false; + } + + if (bytesRead != byteCount) { + return false; + } + + return this.validateHeader(version); + } + + /** + * Reads the contents of the current {@link RowBuffer} from a {@link ByteBuf}. + *

+ * The {@link RowBuffer} is initialized with a copy of the specified input {@link ByteBuf} and the associated layout + * and row {@code version}. + * + * @param input the buffer from which the contents of the current {@link RowBuffer} should be read + * @param version the {@link HybridRowVersion} to be assigned to the current {@link RowBuffer} + * @param resolver the layout resolver to be used in parsing the {@code inputStream} + * @return {@code true} if the read succeeded; otherwise, if the {@link InputStream} was corrupted, {@code false} + */ + public boolean readFrom( + @Nonnull final ByteBuf input, @Nonnull final HybridRowVersion version, @Nonnull final LayoutResolver resolver) { + + checkNotNull(input, "expected non-null input"); + checkNotNull(version, "expected non-null version"); + checkNotNull(resolver, "expected non-null resolver"); + checkState(input.readableBytes() >= HybridRowHeader.BYTES); + + this.reset(); + this.resolver = resolver; + this.buffer.writeBytes(this.buffer); + + return this.validateHeader(version); + } + + /** + * Read the value of a {@code Guid} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Guid} field within this {@link RowBuffer}. + * @return the {@code Guid} value read. + */ + public UUID readGuid(int offset) { + return this.read(() -> GuidCodec.decode(this.buffer), offset).value(); + } + + /** + * Read the value of a {@code Header} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Header} field within this {@link RowBuffer}. + * @return the {@code Header} value read. + */ + public HybridRowHeader readHeader(int offset) { + return this.read(this::readHeader, offset).value(); + } + + /** + * Read the value of a {@code Int16} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Int16} field within this {@link RowBuffer}. + * @return the {@code Int16} value read. + */ + public short readInt16(int offset) { + return this.read(this.buffer::readShortLE, offset).value(); + } + + /** + * Read the value of a {@code Int32} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Int32} field within this {@link RowBuffer}. + * @return the {@code Int32} value read. + */ + public int readInt32(int offset) { + Item item = this.read(this.buffer::readIntLE, offset); + return item.value(); + } + + /** + * Read the value of a {@code Int64} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Int64} field within this {@link RowBuffer}. + * @return the {@code Int64} value read. + */ + public long readInt64(int offset) { + Item item = this.read(this.buffer::readLongLE, offset); + return item.value(); + } + + /** + * Read the value of a {@code Int8} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code Int8} field within this {@link RowBuffer}. + * @return the {@code Int8} value read. + */ + public byte readInt8(int offset) { + Item item = this.read(this.buffer::readByte, offset); + return item.value(); + } + + /** + * Read the value of a {@code SchemaId} field at the given {@code offset} within this {@link RowBuffer}. + * + * @param offset offset of a {@code SchemaId} field within this {@link RowBuffer}. + * @return the {@code SchemaId} value read. + */ + public SchemaId readSchemaId(int offset) { + Item item = this.read(() -> SchemaId.from(this.buffer.readIntLE()), offset); + return item.value(); + } + + /** + * Read the value of a {@code SparseBinary} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseBinary} field within this {@link RowBuffer}. + * @return the {@code SparseBinary} value read. + */ + public ByteBuf readSparseBinary(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.BINARY); + Item item = this.read(this::readVariableBinary, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseBoolean} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseBoolean} field within this {@link RowBuffer}. + * @return the {@code SparseBoolean} value read. + */ + public boolean readSparseBoolean(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.BOOLEAN); + edit.endOffset(edit.valueOffset()); + return edit.cellType() == LayoutTypes.BOOLEAN; + } + + /** + * Read the value of a {@code SparseDateTime} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseDateTime} field within this {@link RowBuffer}. + * @return the {@code SparseDateTime} value read. + */ + public OffsetDateTime readSparseDateTime(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.DATE_TIME); + edit.endOffset(edit.valueOffset() + Long.SIZE); + return this.readDateTime(edit.valueOffset()); + } + + /** + * Read the value of a {@code SparseDecimal} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseDecimal} field within this {@link RowBuffer}. + * @return the {@code SparseDecimal} value read. + */ + public BigDecimal readSparseDecimal(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.DECIMAL); + Item item = this.read(this::readDecimal, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseFloat128} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseFloat128} field within this {@link RowBuffer}. + * @return the {@code SparseFloat128} value read. + */ + public Float128 readSparseFloat128(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.FLOAT_128); + Item item = this.read(this::readFloat128, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseFloat32} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseFloat32} field within this {@link RowBuffer}. + * @return the {@code SparseFloat32} value read. + */ + public float readSparseFloat32(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.FLOAT_32); + Item item = this.read(this.buffer::readFloatLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseFloat64} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseFloat64} field within this {@link RowBuffer}. + * @return the {@code SparseFloat64} value read. + */ + public double readSparseFloat64(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.FLOAT_64); + Item item = this.read(this.buffer::readDoubleLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseGuid} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseGuid} field within this {@link RowBuffer}. + * @return the {@code SparseGuid} value read. + */ + public UUID readSparseGuid(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.GUID); + Item item = this.read(this::readGuid, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseInt16} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseInt16} field within this {@link RowBuffer}. + * @return the {@code SparseInt16} value read. + */ + public short readSparseInt16(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.INT_16); + Item item = this.read(this.buffer::readShortLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseInt32} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseInt32} field within this {@link RowBuffer}. + * @return the {@code SparseInt32} value read. + */ + public int readSparseInt32(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.INT_32); + Item item = this.read(this.buffer::readIntLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseInt64} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseInt64} field within this {@link RowBuffer}. + * @return the {@code SparseInt64} value read. + */ + public long readSparseInt64(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.INT_64); + Item item = this.read(this.buffer::readLongLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseInt8} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseInt8} field within this {@link RowBuffer}. + * @return the {@code SparseInt8} value read. + */ + public byte readSparseInt8(RowCursor edit) { + // TODO: Remove calls to readSparsePrimitiveTypeCode once moved to V2 read. + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.INT_8); + Item item = this.read(this.buffer::readByte, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseNull} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseNull} field within this {@link RowBuffer}. + * @return the {@code SparseNull} value read. + */ + public NullValue readSparseNull(@Nonnull RowCursor edit) { + + checkNotNull(edit, "expected non-null edit"); + + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.NULL); + edit.endOffset(edit.valueOffset()); + + return NullValue.DEFAULT; + } + + /** + * Read the value of a {@code SparsePath} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparsePath} field within this {@link RowBuffer}. + * @return the {@code SparsePath} value read. + */ + public Utf8String readSparsePath(@Nonnull final RowCursor edit) { + + checkNotNull(edit, "expected non-null edit"); + + final StringTokenizer tokenizer = edit.layout().tokenizer(); + final Optional path = tokenizer.tryFindString(edit.pathToken()); + + if (path.isPresent()) { + return path.get(); + } + + final int length = edit.pathToken() - tokenizer.count(); + Item item = this.read(this::readFixedString, edit.pathOffset(), length); + + return item.value(); + } + + /** + * Read the value of a {@code SparsePathLen} field at the given {@code offset} position. + * + * @param layout layout of the {@code SparsePathLen} field. + * @param offset position of the {@code SparsePathLen} field.. + * @param pathOffset [output] position of the {@code SparsePathLen} field value. + * @param pathLengthInBytes [output] length of the {@code SparsePathLen} field value. + * @return the {@code SparsePathLen} value read. + */ + public int readSparsePathLen( + @Nonnull final Layout layout, + final int offset, + @Nonnull final Out pathOffset, + @Nonnull final Out pathLengthInBytes) { + + checkNotNull(layout, "expected non-null layout"); + checkNotNull(pathOffset, "expected non-null pathOffset"); + checkNotNull(pathLengthInBytes, "expected non-null pathLengthInBytes"); + + final Item item = this.read(this::read7BitEncodedUInt, offset); + final int token = item.value().intValue(); + + if (token < layout.tokenizer().count()) { + pathLengthInBytes.set(item.length()); + pathOffset.set(offset); + return token; + } + + final int numBytes = token - layout.tokenizer().count(); + pathLengthInBytes.set(numBytes + item.length()); + pathOffset.set(offset + item.length()); + + return token; + } + + /** + * Read the value of a {@code SparseString} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseString} field within this {@link RowBuffer}. + * @return the {@code SparseString} value read. + */ + public Utf8String readSparseString(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.UTF_8); + Item item = this.read(this::readUtf8String, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseTypeCode} field at the given {@code offset} position. + * + * @param offset position of a {@code SparseTypeCode} field within this {@link RowBuffer}. + * @return the {@code SparseTypeCode} value read. + */ + public LayoutType readSparseTypeCode(int offset) { + byte value = this.readInt8(offset); + LayoutCode code = LayoutCode.from(value); + checkState(code != null, "expected layout code at offset %s, not %s", offset, code); + return LayoutType.fromLayoutCode(code); + } + + /** + * Read the value of a {@code SparseUInt16} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseUInt16} field within this {@link RowBuffer}. + * @return the {@code SparseUInt16} value read. + */ + public int readSparseUInt16(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.UINT_16); + Item item = this.read(this.buffer::readUnsignedShortLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseUInt32} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseUInt32} field within this {@link RowBuffer}. + * @return the {@code SparseUInt32} value read. + */ + public long readSparseUInt32(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.UINT_32); + Item item = this.read(this.buffer::readUnsignedIntLE, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseUInt64} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseUInt64} field within this {@link RowBuffer}. + * @return the {@code SparseUInt64} value read. + */ + public long readSparseUInt64(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.UINT_64); + Item item = this.read(this.buffer::readLongLE, edit); + return item.value; + } + + /** + * Read the value of a {@code SparseUInt8} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseUInt8} field within this {@link RowBuffer}. + * @return the {@code SparseUInt8} value read. + */ + public short readSparseUInt8(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.UINT_8); + Item item = this.read(this.buffer::readUnsignedByte, edit); + return item.value; + } + + /** + * Read the value of a {@code SparseUnixDateTime} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseUnixDateTime} field within this {@link RowBuffer}. + * @return the {@code SparseUnixDateTime} value read. + */ + public UnixDateTime readSparseUnixDateTime(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.UNIX_DATE_TIME); + Item item = this.read(this::readUnixDateTime, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseVarInt} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseVarInt} field within this {@link RowBuffer}. + * @return the {@code SparseVarInt} value read. + */ + public long readSparseVarInt(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.VAR_INT); + Item item = this.read(this::read7BitEncodedInt, edit); + return item.value(); + } + + /** + * Read the value of a {@code SparseVarUInt} field at the given {@link RowCursor edit} position. + * + * @param edit {@link RowCursor edit} position of a {@code SparseVarUInt} field within this {@link RowBuffer}. + * @return the {@code SparseVarUInt} value read. + */ + public long readSparseVarUInt(RowCursor edit) { + this.readSparsePrimitiveTypeCode(edit, LayoutTypes.VAR_UINT); + Item item = this.read(this::read7BitEncodedUInt, edit); + return item.value(); + } + + /** + * Read the value of a {@code UInt16} field at the given {@code offset} position. + * + * @param offset position of a {@code UInt16} field within this {@link RowBuffer}. + * @return the {@code UInt16} value read. + */ + public int readUInt16(int offset) { + Item item = this.read(this.buffer::readUnsignedShortLE, offset); + return item.value(); + } + + /** + * Read the value of a {@code UInt32} field at the given {@code offset} position. + * + * @param offset position of a {@code UInt32} field within this {@link RowBuffer}. + * @return the {@code UInt32} value read. + */ + public long readUInt32(int offset) { + Item item = this.read(this.buffer::readUnsignedIntLE, offset); + return item.value(); + } + + /** + * Read the value of a {@code UInt64} field at the given {@code offset} position. + * + * @param offset position of a {@code UInt64} field within this {@link RowBuffer}. + * @return the {@code UInt64} value read. + */ + public long readUInt64(int offset) { + Item item = this.read(this.buffer::readLongLE, offset); + return item.value(); + } + + /** + * Read the value of a {@code UInt8} field at the given {@code offset} position. + * + * @param offset position of a {@code UInt8} field within this {@link RowBuffer}. + * @return the {@code UInt8} value read. + */ + public short readUInt8(int offset) { + Item item = this.read(this.buffer::readUnsignedByte, offset); + return item.value(); + } + + /** + * Read the value of a {@code UnixDateTime} field at the given {@code offset} position. + * + * @param offset position of a {@code UnixDateTime} field within this {@link RowBuffer}. + * @return the {@code UnixDateTime} value read. + */ + public UnixDateTime readUnixDateTime(int offset) { + Item item = this.read(this::readUnixDateTime, offset); + return item.value(); + } + + /** + * Read the value of a {@code VariableBinary} field at the given {@code offset} position. + * + * @param offset position of a {@code VariableBinary} field within this {@link RowBuffer}. + * @return the {@code VariableBinary} value read. + */ + public ByteBuf readVariableBinary(int offset) { + Item item = this.read(this::readVariableBinary, offset); + return item.value(); + } + + /** + * Read the value of a {@code VariableInt} field at the given {@code offset} position. + * + * @param offset position of a {@code VariableInt} field within this {@link RowBuffer}. + * @return the {@code VariableInt} value read. + */ + public long readVariableInt(int offset) { + Item item = this.read(this::read7BitEncodedInt, offset); + return item.value(); + } + + /** + * Read the value of a {@code VariableString} field at the given {@code offset} position. + * + * @param offset position of a {@code VariableString} field within this {@link RowBuffer}. + * @return the {@code VariableString} value read. + */ + public Utf8String readVariableString(final int offset) { + Item item = this.read(this::readUtf8String, offset); + return item.value(); + } + + /** + * Read the value of a {@code VariableUInt} field at the given {@code offset} position. + * + * @param offset position of a {@code VariableUInt} field within this {@link RowBuffer}. + * @return the {@code VariableUInt} value read. + */ + public long readVariableUInt(final int offset) { + Item item = this.read(this::read7BitEncodedUInt, offset); + return item.value(); + } + + /** + * Read the value of a {@code VariableUInt} field at the given {@code offset} position. + * + * @param offset position of a {@code VariableUInt} field within this {@link RowBuffer}. + * @param length on return, the number of bytes read. + * @return the {@code VariableUInt} value read. + */ + public long readVariableUInt(final int offset, @Nonnull final Out length) { + Item item = this.read(this::read7BitEncodedUInt, offset); + length.set(item.length()); + return item.value(); + } + + /** + * Clears all content from the row. The row is empty after this method. + */ + public void reset() { + this.buffer.clear(); + this.resolver = null; + } + + /** + * The resolver for UDTs. + * + * @return reference to the resolver for UDTs. + */ + public LayoutResolver resolver() { + return this.resolver; + } + + /** + * Rotates the sign bit of a two's complement value to the least significant bit. + * + * @param value A signed value. + * @return An unsigned value encoding the same value but with the sign bit in the LSB. + *

+ * Moves the signed bit of a two's complement value to the least significant bit (LSB) by: + *

    + *
  1. If negative, take the two's complement. + *
  2. Left shift the value by 1 bit. + *
  3. If negative, set the LSB to 1. + *
+ */ + public static long rotateSignToLsb(long value) { + boolean isNegative = value < 0; + long unsignedValue = value; + unsignedValue = isNegative ? ((~unsignedValue + 1) << 1) + 1 : unsignedValue << 1; + return unsignedValue; + } + + /** + * Undoes the rotation introduced by {@link #rotateSignToLsb}. + * + * @param unsignedValue An unsigned value with the sign bit in the LSB. + * @return A signed two's complement value encoding the same value. + */ + public static long rotateSignToMsb(long unsignedValue) { + boolean isNegative = unsignedValue % 2 != 0; + return isNegative ? (~(unsignedValue >>> 1) + 1) | 0x8000000000000000L : unsignedValue >>> 1; + } + + // TODO: DANOBLE: Support MongoDbObjectId values + // public void WriteMongoDbObjectId(int offset, MongoDbObjectId value) { + // Reference tempReference_value = + // new Reference(value); + // MemoryMarshal.Write(this.buffer.Slice(offset), tempReference_value); + // value = tempReference_value.get(); + // } + + public void setBit(final int offset, @Nonnull final LayoutBit bit) { + checkNotNull(bit, "expected non-null bit"); + if (bit.isInvalid()) { + return; + } + final int index = bit.offset(offset); + this.buffer.setByte(index, this.buffer.getByte(bit.offset(offset)) | (byte) (1 << bit.bit())); + } + + /** + * Move a sparse iterator to the next field within the same sparse scope. + * + * @param edit The iterator to advance. + * + * {@code edit.Path} + * On success, the path of the field at the given offset, otherwise + * undefined. + * + * {@code edit.MetaOffset} + * If found, the offset to the metadata of the field, otherwise a + * location to insert the field. + * + * {@code edit.cellType} + * If found, the layout code of the matching field found, otherwise + * undefined. + * + * {@code edit.ValueOffset} + * If found, the offset to the value of the field, otherwise + * undefined. + *. + * + * @return {@code true} if there is another field; {@code false} if there is not. + */ + public boolean sparseIteratorMoveNext(RowCursor edit) { + + if (edit.cellType() != null) { + // Move to the next element of an indexed scope. + if (edit.scopeType().isIndexedScope()) { + edit.index(edit.index() + 1); + } + + // Skip forward to the end of the current value. + if (edit.endOffset() != 0) { + edit.metaOffset(edit.endOffset()); + edit.endOffset(0); + } else { + edit.metaOffset(edit.metaOffset() + this.sparseComputeSize(edit)); + } + } + + // Check if reached end of buffer + + if (edit.metaOffset() < this.length()) { + + // Check if reached end of sized scope. + + if (!edit.scopeType().isSizedScope() || (edit.index() != edit.count())) { + + this.readSparseMetadata(edit); + + if (!(edit.cellType() instanceof LayoutEndScope)) { + // End of sparse scope + edit.exists(true); + return true; + } + } + } + + edit.cellType(LayoutTypes.END_SCOPE); + edit.exists(false); + edit.valueOffset(edit.metaOffset()); + return false; + } + + /** + * Produce a new scope from the current iterator position. + * + * @param edit An initialized iterator pointing at a scope. + * @param immutable {@code true} if the new scope should be marked immutable (read-only). + * @return A new scope beginning at the current iterator position. + */ + public RowCursor sparseIteratorReadScope(@Nonnull final RowCursor edit, boolean immutable) { + + LayoutTypeScope scopeType = edit.cellType() instanceof LayoutTypeScope ? (LayoutTypeScope) edit.cellType() : null; + + if (scopeType instanceof LayoutObject || scopeType instanceof LayoutArray) { + return new RowCursor() + .scopeType(scopeType) + .scopeTypeArgs(edit.cellTypeArgs()) + .start(edit.valueOffset()) + .valueOffset(edit.valueOffset()) + .metaOffset(edit.valueOffset()) + .layout(edit.layout()) + .immutable(immutable); + } + + if (scopeType instanceof LayoutTypedArray || scopeType instanceof LayoutTypedSet || scopeType instanceof LayoutTypedMap) { + + final int valueOffset = edit.valueOffset() + Integer.BYTES; // Point after the Size + + return new RowCursor() + .scopeType(scopeType) + .scopeTypeArgs(edit.cellTypeArgs()) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()) + .immutable(immutable) + .count(this.readInt32(edit.valueOffset())); + } + + if (scopeType instanceof LayoutTypedTuple || scopeType instanceof LayoutTuple || scopeType instanceof LayoutTagged || scopeType instanceof LayoutTagged2) { + + return new RowCursor() + .scopeType(scopeType) + .scopeTypeArgs(edit.cellTypeArgs()) + .start(edit.valueOffset()) + .valueOffset(edit.valueOffset()) + .metaOffset(edit.valueOffset()) + .layout(edit.layout()) + .immutable(immutable) + .count(edit.cellTypeArgs().count()); + } + + if (scopeType instanceof LayoutNullable) { + + boolean hasValue = this.readInt8(edit.valueOffset()) != 0; + + if (hasValue) { + + // Start at the T so it can be read. + final int valueOffset = edit.valueOffset() + 1; + + return new RowCursor() + .scopeType(scopeType) + .scopeTypeArgs(edit.cellTypeArgs()) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()) + .immutable(immutable) + .count(2) + .index(1); + } else { + + // Start at the end of the scope, instead of at the T, so the T will be skipped. + final TypeArgument typeArg = edit.cellTypeArgs().get(0); + final int valueOffset = edit.valueOffset() + 1 + this.countDefaultValue(typeArg.type(), + typeArg.typeArgs()); + + return new RowCursor() + .scopeType(scopeType) + .scopeTypeArgs(edit.cellTypeArgs()) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()) + .immutable(immutable) + .count(2) + .index(2); + } + } + + if (scopeType instanceof LayoutUDT) { + + final Layout udt = this.resolver.resolve(edit.cellTypeArgs().schemaId()); + final int valueOffset = this.computeVariableValueOffset(udt, edit.valueOffset(), udt.numVariable()); + + return new RowCursor() + .scopeType(scopeType) + .scopeTypeArgs(edit.cellTypeArgs()) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(udt) + .immutable(immutable); + } + + throw new IllegalStateException(lenientFormat("Not a scope type: %s", scopeType)); + } + + public byte[] toArray() { + byte[] content = new byte[this.length()]; + this.buffer.getBytes(0, content); + return content; + } + + public void typedCollectionMoveField( + @Nonnull final RowCursor dstEdit, + @Nonnull final RowCursor srcEdit, + @Nonnull final RowOptions options) { + + final int length = this.sparseComputeSize(srcEdit) - (srcEdit.valueOffset() - srcEdit.metaOffset()); + + // Insert the field metadata into its new location + + Out metaBytes = new Out<>(); + Out spaceNeeded = new Out<>(); + Out shiftInsert = new Out<>(); + Out shiftDelete = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse( + length, dstEdit, srcEdit.cellType(), srcEdit.cellTypeArgs(), options, metaBytes, spaceNeeded, shiftInsert); + this.writeSparseMetadata(dstEdit, srcEdit.cellType(), srcEdit.cellTypeArgs(), metaBytes.get()); + + if (srcEdit.metaOffset() >= dstEdit.metaOffset()) { + srcEdit.metaOffset(srcEdit.metaOffset() + shiftInsert.get()); + srcEdit.valueOffset(srcEdit.valueOffset() + shiftInsert.get()); + } + + // Copy the value bits from the old location + + this.writeFixedBinary(dstEdit.valueOffset(), this.buffer, srcEdit.valueOffset(), length); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shiftInsert.get()); + + // Delete the old location + + this.ensureSparse( + length, srcEdit, srcEdit.cellType(), srcEdit.cellTypeArgs(), RowOptions.DELETE, metaBytes, spaceNeeded, + shiftDelete); + + checkState(shiftDelete.get() < 0); + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shiftDelete.get()); + } + + /** + * Rebuild the unique index for a set/map scope. + * + * @param scope The sparse scope to rebuild an index for. + * @return Success if the index could be built, an error otherwise. + *

+ * The {@code scope} MUST be a set or map scope. + *

+ * The scope may have been built (e.g. via RowWriter) with relaxed uniqueness constraint checking. + * This operation rebuilds an index to support verification of uniqueness constraints during + * subsequent partial updates. If the appropriate uniqueness constraints cannot be established (i.e. + * a duplicate exists), this operation fails. Before continuing, the resulting scope should either: + *

    + *
  1. Be repaired (e.g. by deleting duplicates) and the index rebuild operation should be run again. + *
  2. Be deleted. The entire scope should be removed including its items. + *
+ * Failure to perform one of these actions will leave the row is potentially in a corrupted state where partial + * updates may subsequent fail. + *

+ * The target {@code scope} may or may not have already been indexed. This operation is idempotent. + */ + @Nonnull + public Result typedCollectionUniqueIndexRebuild(@Nonnull final RowCursor scope) { + + checkNotNull(scope, "expected non-null scope"); + checkArgument(scope.scopeType().isUniqueScope(), "expected unique scope type"); + checkArgument(scope.index() == 0, "expected scope index of zero"); + + RowCursor edit = scope.clone(); + + if (edit.count() <= 1) { + return Result.SUCCESS; + } + + // Compute index elements + + UniqueIndexItem[] uniqueIndex = new UniqueIndexItem[edit.count()]; + edit.metaOffset(scope.valueOffset()); + + for (; edit.index() < edit.count(); edit.index(edit.index() + 1)) { + + final RowCursor dstEdit = new RowCursor(); + this.readSparseMetadata(dstEdit); + + checkState(edit.pathOffset() == 0); + + final int elementSize = this.sparseComputeSize(edit); + + uniqueIndex[edit.index()] = new UniqueIndexItem() + .code(edit.cellType().layoutCode()) + .metaOffset(edit.metaOffset()) + .valueOffset(edit.valueOffset()) + .size(elementSize); + + edit.metaOffset(edit.metaOffset() + elementSize); + } + + // Create scratch space equal to the sum of the sizes of the scope's values. + // Implementation Note: theoretically this scratch space could be eliminated by + // performing the item move operations directly during the Insertion Sort, however, + // doing so might result in moving the same item multiple times. Under the assumption + // that items are relatively large, using scratch space requires each item to be moved + // AT MOST once. Given that row buffer memory is likely reused, scratch space is + // relatively memory efficient. + + int shift = edit.metaOffset() - scope.valueOffset(); + + // Sort and check for duplicates + + if (!this.insertionSort(scope, edit, Arrays.asList(uniqueIndex))) { + return Result.EXISTS; + } + + // Move elements + + int metaOffset = scope.valueOffset(); + this.ensure(this.length() + shift); + this.writeFixedBinary(metaOffset + shift, this.buffer, metaOffset, this.length() - metaOffset); + + for (UniqueIndexItem item : uniqueIndex) { + this.writeFixedBinary(metaOffset, this.buffer, item.metaOffset() + shift, item.size()); + metaOffset += item.size(); + } + + // Delete the scratch space (if necessary - if it doesn't just fall off the end of the row) + + if (metaOffset != this.length()) { + this.writeFixedBinary(metaOffset, this.buffer, metaOffset + shift, this.length() - metaOffset); + } + + return Result.SUCCESS; + } + + public void unsetBit(final int offset, @Nonnull final LayoutBit bit) { + checkNotNull(bit, "expected non-null bit"); + checkArgument(!bit.isInvalid()); + final int index = bit.offset(offset); + this.buffer.setByte(index, this.buffer.getByte(index) & (byte) ~(1 << bit.bit())); + } + + public int write7BitEncodedInt(final long value) { + return this.write7BitEncodedUInt(RowBuffer.rotateSignToLsb(value)); + } + + /** + * Sets the specified 64-bit integer at the current {@link RowBuffer position} as a 7-bit encoded 32-bit value. + *

+ * The 64-bit integer value is written 7-bits at a time. The high bit of the byte, when set, indicates there are + * more bytes. An {@link IllegalArgumentException} is thrown, if the specified 64-bit integer value is outside + * the range of an unsigned 32-bit integer, [0, 0x00000000FFFFFFFFL]. + * + * @param value a 64-bit integer constrained to the range of an unsigned 32-bit integer, [0, 0x00000000FFFFFFFFL] + * @return The number of bytes written + */ + public int write7BitEncodedUInt(final long value) { + checkArgument(0 <= value && value <= 0x00000000FFFFFFFFL, "expected value in range [0, %s], not %s", 0x00000000FFFFFFFFL, value); + long n = value; + int i = 0; + while (n >= 0x80L) { + this.buffer.writeByte((byte) (n | 0x80L)); + n >>>= 7; + } + this.buffer.writeByte((byte) n); + return i; + } + + public void writeDateTime(int offset, OffsetDateTime value) { + Item item = this.write(this::writeDateTime, offset, value); + } + + public void writeDecimal(int offset, BigDecimal value) { + Item item = this.write(this::writeDecimal, offset, value); + } + + public void writeFixedBinary(final int offset, @Nonnull final ByteBuf value, final int length) { + + checkNotNull(value, "expected non-null value"); + checkArgument(offset >= 0, "expected offset >= 0, not %s", offset); + checkArgument(length >= 0, "expected length >= 0, not %s", length); + + Item item = this.write(buffer -> { + int writableBytes = Math.min(length, buffer.readableBytes()); + this.buffer.writeBytes(buffer, writableBytes); + if (writableBytes < length) { + this.buffer.writeZero(length - writableBytes); + } + }, offset, value); + } + + public void writeFixedBinary(final int offset, @Nonnull final ByteBuf value, final int index, final int length) { + checkArgument(index >= 0, "expected index >= 0, not %s", index); + value.markReaderIndex().readerIndex(index); + this.writeFixedBinary(offset, value, length); + value.resetReaderIndex(); + } + + public void writeFixedBinary(final int offset, @Nonnull final byte[] value, final int index, final int length) { + + checkNotNull(value, "expected non-null value"); + checkArgument(offset >= 0, "expected offset >= 0, not %s", offset); + checkArgument(length >= 0, "expected length >= 0, not %s", length); + checkArgument(0 <= index && index < value.length, "expected in range [0, %s), not index", index); + + Item item = this.write(buffer -> { + int writableBytes = Math.min(length, buffer.length - index); + this.buffer.writeBytes(buffer, index, writableBytes); + if (writableBytes < length) { + this.buffer.writeZero(length - writableBytes); + } + }, offset, value); + } + + public void writeFixedString(final int offset, @Nonnull final Utf8String value) { + checkNotNull(value, "expected non-null value"); + checkArgument(!value.isNull(), "expected non-null value content"); + Item item = this.write(this::writeFixedString, offset, value); + } + + public void writeFloat128(int offset, Float128 value) { + this.buffer.writeLongLE(value.low()); + this.buffer.writeLongLE(value.high()); + } + + public void writeFloat32(final int offset, final float value) { + Item item = this.write(this.buffer::writeFloatLE, offset, value); + } + + public void writeFloat64(final int offset, final double value) { + Item item = this.write(this.buffer::writeDoubleLE, offset, value); + } + + public void writeGuid(final int offset, @Nonnull final UUID value) { + checkNotNull(value, "expected non-null value"); + Item item = this.write(this::writeGuid, offset, value); + } + + public void writeHeader(HybridRowHeader value) { + this.buffer.writeByte(value.version().value()); + this.buffer.writeIntLE(value.schemaId().value()); + } + + public void writeInt16(final int ignored, final short value) { + this.buffer.writeShortLE(value); + } + + public void writeInt32(final int ignored, final int value) { + this.buffer.writeIntLE(value); + } + + public void writeInt64(final int ignored, final long value) { + this.buffer.writeLongLE(value); + } + + public void writeInt8(final int ignored, final byte value) { + this.buffer.writeByte(value); + } + + @Nonnull + public RowCursor writeNullable( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + boolean hasValue) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + + final int length = this.countDefaultValue(scope, typeArgs); + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + + final int numWritten = this.writeDefaultValue(edit.valueOffset(), scope, typeArgs); + checkState(length == numWritten); + + if (hasValue) { + this.writeInt8(edit.valueOffset(), (byte) 1); + } + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + final int valueOffset = edit.valueOffset() + 1; + + RowCursor newScope = new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()) + .count(2) + .index(1); + + RowCursors.moveNext(newScope, this); + return newScope; + } + + public void writeSchemaId(final int offset, @Nonnull final SchemaId value) { + checkNotNull(value, "expected non-null value"); + this.writeInt32(offset, value.value()); + } + + @Nonnull + public RowCursor writeSparseArray( + @Nonnull final RowCursor edit, @Nonnull final LayoutTypeScope scope, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(options, "expected non-null options"); + + int length = LayoutCode.BYTES; + TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + this.writeSparseTypeCode(edit.valueOffset(), LayoutCode.END_SCOPE); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(edit.valueOffset()) + .metaOffset(edit.valueOffset()) + .layout(edit.layout()); + } + + public void writeSparseBinary( + @Nonnull final RowCursor edit, @Nonnull final ByteBuf value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + final int length = RowBuffer.count7BitEncodedUInt(value.readableBytes()) + value.readableBytes(); + final LayoutType type = LayoutTypes.BINARY; + + final Out metaBytes = new Out<>(); + final Out shift = new Out<>(); + final Out spaceNeeded = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeVariableBinary(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseBoolean( + @Nonnull final RowCursor edit, final boolean value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final int length = 0; + final LayoutType type = value ? LayoutTypes.BOOLEAN : LayoutTypes.BOOLEAN_FALSE; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get()); + + checkState(spaceNeeded.get() == (int) metaBytes.get()); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseDateTime( + @Nonnull final RowCursor edit, @Nonnull final OffsetDateTime value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + LayoutType type = LayoutTypes.DATE_TIME; + int length = DateTimeCodec.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeDateTime(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseDecimal( + @Nonnull final RowCursor edit, @Nonnull final BigDecimal value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.DECIMAL; + final int length = DecimalCodec.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeDecimal(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseFloat128( + @Nonnull final RowCursor edit, @Nonnull final Float128 value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.FLOAT_128; + final int length = Float128.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeFloat128(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseFloat32(@Nonnull RowCursor edit, float value, @Nonnull UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.FLOAT_32; + final int length = Float.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeFloat32(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseFloat64(@Nonnull final RowCursor edit, double value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.FLOAT_64; + final int length = Double.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeFloat64(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseGuid( + @Nonnull final RowCursor edit, @Nonnull final UUID value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.GUID; + final int length = GuidCodec.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeGuid(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseInt16(@Nonnull final RowCursor edit, short value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.INT_16; + final int length = Short.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeInt16(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseInt32(@Nonnull final RowCursor edit, int value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.INT_32; + final int length = Integer.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeInt32(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseInt64(@Nonnull final RowCursor edit, long value, UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.INT_64; + final int length = Long.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeInt64(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseInt8(@Nonnull final RowCursor edit, byte value, UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final int length = Long.BYTES; + final LayoutType type = LayoutTypes.INT_8; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get()); + this.writeInt8(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseNull( + @Nonnull final RowCursor edit, @Nonnull final NullValue value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final int length = 0; + final LayoutType type = LayoutTypes.NULL; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get()); + + checkState(spaceNeeded.get() == (int)metaBytes.get()); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public RowCursor writeSparseObject( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(options, "expected non-null options"); + + int length = LayoutCode.BYTES; // end scope type code. + TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + this.writeSparseTypeCode(edit.valueOffset(), LayoutCode.END_SCOPE); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(TypeArgumentList.EMPTY) + .start(edit.valueOffset()) + .valueOffset(edit.valueOffset()) + .metaOffset(edit.valueOffset()) + .layout(edit.layout()); + } + + public void writeSparseString( + @Nonnull final RowCursor edit, @Nonnull final Utf8String value, @Nonnull final UpdateOptions options) { + + final LayoutType type = LayoutTypes.UTF_8; + final TypeArgumentList args = TypeArgumentList.EMPTY; + final int length = RowBuffer.count7BitEncodedUInt(value.encodedLength()) + value.encodedLength(); + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, args, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, args, metaBytes.get()); + this.write(this::writeVariableString, edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + @Nonnull + public RowCursor writeSparseTuple( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options) { + + int length = LayoutCode.BYTES * (1 + typeArgs.count()); // nulls for each element + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + + int valueOffset = edit.valueOffset(); + + for (int i = 0; i < typeArgs.count(); i++) { + this.writeSparseTypeCode(valueOffset, LayoutCode.NULL); + valueOffset += LayoutCode.BYTES; + } + + this.writeSparseTypeCode(valueOffset, LayoutCode.END_SCOPE); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(edit.valueOffset()) + .metaOffset(edit.valueOffset()) + .layout(edit.layout()) + .count(typeArgs.count()); + } + + public void writeSparseTypeCode(int offset, LayoutCode code) { + this.writeUInt8(offset, code.value()); + } + + @Nonnull + public RowCursor writeSparseUDT( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final Layout udt, + @Nonnull final UpdateOptions options) { + + TypeArgumentList typeArgs = new TypeArgumentList(udt.schemaId()); + int length = udt.size() + LayoutCode.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + this.write(this.buffer::writeZero, edit.valueOffset(), udt.size()); // clear all presence bits + + // Write scope terminator + + int valueOffset = edit.valueOffset() + udt.size(); + this.writeSparseTypeCode(valueOffset, LayoutCode.END_SCOPE); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(udt); + } + + public void writeSparseUInt16( + @Nonnull final RowCursor edit, final short value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final int length = Short.BYTES; + final LayoutType type = LayoutTypes.UINT_16; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeUInt16(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseUInt32( + @Nonnull final RowCursor edit, final int value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final int length = Integer.BYTES; + final LayoutType type = LayoutTypes.UINT_32; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeUInt32(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseUInt64(@Nonnull final RowCursor edit, long value, @Nonnull UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final int length = Long.BYTES; + final LayoutType type = LayoutTypes.UINT_64; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeUInt64(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseUInt8( + @Nonnull final RowCursor edit, final byte value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.UINT_8; + final int length = Byte.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeUInt8(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseUnixDateTime( + @Nonnull final RowCursor edit, @Nonnull final UnixDateTime value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + LayoutType type = LayoutTypes.UNIX_DATE_TIME; + final int length = UnixDateTime.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.writeUnixDateTime(edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseVarInt(@Nonnull final RowCursor edit, final long value, @Nonnull final UpdateOptions options) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(options, "expected non-null options"); + + final LayoutType type = LayoutTypes.VAR_INT; + final int length = RowBuffer.count7BitEncodedInt(value); + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, TypeArgumentList.EMPTY, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, TypeArgumentList.EMPTY, metaBytes.get()); + this.write(this::write7BitEncodedInt, edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + public void writeSparseVarUInt( + @Nonnull final RowCursor edit, final long value, @Nonnull final UpdateOptions options) { + + final LayoutType type = LayoutTypes.VAR_UINT; + final TypeArgumentList typeArgs = TypeArgumentList.EMPTY; + final int length = RowBuffer.count7BitEncodedUInt(value); + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, type, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, type, typeArgs, metaBytes.get()); + this.write(this::write7BitEncodedUInt, edit.valueOffset(), value); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + edit.endOffset(edit.metaOffset() + spaceNeeded.get()); + } + + /** + * Writes the content of the buffer on to an {@link OutputStream}. + * + * @param stream the target @{link OutputStream} + * @throws IOException if the specified {@code stream} throws an {@link IOException} during output + */ + public void writeTo(@Nonnull final OutputStream stream) throws IOException { + checkNotNull(stream, "expected non-null stream"); + this.buffer.getBytes(0, stream, this.length()); + } + + @Nonnull + public RowCursor writeTypedArray( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options) { + + final int length = Integer.BYTES; + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + this.writeUInt32(edit.valueOffset(), 0); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + int valueOffset = edit.valueOffset() + Integer.BYTES; // point after the size + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()); + } + + @Nonnull + public RowCursor writeTypedMap( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options) { + + final int length = Integer.BYTES; // sized scope + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + this.writeUInt32(edit.valueOffset(), 0); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + int valueOffset = edit.valueOffset() + Integer.BYTES; // point after the size + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()); + } + + @Nonnull + public RowCursor writeTypedSet( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options) { + + final int length = Integer.BYTES; + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + this.writeUInt32(edit.valueOffset(), 0); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + final int valueOffset = edit.valueOffset() + Integer.BYTES; // point after the size + + return new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(valueOffset) + .metaOffset(valueOffset) + .layout(edit.layout()); + } + + public RowCursor writeTypedTuple( + @Nonnull final RowCursor edit, + @Nonnull final LayoutTypeScope scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options) { + + final int length = this.countDefaultValue(scope, typeArgs); + + final Out metaBytes = new Out<>(); + final Out spaceNeeded = new Out<>(); + final Out shift = new Out<>(); + + final int priorLength = this.length(); + + this.ensureSparse(length, edit, scope, typeArgs, options, metaBytes, spaceNeeded, shift); + this.writeSparseMetadata(edit, scope, typeArgs, metaBytes.get()); + + final int numWritten = this.writeDefaultValue(edit.valueOffset(), scope, typeArgs); + checkState(length == numWritten); + + checkState(spaceNeeded.get() == metaBytes.get() + length); + checkState(this.length() == priorLength + shift.get()); + + final RowCursor newScope = new RowCursor() + .scopeType(scope) + .scopeTypeArgs(typeArgs) + .start(edit.valueOffset()) + .valueOffset(edit.valueOffset()) + .metaOffset(edit.valueOffset()) + .layout(edit.layout()) + .count(typeArgs.count()); + + RowCursors.moveNext(newScope, this); + return newScope; + } + + public void writeUInt16(final int offset, final short value) { + final Item item = this.write(this::writeUInt16, offset, value); + } + + public void writeUInt32(final int offset, final int value) { + final Item item = this.write(this::writeUInt32, offset, value); + } + + public void writeUInt64(final int offset, final long value) { + final Item item = this.write(this::writeUInt64, offset, value); + } + + public void writeUInt8(int offset, byte value) { + final Item item = this.write(this::writeUInt8, offset, value); + } + + public void writeUnixDateTime(int offset, UnixDateTime value) { + final Item item = this.write(this::writeUInt64, offset, value.milliseconds()); + } + + public void writeVariableBinary( + final int offset, @Nonnull final ByteBuf value, final boolean exists, @Nonnull final Out shift) { + + checkNotNull(value, "expected non-null value"); + checkNotNull(shift, "expected non-null shift"); + + final int length = value.readableBytes(); + final Out spaceNeeded = new Out<>(); + + final int priorLength = this.length(); + + this.ensureVariable(offset, false, length, exists, spaceNeeded, shift); + final Item item = this.write(this::writeVariableBinary, offset, value); + + checkState(spaceNeeded.get() == length + item.length()); + checkState(this.length() == priorLength + shift.get()); + } + + public int writeVariableInt(int offset, long value, boolean exists) { + + final int length = RowBuffer.count7BitEncodedInt(value); + final Out shift = new Out<>(); + final Out spaceNeeded = new Out<>(); + + final int priorLength = this.length(); + + this.ensureVariable(offset, true, length, exists, spaceNeeded, shift); + final Item item = this.write(this::write7BitEncodedInt, offset, value); + + checkState(item.length == length); + checkState(spaceNeeded.get() == length); + checkState(this.length() == priorLength + shift.get()); + + return shift.get(); + } + + public int writeVariableString( + final int offset, @Nonnull final Utf8String value, final boolean exists) { + + checkNotNull(value, "expected non-null value"); + checkArgument(!value.isNull(), "expected non-null value content"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + final int length = value.encodedLength(); + final Out shift = new Out<>(); + final Out spaceNeeded = new Out<>(); + + final int priorLength = this.length(); + + this.ensureVariable(offset, false, length, exists, spaceNeeded, shift); + Item item = this.write(this::writeVariableString, offset, value); + + checkState(spaceNeeded.get() == length + item.length()); + checkState(this.length() == priorLength + shift.get()); + + return shift.get(); + } + + public int writeVariableUInt(final int offset, final long value) { + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + Item item = this.write(this::write7BitEncodedUInt, offset, value); + return item.length(); + } + + public int writeVariableUInt(final int offset, final long value, final boolean exists) { + + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + final int length = RowBuffer.count7BitEncodedUInt(value); + final Out shift = new Out<>(); + final Out spaceNeeded = new Out<>(); + + final int priorLength = this.length(); + + this.ensureVariable(offset, true, length, exists, spaceNeeded, shift); + final Item item = this.write(this::write7BitEncodedUInt, offset, value); + + checkState(item.length == length); + checkState(spaceNeeded.get() == length); + checkState(this.length() == priorLength + shift.get()); + + return shift.get(); + } + + /** + * Compares the values of two encoded fields using the hybrid row binary collation. + * + * @param left An edit describing the left field. + * @param leftLength The size of the left field's value in bytes. + * @param right An edit describing the right field. + * @param rightLength The size of the right field's value in bytes. + * @return + * + * -1left less than right. + * + * 0left and right are equal. + * + * 1left is greater than right. + * + * + */ + private int compareFieldValue( + @Nonnull final RowCursor left, final int leftLength, @Nonnull final RowCursor right, final int rightLength) { + + checkNotNull(left, "expected non-null left"); + checkNotNull(right, "expected non-null right"); + checkArgument(leftLength >= 0, "expected non-negative leftLength"); + checkArgument(rightLength >= 0, "expected non-negative rightLength"); + + if (left.cellType().layoutCode().value() < right.cellType().layoutCode().value()) { + return -1; + } + + if (left.cellType() != right.cellType()) { + return 1; + } + + if (leftLength > rightLength) { + return 1; + } + + if (leftLength < rightLength) { + return -1; + } + + ByteBuf sliceLeft = this.buffer.slice(left.valueOffset(), leftLength); + ByteBuf sliceRight = this.buffer.slice(right.valueOffset(), rightLength); + + return sliceLeft.compareTo(sliceRight); + } + + /** + * Compares the values of two encoded key-value pair fields using the hybrid row binary. + * collation. + * + * @param left An edit describing the left field. + * @param right An edit describing the right field. + * @return + * + * -1left less than right. + * + * 0left and right are equal. + * + * 1left is greater than right. + * + * + */ + private int compareKeyValueFieldValue(RowCursor left, RowCursor right) { + + LayoutTypedTuple leftScopeType = left.cellType() instanceof LayoutTypedTuple + ? (LayoutTypedTuple) left.cellType() + : null; + LayoutTypedTuple rightScopeType = right.cellType() instanceof LayoutTypedTuple + ? (LayoutTypedTuple) right.cellType() + : null; + + checkArgument(leftScopeType != null); + checkArgument(rightScopeType != null); + checkArgument(left.cellTypeArgs().count() == 2); + checkArgument(left.cellTypeArgs().equals(right.cellTypeArgs())); + + RowCursor leftKey = new RowCursor(); + leftKey.layout(left.layout()); + leftKey.scopeType(leftScopeType); + leftKey.scopeTypeArgs(left.cellTypeArgs()); + leftKey.start(left.valueOffset()); + leftKey.metaOffset(left.valueOffset()); + leftKey.index(0); + + this.readSparseMetadata(leftKey); + checkState(leftKey.pathOffset() == 0); + int leftKeyLen = this.sparseComputeSize(leftKey) - (leftKey.valueOffset() - leftKey.metaOffset()); + + RowCursor rightKey = new RowCursor(); + rightKey.layout(right.layout()); + rightKey.scopeType(rightScopeType); + rightKey.scopeTypeArgs(right.cellTypeArgs()); + rightKey.start(right.valueOffset()); + rightKey.metaOffset(right.valueOffset()); + rightKey.index(0); + + this.readSparseMetadata(rightKey); + checkState(rightKey.pathOffset() == 0); + int rightKeyLen = this.sparseComputeSize(rightKey) - (rightKey.valueOffset() - rightKey.metaOffset()); + + return this.compareFieldValue(leftKey, leftKeyLen, rightKey, rightKeyLen); + } + + /** + * Compute the number of bytes necessary to store the signed integer using the varint encoding. + * + * @param value The value to be encoded + * @return The number of bytes needed to store the varint encoding of {@code value} + */ + private static int count7BitEncodedInt(long value) { + return RowBuffer.count7BitEncodedUInt(RowBuffer.rotateSignToLsb(value)); + } + + /** + * Return the size (in bytes) of the default sparse value for the type. + * + * @param code The type of the default value. + * @param typeArgs + */ + private int countDefaultValue(LayoutType code, TypeArgumentList typeArgs) { + + // TODO: JTH: convert to a virtual? + + if (code instanceof LayoutNull || code instanceof LayoutBoolean) { + return 1; + } + if (code instanceof LayoutInt8) { + return LayoutTypes.INT_8.size(); + } + if (code instanceof LayoutInt16) { + return LayoutTypes.INT_16.size(); + } + if (code instanceof LayoutInt32) { + return LayoutTypes.INT_32.size(); + } + if (code instanceof LayoutInt64) { + return LayoutTypes.INT_64.size(); + } + if (code instanceof LayoutUInt8) { + return LayoutTypes.UINT_8.size(); + } + if (code instanceof LayoutUInt16) { + return LayoutTypes.UINT_16.size(); + } + if (code instanceof LayoutUInt32) { + return LayoutTypes.UINT_32.size(); + } + if (code instanceof LayoutUInt64) { + return LayoutTypes.UINT_64.size(); + } + if (code instanceof LayoutFloat32) { + return LayoutTypes.FLOAT_32.size(); + } + if (code instanceof LayoutFloat64) { + return LayoutTypes.FLOAT_64.size(); + } + if (code instanceof LayoutFloat128) { + return LayoutTypes.FLOAT_128.size(); + } + if (code instanceof LayoutDecimal) { + return LayoutTypes.DECIMAL.size(); + } + if (code instanceof LayoutDateTime) { + return LayoutTypes.DATE_TIME.size(); + } + if (code instanceof LayoutUnixDateTime) { + return LayoutTypes.UNIX_DATE_TIME.size(); + } + if (code instanceof LayoutGuid) { + return LayoutTypes.GUID.size(); + } + if (code instanceof LayoutMongoDbObjectId) { + // return MongoDbObjectId.size(); + throw new UnsupportedOperationException(); + } + if (code instanceof LayoutUtf8 || code instanceof LayoutBinary || code instanceof LayoutVarInt || code instanceof LayoutVarUInt) { + // Variable length types preceded by their varuint size take 1 byte for a size of 0. + return 1; + } + if (code instanceof LayoutObject || code instanceof LayoutArray) { + // Variable length sparse collection scopes take 1 byte for the end-of-scope terminator. + return LayoutCode.BYTES; + } + if (code instanceof LayoutTypedArray || code instanceof LayoutTypedSet || code instanceof LayoutTypedMap) { + // Variable length typed collection scopes preceded by their scope size take sizeof(uint) for a size of 0. + return Integer.BYTES; + } + if (code instanceof LayoutTuple) { + // Fixed arity sparse collections take 1 byte for end-of-scope plus a null for each element. + return LayoutCode.BYTES + (LayoutCode.BYTES * typeArgs.count()); + } + if (code instanceof LayoutTypedTuple || code instanceof LayoutTagged || code instanceof LayoutTagged2) { + // Fixed arity typed collections take the sum of the default values of each element. The scope size is + // implied by the arity. + return typeArgs.stream() + .map(arg -> this.countDefaultValue(arg.type(), arg.typeArgs())) + .reduce(0, Integer::sum); + } + if (code instanceof LayoutNullable) { + // Nullables take the default values of the value plus null. The scope size is implied by the arity. + return 1 + this.countDefaultValue(typeArgs.get(0).type(), typeArgs.get(0).typeArgs()); + } + if (code instanceof LayoutUDT) { + Layout udt = this.resolver.resolve(typeArgs.schemaId()); + return udt.size() + LayoutCode.BYTES; + } + throw new IllegalStateException(lenientFormat("Not Implemented: %s", code)); + } + + private static int countSparsePath(@Nonnull final RowCursor edit) { + + if (!edit.writePathToken().isNull()) { + StringToken token = edit.writePathToken(); + ByteBuf varint = token.varint(); + return varint.readerIndex() + varint.readableBytes(); + } + + Optional optional = edit.layout().tokenizer().tryFindToken(edit.writePath()); + + if (optional.isPresent()) { + StringToken token = optional.get(); + edit.writePathToken(token); + ByteBuf varint = token.varint(); + return varint.readerIndex() + varint.readableBytes(); + } + + Utf8String path = edit.writePath().toUtf8(); + assert path != null; + + int numBytes = path.length(); + int sizeLenInBytes = RowBuffer.count7BitEncodedUInt(edit.layout().tokenizer().count() + numBytes); + + return sizeLenInBytes + numBytes; + } + + private void ensure(int size) { + this.buffer.ensureWritable(size); + } + + /** + * Ensure that sufficient space exists in the row buffer to write the specified value. + * + * @param length The number of bytes needed to encode the value of the field to be written. + * @param edit The prepared edit indicating where and in what context the current write will happen. + * @param type The type of the field to be written. + * @param typeArgs The type arguments of the field to be written. + * @param options The kind of edit to be performed. + * @param metaBytes On success, the number of bytes needed to encode the metadata of the new field. + * @param spaceNeeded On success, the number of bytes needed in total to encode the new field and its metadata. + * @param shift On success, the number of bytes the length of the row buffer was increased. + */ + private void ensureSparse( + final int length, + @Nonnull final RowCursor edit, + @Nonnull final LayoutType type, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final RowOptions options, + @Nonnull final Out metaBytes, + @Nonnull final Out spaceNeeded, + @Nonnull final Out shift + ) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(type, "expected non-null type"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(metaBytes, "expected non-null metaBytes"); + checkNotNull(spaceNeeded, "expected non-null spaceNeeded"); + checkNotNull(shift, "expected non-null shift"); + + int metaOffset = edit.metaOffset(); + int spaceAvailable = 0; + + // Compute the metadata offsets + + if (edit.scopeType().hasImplicitTypeCode(edit)) { + metaBytes.set(0); + } else { + metaBytes.set(type.countTypeArgument(typeArgs)); + } + + if (!edit.scopeType().isIndexedScope()) { + checkState(edit.writePath() != null); + int pathLenInBytes = RowBuffer.countSparsePath(edit); + metaBytes.set(metaBytes.get() + pathLenInBytes); + } + + if (edit.exists()) { + // Compute value offset for existing value to be overwritten + spaceAvailable = this.sparseComputeSize(edit); + } + + spaceNeeded.set(options == RowOptions.DELETE ? 0 : metaBytes.get() + length); + shift.set(spaceNeeded.get() - spaceAvailable); + + // Shift the contents of the buffer tail left or right as required to snugly fit the specified value + + final int destination = metaOffset + spaceNeeded.get(); + final int source = metaOffset + spaceAvailable; + + this.shift(destination, source, this.length() - (metaOffset + spaceAvailable)); + + // Update the stored size (fixed arity scopes don't store the size because it is implied by the type args) + + if (edit.scopeType().isSizedScope() && !edit.scopeType().isFixedArity()) { + + if ((options == RowOptions.INSERT) || (options == RowOptions.INSERT_AT) || ((options == RowOptions.UPSERT) && !edit.exists())) { + // Add one to the current scope count + checkState(!edit.exists()); + this.incrementUInt32(edit.start(), 1); + edit.count(edit.count() + 1); + } else if ((options == RowOptions.DELETE) && edit.exists()) { + // Subtract one from the current scope count + checkState(this.readUInt32(edit.start()) > 0); + this.decrementUInt32(edit.start(), 1); + edit.count(edit.count() - 1); + } + } + + if (options == RowOptions.DELETE) { + edit.cellType(null); + edit.cellTypeArgs(null); + edit.exists(false); + } else { + edit.cellType(type); + edit.cellTypeArgs(typeArgs); + edit.exists(true); + } + } + + /** + * Ensure that sufficient space exists in the row buffer to write the specified value. + * + * @param length The number of bytes needed to encode the value of the field to be written. + * @param edit The prepared edit indicating where and in what context the current write will happen. + * @param type The type of the field to be written. + * @param typeArgs The type arguments of the field to be written. + * @param options The kind of edit to be performed. + * @param metaBytes On success, the number of bytes needed to encode the metadata of the new field. + * @param spaceNeeded On success, the number of bytes needed in total to encode the new field and its metadata. + * @param shift On success, the number of bytes the length of the row buffer was increased. + */ + private void ensureSparse( + final int length, + @Nonnull final RowCursor edit, + @Nonnull final LayoutType type, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out metaBytes, + @Nonnull final Out spaceNeeded, + @Nonnull final Out shift + ) { + checkNotNull(options, "expected non-null options"); + this.ensureSparse(length, edit, type, typeArgs, RowOptions.from(options.value()), metaBytes, spaceNeeded, shift); + } + + private void ensureVariable( + final int offset, + final boolean isVarint, + final int length, + final boolean exists, + @Nonnull final Out spaceNeeded, + @Nonnull final Out shift) { + + int spaceAvailable = 0; + long existingValueBytes = exists ? 0 : this.read7BitEncodedUInt(offset); + + if (isVarint) { + spaceNeeded.set(length); + } else { + assert existingValueBytes <= Integer.MAX_VALUE; + spaceAvailable += (int) existingValueBytes; + spaceNeeded.set(length + RowBuffer.count7BitEncodedUInt(length)); + } + + shift.set(spaceNeeded.get() - spaceAvailable); + + if (shift.get() != 0) { + final int destination = offset + spaceNeeded.get(); + final int source = offset + spaceAvailable; + this.shift(destination, source, this.length() - (offset + spaceAvailable)); + } + } + + /** + * Sorts a {@code uniqueIndex} list using the hybrid row binary collation. + * + * @param scope The scope to be sorted. + * @param edit A edit that points at the scope. + * @param uniqueIndex A unique index array structure that identifies the row offsets of each + * element in the scope. + * @return true if the array was sorted, false if a duplicate was found during sorting. + *

+ * Implementation Note: + *

This method MUST guarantee that if at least one duplicate exists it will be found.

+ * Insertion Sort is used for this purpose as it guarantees that each value is eventually compared + * against its previous item in sorted order. If any two successive items are the same they must be + * duplicates. + *

+ * Other search algorithms, such as Quick Sort or Merge Sort, may offer fewer comparisons in the + * limit but don't necessarily guarantee that duplicates will be discovered. If an alternative + * algorithm is used, then an independent duplicate pass MUST be employed. + *

+ *

+ * Under the current operational assumptions, the expected cardinality of sets and maps is + * expected to be relatively small. If this assumption changes, Insertion Sort may no longer be the + * best choice. + *

+ */ + private boolean insertionSort( + @Nonnull final RowCursor scope, + @Nonnull final RowCursor edit, + @Nonnull final List uniqueIndex) { + + checkNotNull(scope, "expected non-null scope"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(uniqueIndex, "expected non-null uniqueIndex"); + + RowCursor leftEdit = edit.clone(); + RowCursor rightEdit = edit.clone(); + + for (int i = 1; i < uniqueIndex.size(); i++) { + + UniqueIndexItem x = uniqueIndex.get(i); + leftEdit.cellType(LayoutType.fromLayoutCode(x.code())); + leftEdit.metaOffset(x.metaOffset()); + leftEdit.valueOffset(x.valueOffset()); + + final int leftBytes = x.size() - (x.valueOffset() - x.metaOffset()); + + // Walk backwards searching for the insertion point for the item as position i. + int j; + for (j = i - 1; j >= 0; j--) { + UniqueIndexItem y = uniqueIndex.get(j); + rightEdit.cellType(LayoutType.fromLayoutCode(y.code())); + rightEdit.metaOffset(y.metaOffset()); + rightEdit.valueOffset(y.valueOffset()); + + int cmp; + if (scope.scopeType() instanceof LayoutTypedMap) { + cmp = this.compareKeyValueFieldValue(leftEdit.clone(), rightEdit.clone()); + } else { + int rightBytes = y.size() - (y.valueOffset() - y.metaOffset()); + cmp = this.compareFieldValue(leftEdit.clone(), leftBytes, rightEdit.clone(), rightBytes); + } + + // If there are duplicates then fail. + if (cmp == 0) { + return false; + } + + if (cmp > 0) { + break; + } + + // Swap the jth item to the right to make space for the ith item which is smaller. + uniqueIndex.set(j + 1, uniqueIndex.get(j)); + } + + // Insert the ith item into the sorted array. + uniqueIndex.set(j + 1, x); + } + + return true; + } + + private Item read(@Nonnull final Supplier reader, @Nonnull final RowCursor cursor) { + + checkNotNull(reader, "expected non-null reader"); + checkNotNull(cursor, "expected non-null cursor"); + + Item item = this.read(reader, cursor.valueOffset()); + cursor.endOffset(this.buffer.readerIndex()); + + return item; + } + + private Item read(@Nonnull final Supplier reader, final int offset) { + + checkNotNull(reader, "expected non-null reader"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + this.buffer.readerIndex(offset); + final T value = reader.get(); + + return Item.of(value, offset, this.buffer.readerIndex() - offset); + } + + private Item read(@Nonnull final Function reader, final int offset, final int length) { + + checkNotNull(reader, "expected non-null reader"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + checkArgument(length >= 0, "expected non-negative length, not %s", length); + + this.buffer.readerIndex(offset); + final T value = reader.apply(length); + final int actualLength = this.buffer.readerIndex() - offset; + + checkState(actualLength == length, "expected read of length %s, not %s", length, actualLength); + return Item.of(value, offset, actualLength); + } + + private long read7BitEncodedInt(int offset) { + Item item = this.read(this::read7BitEncodedInt, offset); + return item.value(); + } + + private long read7BitEncodedInt() { + return RowBuffer.rotateSignToMsb(this.read7BitEncodedUInt()); + } + + private long read7BitEncodedUInt(int offset) { + Item item = this.read(this::read7BitEncodedUInt, offset); + return item.value(); + } + + private long read7BitEncodedUInt() { + + long b = this.buffer.readByte() & 0xFFL; + + if (b < 0x80L) { + return b; + } + + long result = b & 0x7FL; + int shift = 7; + + do { + checkState(shift < 10 * 7); + b = this.buffer.readByte() & 0xFFL; + result |= (b & 0x7FL) << shift; + shift += 7; + } while (b >= 0x80L); + + return result; + } + + private BigDecimal readDecimal() { + return DecimalCodec.decode(this.buffer); + } + + private Utf8String readFixedString(int length) { + return Utf8String.fromUnsafe(this.buffer.readSlice(length)); + } + + private Float128 readFloat128() { + return Float128Codec.decode(this.buffer); + } + + private UUID readGuid() { + return GuidCodec.decode(this.buffer); + } + + private HybridRowHeader readHeader() { + HybridRowVersion version = HybridRowVersion.from(this.buffer.readByte()); + SchemaId schemaId = SchemaId.from(this.buffer.readIntLE()); + return new HybridRowHeader(version, schemaId); + } + + /** + * Read the metadata of an encoded sparse field. + * + * @param edit The edit structure to fill in. + * + * {@code edit.Path} + * On success, the path of the field at the given offset, otherwise + * undefined. + * + * {@code edit.MetaOffset} + * On success, the offset to the metadata of the field, otherwise a + * location to insert the field. + * + * {@code edit.cellType} + * On success, the layout code of the existing field, otherwise + * undefined. + * + * {@code edit.TypeArgs} + * On success, the type args of the existing field, otherwise + * undefined. + * + * {@code edit.ValueOffset} + * On success, the offset to the value of the field, otherwise + * undefined. + *. + */ + private void readSparseMetadata(@Nonnull final RowCursor edit) { + + checkNotNull(edit, "expected non-null edit"); + + if (edit.scopeType().hasImplicitTypeCode(edit)) { + + edit.scopeType().setImplicitTypeCode(edit); + edit.valueOffset(edit.metaOffset()); + + } else { + + int metaOffset = edit.metaOffset(); + LayoutType layoutType = this.readSparseTypeCode(metaOffset); + + edit.cellType(layoutType); + edit.valueOffset(metaOffset + LayoutCode.BYTES); + edit.cellTypeArgs(TypeArgumentList.EMPTY); + + if (edit.cellType() instanceof LayoutEndScope) { + // Reached end of current scope without finding another field. + edit.pathToken(0); + edit.pathOffset(0); + edit.valueOffset(edit.metaOffset()); + return; + } + + Out lengthInBytes = new Out<>(); + edit.cellTypeArgs(edit.cellType().readTypeArgumentList(this, edit.valueOffset(), lengthInBytes)); + edit.valueOffset(edit.valueOffset() + lengthInBytes.get()); + } + + edit.scopeType().readSparsePath(this, edit); + } + + private void readSparsePrimitiveTypeCode(@Nonnull final RowCursor edit, @Nonnull final LayoutType code) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(code, "expected non-null code"); + checkArgument(edit.exists(), "expected edit.exists value of true, not false"); + + if (edit.scopeType().hasImplicitTypeCode(edit)) { + if (edit.scopeType() instanceof LayoutNullable) { + checkState(edit.scopeTypeArgs().count() == 1); + checkState(edit.index() == 1); + checkState(edit.scopeTypeArgs().get(0).type() == code); + checkState(edit.scopeTypeArgs().get(0).typeArgs().count() == 0); + } else if (edit.scopeType().isFixedArity()) { + checkState(edit.scopeTypeArgs().count() > edit.index()); + checkState(edit.scopeTypeArgs().get(edit.index()).type() == code); + checkState(edit.scopeTypeArgs().get(edit.index()).typeArgs().count() == 0); + } else { + checkState(edit.scopeTypeArgs().count() == 1); + checkState(edit.scopeTypeArgs().get(0).type() == code); + checkState(edit.scopeTypeArgs().get(0).typeArgs().count() == 0); + } + } else { + if (code == LayoutTypes.BOOLEAN) { + final LayoutType layoutType = this.readSparseTypeCode(edit.metaOffset()); + checkState(layoutType == LayoutTypes.BOOLEAN || layoutType == LayoutTypes.BOOLEAN_FALSE); + } else { + checkState(this.readSparseTypeCode(edit.metaOffset()) == code); + } + } + + if (edit.scopeType().isIndexedScope()) { + checkState(edit.pathOffset() == 0); + checkState(edit.pathToken() == 0); + } else { + int offset = edit.metaOffset() + LayoutCode.BYTES; + Out pathLenInBytes = new Out<>(); + Out pathOffset = new Out<>(); + int token = this.readSparsePathLen(edit.layout(), offset, pathOffset, pathLenInBytes); + checkState(edit.pathOffset() == pathOffset.get()); + checkState(edit.pathToken() == token); + } + } + + private UnixDateTime readUnixDateTime() { + return new UnixDateTime(this.buffer.readLongLE()); + } + + private Utf8String readUtf8String() { + long length = this.read7BitEncodedUInt(); + checkState(length <= Integer.MAX_VALUE, "expected length <= %s, not %s", Integer.MAX_VALUE, length); + return Utf8String.fromUnsafe(this.buffer.readSlice((int)length)); + } + + private ByteBuf readVariableBinary() { + long length = this.read7BitEncodedUInt(); + checkState(length <= Integer.MAX_VALUE, "expected length <= %s, not %s", Integer.MAX_VALUE, length); + return this.buffer.readSlice((int)length).asReadOnly(); + } + + private void shift(int destination, int source, int length) { + if (source != destination) { + if (length > 0) { + this.buffer.setBytes(destination, this.buffer, source, length); + } + this.buffer.writerIndex(destination + length); + } + } + + /** + * Skip over a nested scope. + * + * @param edit The sparse scope to search + * @return The zero-based byte offset immediately following the scope end marker + */ + private int skipScope(RowCursor edit) { + + //noinspection StatementWithEmptyBody + while (this.sparseIteratorMoveNext(edit)) { + } + + if (!edit.scopeType().isSizedScope()) { + edit.metaOffset(edit.metaOffset() + LayoutCode.BYTES); // move past end of scope marker + } + + return edit.metaOffset(); + } + + /** + * Compute the size of a sparse (primitive) field. + * + * @param type The type of the current sparse field. + * @param metaOffset The zero-based offset from the beginning of the row where the field begins. + * @param valueOffset The zero-based offset from the beginning of the row where the field's value begins. + * @return The length (in bytes) of the encoded field including the metadata and the value. + */ + private int sparseComputePrimitiveSize(LayoutType type, int metaOffset, int valueOffset) { + + // TODO: JTH: convert to a virtual? + + int metaBytes = valueOffset - metaOffset; + LayoutCode code = type.layoutCode(); + + switch (code) { + case NULL: + checkState(LayoutTypes.NULL.size() == 0); + return metaBytes; + + case BOOLEAN: + case BOOLEAN_FALSE: + checkState(LayoutTypes.BOOLEAN.size() == 0); + return metaBytes; + + case INT_8: + return metaBytes + LayoutTypes.INT_8.size(); + + case INT_16: + return metaBytes + LayoutTypes.INT_16.size(); + + case INT_32: + return metaBytes + LayoutTypes.INT_32.size(); + + case INT_64: + return metaBytes + LayoutTypes.INT_64.size(); + + case UINT_8: + return metaBytes + LayoutTypes.UINT_8.size(); + + case UINT_16: + return metaBytes + LayoutTypes.UINT_16.size(); + + case UINT_32: + return metaBytes + LayoutTypes.UINT_32.size(); + + case UINT_64: + return metaBytes + LayoutTypes.UINT_64.size(); + + case FLOAT_32: + return metaBytes + LayoutTypes.FLOAT_32.size(); + + case FLOAT_64: + return metaBytes + LayoutTypes.FLOAT_64.size(); + + case FLOAT_128: + return metaBytes + LayoutTypes.FLOAT_128.size(); + + case DECIMAL: + return metaBytes + LayoutTypes.DECIMAL.size(); + + case DATE_TIME: + return metaBytes + LayoutTypes.DATE_TIME.size(); + + case UNIX_DATE_TIME: + return metaBytes + LayoutTypes.UNIX_DATE_TIME.size(); + + case GUID: + return metaBytes + LayoutTypes.GUID.size(); + + case MONGODB_OBJECT_ID: + // return metaBytes + MongoDbObjectId.size(); + throw new UnsupportedOperationException(); + + case UTF_8: + case BINARY: { + Item item = this.read(this::read7BitEncodedUInt, metaOffset + metaBytes); + return metaBytes + item.length() + item.value().intValue(); + } + case VAR_INT: + case VAR_UINT: { + Item item = this.read(this::read7BitEncodedUInt, metaOffset + metaBytes); + return metaBytes + item.length(); + } + default: + throw new IllegalStateException(lenientFormat("Not Implemented: %s", code)); + } + } + + /** + * Compute the size of a sparse field. + * + * @param edit The edit structure describing the field to measure. + * @return The length (in bytes) of the encoded field including the metadata and the value. + */ + private int sparseComputeSize(RowCursor edit) { + + if (!(edit.cellType() instanceof LayoutTypeScope)) { + return this.sparseComputePrimitiveSize(edit.cellType(), edit.metaOffset(), edit.valueOffset()); + } + + // Compute offset to end of value for current value + RowCursor newScope = this.sparseIteratorReadScope(edit, true); + return this.skipScope(newScope) - edit.metaOffset(); + } + + /** + * Reads and validates the header of the current {@link RowBuffer}. + * + * @return {@code true} if the header validation succeeded; otherwise, if the header is invalid, {@code false} + */ + private boolean validateHeader(@Nonnull final HybridRowVersion version) { + + checkNotNull(version, "expected non-null version"); + + final Item item = this.read(this::readHeader, 0); + final HybridRowHeader header = item.value(); + final Layout layout = this.resolver.resolve(header.schemaId()); + + checkState(header.schemaId().equals(layout.schemaId())); + return header.version().equals(version) && (HybridRowHeader.BYTES + layout.size()) <= this.length(); + } + + private Item write(@Nonnull final Consumer consumer, final int offset, @Nonnull final T value) { + + checkNotNull(consumer, "expected non-null consumer"); + checkNotNull(value, "expected non-null value"); + checkArgument(offset >= 0, "expected non-negative offset"); + + final int priorWriterIndex = this.buffer.writerIndex(); + this.buffer.writerIndex(offset); + final int length; + + try { + consumer.accept(value); + length = this.buffer.writerIndex() - offset; + } finally { + if (priorWriterIndex > this.buffer.writerIndex()) { + this.buffer.writerIndex(priorWriterIndex); + } + } + + return new Item<>(value, offset, length); + } + + private void writeDateTime(OffsetDateTime value) { + DateTimeCodec.encode(value, this.buffer); + } + + private void writeDecimal(BigDecimal value) { + DecimalCodec.encode(value, this.buffer); + } + + private int writeDefaultValue(int offset, LayoutType code, TypeArgumentList typeArgs) { + + // TODO: DANOBLE: Put default values in a central location (LayoutTypes?) and use them in this method + // ensure that there are no null default values (which this method currently uses) + // TODO: JTH: convert to a virtual? + + if (code == LayoutTypes.NULL) { + this.writeSparseTypeCode(offset, code.layoutCode()); + return 1; + } + + if (code == LayoutTypes.BOOLEAN) { + this.writeSparseTypeCode(offset, LayoutCode.BOOLEAN_FALSE); + return 1; + } + + if (code == LayoutTypes.INT_8) { + this.writeInt8(offset, (byte) 0); + return LayoutTypes.INT_8.size(); + } + + if (code == LayoutTypes.INT_16) { + this.writeInt16(offset, (short) 0); + return LayoutTypes.INT_16.size(); + } + + if (code == LayoutTypes.INT_32) { + this.writeInt32(offset, 0); + return LayoutTypes.INT_32.size(); + } + + if (code == LayoutTypes.INT_64) { + this.writeInt64(offset, 0); + return LayoutTypes.INT_64.size(); + } + + if (code == LayoutTypes.UINT_8) { + this.writeUInt8(offset, (byte) 0); + return LayoutTypes.UINT_8.size(); + } + + if (code == LayoutTypes.UINT_16) { + this.writeUInt16(offset, (short) 0); + return LayoutTypes.UINT_16.size(); + } + + if (code == LayoutTypes.UINT_32) { + this.writeUInt32(offset, 0); + return LayoutTypes.UINT_32.size(); + } + + if (code == LayoutTypes.UINT_64) { + this.writeUInt64(offset, 0); + return LayoutTypes.UINT_64.size(); + } + + if (code == LayoutTypes.FLOAT_32) { + this.writeFloat32(offset, 0); + return LayoutTypes.FLOAT_32.size(); + } + + if (code == LayoutTypes.FLOAT_64) { + this.writeFloat64(offset, 0); + return LayoutTypes.FLOAT_64.size(); + } + + if (code == LayoutTypes.FLOAT_128) { + this.writeFloat128(offset, Float128.ZERO); + return LayoutTypes.FLOAT_128.size(); + } + + if (code == LayoutTypes.DECIMAL) { + this.writeDecimal(offset, BigDecimal.ZERO); + return LayoutTypes.DECIMAL.size(); + } + + if (code == LayoutTypes.DATE_TIME) { + this.writeDateTime(offset, OffsetDateTime.MIN); + return LayoutTypes.DATE_TIME.size(); + } + + if (code == LayoutTypes.UNIX_DATE_TIME) { + this.writeUnixDateTime(offset, UnixDateTime.EPOCH); + return LayoutTypes.UNIX_DATE_TIME.size(); + } + + if (code == LayoutTypes.GUID) { + this.writeGuid(offset, GuidCodec.EMPTY); + return LayoutTypes.GUID.size(); + } + + if (code == LayoutTypes.MONGODB_OBJECT_ID) { + // TODO: DANOBLE: Add support for LayoutTypes.MONGODB_OBJECT_ID + // this.writeMongoDbObjectId(offset, null); + // return MongoDbObjectId.Size; + throw new UnsupportedOperationException(); + } + + if (code == LayoutTypes.UTF_8 || code == LayoutTypes.BINARY || code == LayoutTypes.VAR_INT || code == LayoutTypes.VAR_UINT) { + // Variable length types preceded by their varuint size take 1 byte for a size of 0 + return this.write(this::write7BitEncodedUInt, offset, 0L).length(); + } + + if (code == LayoutTypes.OBJECT || code == LayoutTypes.ARRAY) { + // Variable length sparse collection scopes take 1 byte for the end-of-scope terminator. + this.writeSparseTypeCode(offset, LayoutCode.END_SCOPE); + return LayoutCode.BYTES; + } + + if (code == LayoutTypes.TYPED_ARRAY || code == LayoutTypes.TYPED_SET || code == LayoutTypes.TYPED_MAP) { + // Variable length typed collection scopes preceded by their scope size take sizeof(uint) for a size of 0. + this.writeUInt32(offset, 0); + return Integer.BYTES; + } + + if (code == LayoutTypes.TUPLE) { + // Fixed arity sparse collections take 1 byte for end-of-scope plus a null for each element. + for (int i = 0; i < typeArgs.count(); i++) { + this.writeSparseTypeCode(offset, LayoutCode.NULL); + } + this.writeSparseTypeCode(offset, LayoutCode.END_SCOPE); + return LayoutCode.BYTES + (LayoutCode.BYTES * typeArgs.count()); + } + + if (code == LayoutTypes.TYPED_TUPLE || code == LayoutTypes.TAGGED || code == LayoutTypes.TAGGED_2) { + // Fixed arity typed collections take the sum of the default values of each element. The scope size is + // implied by the arity. + int sum = 0; + for (final Iterator iterator = typeArgs.stream().iterator(); iterator.hasNext(); ) { + final TypeArgument arg = iterator.next(); + sum += this.writeDefaultValue(offset + sum, arg.type(), arg.typeArgs()); + } + return sum; + } + + if (code == LayoutTypes.NULLABLE) { + // Nullables take the default values of the value plus null. The scope size is implied by the arity. + this.writeInt8(offset, (byte) 0); + return 1 + this.writeDefaultValue(offset + 1, typeArgs.get(0).type(), typeArgs.get(0).typeArgs()); + } + + if (code == LayoutTypes.UDT) { + + // Clear all presence bits + Layout udt = this.resolver.resolve(typeArgs.schemaId()); + this.write(this.buffer::writeZero, offset, udt.size()); + + // Write scope terminator + this.writeSparseTypeCode(offset + udt.size(), LayoutCode.END_SCOPE); + return udt.size() + LayoutCode.BYTES; + } + + throw new IllegalStateException(lenientFormat("Not Implemented: %s", code)); + } + + private void writeFixedString(Utf8String value) { + this.buffer.writeBytes(value.content(), value.encodedLength()); + } + + private void writeGuid(UUID value) { + GuidCodec.encode(value, this.buffer); + } + + private void writeSparseMetadata( + @Nonnull final RowCursor edit, @Nonnull final LayoutType cellType, @Nonnull final TypeArgumentList typeArgs, + final int metaBytes) { + + int metaOffset = edit.metaOffset(); + + if (!edit.scopeType().hasImplicitTypeCode(edit)) { + metaOffset += cellType.writeTypeArgument(this, metaOffset, typeArgs); + } + + this.writeSparsePath(edit, metaOffset); + edit.valueOffset(edit.metaOffset() + metaBytes); + + checkState(edit.valueOffset() == edit.metaOffset() + metaBytes); + } + + private void writeSparsePath(@Nonnull final RowCursor edit, final int offset) { + + checkNotNull(edit, "expected non-null edit"); + checkArgument(offset >= 0, "expected non-negative offset"); + + // Some scopes don't encode paths, therefore the cost is always zero + + if (edit.scopeType().isIndexedScope()) { + edit.pathToken(0); + edit.pathOffset(0); + return; + } + + final StringTokenizer tokenizer = edit.layout().tokenizer(); + final Optional writePathToken = tokenizer.tryFindToken(edit.writePath()); + + checkState(!(writePathToken.isPresent() && edit.writePathToken().isNull())); + + if (!edit.writePathToken().isNull()) { + this.write(this.buffer::writeBytes, offset, edit.writePathToken().varint()); + edit.pathToken((int) edit.writePathToken().id()); + edit.pathOffset(offset); + } else { + // TODO: It would be better if we could avoid allocating here when the path is UTF16 + Utf8String writePath = edit.writePath().toUtf8(); + checkState(writePath != null); + edit.pathToken(tokenizer.count() + writePath.encodedLength()); + Item item = this.write(this::write7BitEncodedUInt, offset, (long) edit.pathToken()); + edit.pathOffset(offset + item.length()); + this.write(this::writeFixedString, edit.pathOffset(), writePath); + } + } + + + private void writeUInt16(Short value) { + this.buffer.writeShortLE(value); + } + + private void writeUInt32(Integer value) { + this.buffer.writeIntLE(value); + } + + private void writeUInt64(Long value) { + this.buffer.writeLongLE(value); + } + + private void writeUInt8(Byte value) { + this.buffer.writeByte(value); + } + + private int writeVariableBinary(int offset, ByteBuf value) { + Item item = this.write(this::writeVariableBinary, offset, value); + return item.length(); + } + + private void writeVariableBinary(ByteBuf value) { + this.write7BitEncodedUInt(value.readableBytes()); + this.buffer.writeBytes(value); + } + + private void writeVariableString(@Nonnull final Utf8String value) { + final int length = this.write7BitEncodedUInt((long) value.encodedLength()); + assert length == value.encodedLength(); + assert value.content() != null; + this.buffer.writeBytes(value.content().readerIndex(0)); + } + + private static class Item { + + private int length; + private int offset; + private T value; + + private Item(T value, int offset, int length) { + this.value = value; + this.offset = offset; + this.length = length; + } + + public int length() { + return this.length; + } + + public static Item of(T value, int offset, int length) { + return new Item<>(value, offset, length); + } + + public int offset() { + return this.offset; + } + + public T value() { + return this.value; + } + } + + /** + * Represents a single item within a set/map scope that needs to be indexed. + *

+ * This structure is used when rebuilding a set/map index during row streaming via {@link RowWriter}. Each item + * encodes its offsets and length within the row. + */ + static final class UniqueIndexItem { + + private LayoutCode code = LayoutCode.values()[0]; + private int metaOffset; + private int size; + private int valueOffset; + + /** + * The layout code of the value. + */ + public LayoutCode code() { + return this.code; + } + + public UniqueIndexItem code(LayoutCode code) { + this.code = code; + return this; + } + + /** + * If existing, the offset to the metadata of the existing field, otherwise the location to insert a new field. + */ + public int metaOffset() { + return this.metaOffset; + } + + public UniqueIndexItem metaOffset(int metaOffset) { + this.metaOffset = metaOffset; + return this; + } + + /** + * Size of the target element. + */ + public int size() { + return this.size; + } + + public UniqueIndexItem size(int size) { + this.size = size; + return this; + } + + /** + * If existing, the offset to the value of the existing field, otherwise undefined. + */ + public int valueOffset() { + return this.valueOffset; + } + + public UniqueIndexItem valueOffset(int valueOffset) { + this.valueOffset = valueOffset; + return this; + } + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..f922c10 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursor.java @@ -0,0 +1,415 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import com.azure.data.cosmos.core.UtfAnyString; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutEndScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTuple; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypeScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypes; +import com.azure.data.cosmos.serialization.hybridrow.layouts.StringToken; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; + +import static com.google.common.base.Strings.lenientFormat; + +public final class RowCursor implements Cloneable { + + private LayoutType cellType; + private TypeArgumentList cellTypeArgs; + private int count; + private boolean deferUniqueIndex; + private int endOffset; + private boolean exists; + private boolean immutable; + private int index; + private Layout layout; + private int metaOffset; + private int pathOffset; + private int pathToken; + private LayoutTypeScope scopeType; + private TypeArgumentList scopeTypeArgs; + private int start; + private int valueOffset; + private UtfAnyString writePath; + private StringToken writePathToken; + + 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(); + } catch (CloneNotSupportedException error) { + throw new IllegalStateException(error); + } + } + + /** + * 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 offset = row.computeVariableValueOffset(layout, HybridRowHeader.BYTES, layout.numVariable()); + + return new RowCursor() + .layout(layout) + .scopeType(LayoutTypes.UDT) + .scopeTypeArgs(new TypeArgumentList(schemaId)) + .start(HybridRowHeader.BYTES) + .metaOffset(offset) + .valueOffset(offset); + } + + public static RowCursor createForAppend(RowBuffer row) { + + final SchemaId schemaId = row.readSchemaId(1); + final Layout layout = row.resolver().resolve(schemaId); + + return new RowCursor() + .layout(layout) + .scopeType(LayoutTypes.UDT) + .scopeTypeArgs(new TypeArgumentList(schemaId)) + .start(HybridRowHeader.BYTES) + .metaOffset(row.length()) + .valueOffset(row.length()); + } + + /** + * If true, this scope is a unique index scope whose index will be built after its items are written. + * + * @return {@code true}, if this cursor identifies a unique index scope, otherwise {@code false}. + */ + public boolean deferUniqueIndex() { + return this.deferUniqueIndex; + } + + /** + * Sets a value that indicates whether this cursor identifies a unique index scope. + * + * @param value {@code true}, if this cursor identifies a unique index scope, otherwise {@code false}. + * @return a reference to this {@link RowCursor}. + */ + public RowCursor deferUniqueIndex(boolean value) { + this.deferUniqueIndex = value; + return this; + } + + /** + * If existing, the offset to the end of the existing field. + *

+ * This value is used as a hint when skipping forward. + * + * @return offset of the end of an existing field. + */ + public int endOffset() { + return this.endOffset; + } + + /** + * Sets a value that indicates whether this cursor identifies a unique index scope. + * + * @param value {@code true}, if this cursor identifies a unique index scope, otherwise {@code false}. + * @return a reference to this {@link RowCursor}. + */ + public RowCursor endOffset(int value) { + this.endOffset = value; + return this; + } + + /** + * {@code true} if an existing field matching the search criteria was found. + * + * @return {@code true} if an existing field matching the search criteria was found, otherwise {@code false}. + */ + public boolean exists() { + return this.exists; + } + + /** + * Sets a value that indicates whether this cursor identifies a field matching search criteria. + * + * @param value {@code true}, if this cursor identifies a field matching search criteria, otherwise {@code false}. + * @return a reference to this {@link RowCursor}. + */ + public RowCursor exists(boolean value) { + this.exists = value; + return this; + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * The layout describing the contents of the scope, or {@code null} if the scope is unschematized. + * + * @return layout describing the context of the scope, or {@code null} if the scope is unschematized. + */ + public Layout layout() { + return this.layout; + } + + public RowCursor layout(Layout value) { + this.layout = value; + return this; + } + + /** + * If existing, offset to the metadata of the existing field, otherwise the location to insert a new field. + * + * @return offset to the metadata of an existing field or the location to insert a new field. + */ + public int metaOffset() { + return this.metaOffset; + } + + public RowCursor metaOffset(final int value) { + this.metaOffset = value; + return this; + } + + /** + * If existing, the offset scope relative path for reading. + * + * @return If existing, the offset scope relative path for reading. + */ + public int pathOffset() { + return this.pathOffset; + } + + public RowCursor pathOffset(final int value) { + this.pathOffset = value; + return this; + } + + /** + * If existing, the layout string token of scope relative path for reading. + * + * @return If existing, the layout string token of scope relative path for reading. + */ + public int pathToken() { + return this.pathToken; + } + + public RowCursor pathToken(int value) { + this.pathToken = value; + return this; + } + + /** + * The kind of scope within which this edit was prepared. + * + * @return The kind of scope within which this edit was prepared. + */ + public LayoutTypeScope scopeType() { + return this.scopeType; + } + + public RowCursor scopeType(LayoutTypeScope scopeType) { + this.scopeType = scopeType; + return this; + } + + /** + * The type parameters of the scope within which this edit was prepared. + * + * @return The type parameters of the scope within which this edit was prepared. + */ + public TypeArgumentList scopeTypeArgs() { + return this.scopeTypeArgs; + } + + public RowCursor scopeTypeArgs(TypeArgumentList scopeTypeArgs) { + this.scopeTypeArgs = scopeTypeArgs; + return this; + } + + /** + * The 0-based offset from the beginning of the row where the first sparse field within the scope begins. + * + * @return 0-based offset from the beginning of the row where the first sparse field within the scope begins. + */ + public int start() { + return this.start; + } + + public RowCursor start(int start) { + this.start = start; + return this; + } + + @Override + public String toString() { + + try { + + if (this.scopeType() == null) { + return ""; + } + + TypeArgument scopeTypeArg = (this.scopeType() instanceof LayoutEndScope) + ? TypeArgument.NONE + : new TypeArgument(this.scopeType(), this.scopeTypeArgs()); + + TypeArgument typeArg = (this.cellType() == null) || (this.cellType() instanceof LayoutEndScope) + ? TypeArgument.NONE + : new TypeArgument(this.cellType(), this.cellTypeArgs()); + + String pathOrIndex = this.writePath().isNull() ? String.valueOf(this.index()) : this.writePath().toString(); + + return lenientFormat("%s[%s] : %s@%s/%s%s", + scopeTypeArg, + pathOrIndex, + typeArg, + this.metaOffset(), + this.valueOffset(), + this.immutable() ? " immutable" : ""); + + } catch (Exception ignored) { + return ""; + } + } + + /** + * If existing, the offset to the value of the existing field, otherwise undefined. + * + * @return If existing, the offset to the value of the existing field, otherwise undefined. + */ + public int valueOffset() { + return this.valueOffset; + } + + public RowCursor valueOffset(int valueOffset) { + this.valueOffset = valueOffset; + return this; + } + + /** + * If existing, the scope relative path for writing. + * + * @return If existing, the scope relative path for writing. + */ + public UtfAnyString writePath() { + return this.writePath; + } + + public void writePath(UtfAnyString writePath) { + this.writePath = writePath; + } + + /** + * If {@link #writePath} is tokenized, then its token. + * + * @return if {@link #writePath} is tokenized, then its token. + */ + public StringToken writePathToken() { + return this.writePathToken; + } + + public void writePathToken(StringToken writePathToken) { + this.writePathToken = writePathToken; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java new file mode 100644 index 0000000..f795404 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowCursors.java @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import com.azure.data.cosmos.core.UtfAnyString; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutEndScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.StringToken; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class RowCursors { + + private RowCursors() { + } + + public static RowCursor Find(@Nonnull RowCursor edit, @Nonnull RowBuffer row, @Nonnull UtfAnyString path) { + checkArgument(!edit.scopeType().isIndexedScope()); + + if (!(edit.cellType() instanceof LayoutEndScope)) { + while (row.sparseIteratorMoveNext(edit)) { + if (path.equals(row.readSparsePath(edit))) { + edit.exists(true); + break; + } + } + } + + edit.writePath(path); + edit.writePathToken(null); + + return edit; + } + + public static RowCursor Find(@Nonnull RowCursor edit, @Nonnull RowBuffer row, @Nonnull StringToken pathToken) { + + checkNotNull(edit); + checkNotNull(row); + checkNotNull(pathToken); + + checkArgument(!edit.scopeType().isIndexedScope()); + + if (!(edit.cellType() instanceof LayoutEndScope)) { + while (row.sparseIteratorMoveNext(edit)) { + if (pathToken.id() == (long) edit.pathToken()) { + edit.exists(true); + break; + } + } + } + + edit.writePath(new UtfAnyString(pathToken.path())); + edit.writePathToken(pathToken); + + return edit; + } + + /** + * An equivalent scope that is read-only. + * + * @param source source scope. + * @return an equivalent scope that is read-only. + */ + public static RowCursor asReadOnly(RowCursor source) { + return source.clone().immutable(true); + } + + /** + * Makes a copy of the current cursor. + *

+ * The two cursors will have independent and unconnected lifetimes after cloning. However, mutations to a + * {@link RowBuffer} can invalidate any active cursors over the same row. + * + * @param source source cursor. + * @return copy of the source cursor. + */ + public static RowCursor copy(RowCursor source) { + return source.clone(); + } + + public static boolean moveNext(RowCursor edit, RowBuffer row) { + edit.writePath(null); + edit.writePathToken(null); + return row.sparseIteratorMoveNext(edit); + } + + public static boolean moveNext(@Nonnull RowCursor edit, @Nonnull RowBuffer row, @Nonnull RowCursor childScope) { + if (childScope.scopeType() != null) { + RowCursors.skip(edit.clone(), row, childScope); + } + return RowCursors.moveNext(edit.clone(), row); + } + + public static boolean moveTo(@Nonnull final RowCursor edit, @Nonnull final RowBuffer row, final int index) { + + checkNotNull(row); + checkNotNull(edit); + checkArgument(edit.index() <= index); + + edit.writePath(null); + edit.writePathToken(null); + + while (edit.index() < index) { + if (!row.sparseIteratorMoveNext(edit)) { + return false; + } + } + + return true; + } + + public static void skip( + @Nonnull final RowCursor edit, @Nonnull final RowBuffer buffer, @Nonnull final RowCursor childScope) { + + checkNotNull(edit, "expected non-null edit"); + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(childScope, "expected non-null childScope"); + + checkArgument(childScope.start() == edit.valueOffset()); + + if (!(childScope.cellType() instanceof LayoutEndScope)) { + //noinspection StatementWithEmptyBody + while (buffer.sparseIteratorMoveNext(childScope)) { + } + } + + if (childScope.scopeType().isSizedScope()) { + edit.endOffset(childScope.metaOffset()); + } else { + edit.endOffset(childScope.metaOffset() + LayoutCode.BYTES); // move past end of scope marker + } + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..f9d58fc --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/RowOptions.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +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. + */ +public enum RowOptions { + + NONE(0), + + /** + * Overwrite an existing value. + *

+ * An existing value is assumed to exist at the offset provided. The existing value is + * replaced inline. The remainder of the row is resized to accomodate either an increase or decrease + * in required space. + */ + UPDATE(1), + + /** + * Insert a new value. + *

+ * An existing value is assumed NOT to exist at the offset provided. The new value is + * inserted immediately at the offset. The remainder of the row is resized to accomodate either an + * increase or decrease in required space. + */ + INSERT(2), + + /** + * Update an existing value or insert a new value, if no value exists. + *

+ * If a value exists, then this operation becomes {@link #UPDATE}, otherwise it + * becomes {@link #INSERT}. + */ + UPSERT(3), + + /** + * Insert a new value moving existing values to the right. + *

+ * Within an array scope, inserts a new value immediately at the index moving all subsequent + * items to the right. In any other scope behaves the same as {@link #UPSERT}. + */ + INSERT_AT(4), + + /** + * Delete an existing value. + *

+ * 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 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; + } + + public static RowOptions from(int value) { + return mappings.get().get(value); + } + + public int value() { + return this.value; + } +} \ 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 new file mode 100644 index 0000000..91b1459 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/SchemaId.java @@ -0,0 +1,160 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import it.unimi.dsi.fastutil.HashCommon; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; + +import javax.annotation.Nonnull; +import java.io.IOException; + +import static com.google.common.base.Strings.lenientFormat; +import static it.unimi.dsi.fastutil.HashCommon.mix; + +/** + * 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) +@JsonSerialize(using = SchemaId.JsonSerializer.class) +public final class SchemaId implements Comparable { + + public static final int BYTES = Integer.BYTES; + public static final SchemaId INVALID; + public static final SchemaId NONE; + + private static final Int2ReferenceMap cache; + + static { + cache = new Int2ReferenceOpenHashMap<>(); + cache.put(0, INVALID = NONE = new SchemaId(0)); + } + + private final int value; + + /** + * Initializes a new instance of the {@link SchemaId} class. + * + * @param value The underlying globally unique identifier of the schema. + */ + private SchemaId(int value) { + this.value = value; + } + + @Override + public int compareTo(@Nonnull SchemaId other) { + return Integer.compare(this.value, other.value); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || this.getClass() != other.getClass()) { + return false; + } + SchemaId schemaId = (SchemaId) other; + return this.value == schemaId.value; + } + + /** + * {@code true} if this is the same {@link SchemaId} as {@code other}. + * + * @param other The value to compare against. + * @return {@code true} if the two values are the same. + */ + public boolean equals(SchemaId other) { + if (null == other) { + return false; + } + return this.value() == other.value(); + } + + /** + * Returns a {@link SchemaId} with the given underlying integer value. + * + * @param value an integer. + * @return a {@link SchemaId} with the given underlying integer {@code value}. + */ + public static SchemaId from(int value) { + return cache.computeIfAbsent(value, SchemaId::new); + } + + /** + * Returns the hash code value for this {@link SchemaId}. + *

+ * This method mixes the bits of the underlying {@code int} value of the {@link SchemaId} by multiplying by the + * golden ratio and xor-shifting the result. It has slightly worse behavior than MurmurHash3. In open-addressing + * In open-addressing tables the average number of probes is slightly larger, but the computation of the value + * is faster. + * + * @return the hash code value for this {@link SchemaId}. + * @see HashCommon#mix(int) + * @see Koloboke + * @see MurmurHash + */ + @Override + public int hashCode() { + return mix(this.value); + } + + @Override + public String toString() { + return Integer.toString(this.value); + } + + /** + * The underlying integer value of this {@link SchemaId}. + * + * @return The integer value of this {@link SchemaId} + */ + public int value() { + return this.value; + } + + static final class JsonDeserializer extends StdDeserializer { + + private JsonDeserializer() { + super(SchemaId.class); + } + + @Override + public SchemaId deserialize(final JsonParser parser, final DeserializationContext context) throws IOException { + + final int value = parser.getIntValue(); + + if (value == 0) { + String message = "expected non-zero int value for SchemaId"; + throw MismatchedInputException.from(parser, SchemaId.class, message); + } + + return SchemaId.from(value); + } + } + + static final class JsonSerializer extends StdSerializer { + + private JsonSerializer() { + super(SchemaId.class); + } + + @Override + public void serialize( + final SchemaId value, final JsonGenerator generator, final SerializerProvider provider) throws IOException { + generator.writeNumber(value.value()); + } + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/UnixDateTime.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/UnixDateTime.java new file mode 100644 index 0000000..49be205 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/UnixDateTime.java @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow; + +/** + * A wall clock time expressed in milliseconds since the Unix Epoch. + *

+ * A {@link UnixDateTime} is a fixed length value-type providing millisecond + * granularity as a signed offset from the Unix Epoch (midnight, January 1, 1970 UTC). + */ +public final class UnixDateTime { + /** + * Unix epoch. + *

+ * {@link UnixDateTime} values are signed values centered on this value. + */ + public static final UnixDateTime EPOCH = new UnixDateTime(); + + /** + * Size in bytes of a {@link UnixDateTime}. + */ + public static final int BYTES = Long.SIZE; + + private long milliseconds; + + private UnixDateTime() { + } + + /** + * Initializes a new instance of the {@link UnixDateTime} class. + * + * @param milliseconds The number of milliseconds since {@link #EPOCH}. + */ + public UnixDateTime(long milliseconds) { + this.milliseconds = milliseconds; + } + + /** + * {@code> true} if this value is the same as another value. + * + * @param other value to compare. + * @return {code true} if this value is the same as the {code other}, {@code false} otherwise. + */ + public boolean equals(UnixDateTime other) { + if (other == null) { + return false; + } + return this.milliseconds() == other.milliseconds(); + } + + @Override + public boolean equals(Object other) { + if (null == other) { + return false; + } + if (this == other) { + return true; + } + return other instanceof UnixDateTime && this.equals((UnixDateTime)other); + } + + @Override + public int hashCode() { + return Long.valueOf(this.milliseconds).hashCode(); + } + + /** + * The number of milliseconds since {@link #EPOCH}. + *

+ * This value may be negative. + * + * @return the number of milliseconds since {@link #EPOCH}. + */ + public long milliseconds() { + return this.milliseconds; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodec.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodec.java new file mode 100644 index 0000000..53254a6 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodec.java @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Provides static methods for encoding and decoding {@link OffsetDateTime}s serialized as {@code System.DateTime}s + * + * {@link OffsetDateTime} values are serialized as unsigned 64-bit integers: + * + * + * + * + * + * + *
+ * Bits 01-62 + * + * Contain the number of 100-nanosecond ticks where 0 represents {@code 1/1/0001 12:00am}, up until the value + * {@code 12/31/9999 23:59:59.9999999}. + *
+ * Bits 63-64 + * + * Contain a four-state value that describes the {@code System.DateTimeKind} value of the date time, with a + * 2nd value for the rare case where the date time is local, but is in an overlapped daylight savings time + * hour and it is in daylight savings time. This allows distinction of these otherwise ambiguous local times + * and prevents data loss when round tripping from Local to UTC time. + *
+ * + * @see struct DateTime source + */ +public final class DateTimeCodec { + + public static final int BYTES = Long.BYTES; + + private static final long FLAGS_MASK = 0xC000000000000000L; + private static final long KIND_AMBIGUOUS = 0xC000000000000000L; + private static final long KIND_LOCAL = 0x8000000000000000L; + private static final long KIND_UTC = 0x4000000000000000L; + private static final long TICKS_MASK = 0x3FFFFFFFFFFFFFFFL; + + private static final long UNIX_EPOCH_TICKS = 0x89F7FF5F7B58000L; + + private static final ZoneOffset ZONE_OFFSET_LOCAL = OffsetDateTime.now().getOffset(); + private static final int ZONE_OFFSET_LOCAL_TOTAL_SECONDS = ZONE_OFFSET_LOCAL.getTotalSeconds(); + private static final int ZONE_OFFSET_UTC_TOTAL_SECONDS = ZoneOffset.UTC.getTotalSeconds(); + + private DateTimeCodec() { + } + + /** + * Decode an {@link OffsetDateTime} serialized like a {@code System.DateTime} by {@code MemoryMarshal.Write}. + * + * @param bytes an array containing the serialized value to be decoded. + * @return a new {@link OffsetDateTime}. + * @see struct DateTime source + */ + public static OffsetDateTime decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode an {@link OffsetDateTime} serialized like a {@code System.DateTime} by {@code MemoryMarshal.Write}. + * + * @param in a {@link ByteBuf} containing the serialized value to be decoded. + * @return a new {@link OffsetDateTime}. + * @see struct DateTime source + */ + public static OffsetDateTime decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + final long data = in.readLongLE(); + final long ticks = data & TICKS_MASK; + final ZoneOffset zoneOffset = (data & FLAGS_MASK) == KIND_UTC ? ZoneOffset.UTC : ZONE_OFFSET_LOCAL; + + final long epochSecond = ((ticks - UNIX_EPOCH_TICKS) / 10_000_000L) - zoneOffset.getTotalSeconds(); + final int nanos = (int) (100L * (ticks % 10_000_000L)); + + return OffsetDateTime.ofInstant(Instant.ofEpochSecond(epochSecond, nanos), zoneOffset); + } + + /** + * Encode an {@link OffsetDateTime} like a {@code System.DateTime} serialized by {@code MemoryMarshal.Write}. + * + * @param offsetDateTime an {@link OffsetDateTime} to be encoded. + * @return a new byte array containing the encoded {@code offsetDateTime}. + * @see struct DateTime source + */ + public static byte[] encode(final OffsetDateTime offsetDateTime) { + final byte[] bytes = new byte[BYTES]; + encode(offsetDateTime, Unpooled.wrappedBuffer(bytes).clear()); + return bytes; + } + + /** + * Encode an {@link OffsetDateTime} like a {@code System.DateTime} produced by {@code MemoryMarshal.Write}. + * + * @param offsetDateTime an {@link OffsetDateTime} to be encoded. + * @param out an output {@link ByteBuf}. + * @see struct DateTime source + */ + public static void encode(final OffsetDateTime offsetDateTime, final ByteBuf out) { + + final ZoneOffset offset = offsetDateTime.getOffset(); + final Instant instant = offsetDateTime.toInstant(); + + final long ticks = UNIX_EPOCH_TICKS + 10_000_000L * (instant.getEpochSecond() + offset.getTotalSeconds()) + + instant.getNano() / 100L; + + checkArgument(ticks <= TICKS_MASK, "expected offsetDateTime epoch second in range [0, %s], not %s", + TICKS_MASK, + ticks); + + final int zoneOffsetTotalSeconds = offsetDateTime.getOffset().getTotalSeconds(); + final long value; + + if (zoneOffsetTotalSeconds == ZONE_OFFSET_UTC_TOTAL_SECONDS) { + value = ticks | KIND_UTC; + } else if (zoneOffsetTotalSeconds == ZONE_OFFSET_LOCAL_TOTAL_SECONDS) { + value = ticks | KIND_LOCAL; + } else { + value = ticks | KIND_AMBIGUOUS; + } + + out.writeLongLE(value); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodec.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodec.java new file mode 100644 index 0000000..d8ecb07 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodec.java @@ -0,0 +1,200 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.util.ByteProcessor; + +import javax.annotation.Nonnull; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.math.RoundingMode; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static java.lang.Math.max; +import static java.lang.Math.min; + +/** + * Provides static methods for encoding and decoding {@link BigDecimal}s serialized as {@code System.Decimal}s + * + * The serialization format is lossy as the {@link BigDecimal} class represents arbitrary-precision signed decimal + * numbers while the binary representation of a {@code System.Decimal} value is constrained to a magnitude of 96-bits + * with a scaling factor of 10 and a scale value between 0 and 28. This yields a precision between 28 and 29 + * decimal digits. + * + * @see struct Decimal source + */ +public final class DecimalCodec { + + public static final int BYTES = 4 * Integer.BYTES; + + private static final int FLAGS_MASK_INVALID = 0b01111111000000001111111111111111; + private static final int FLAGS_MASK_POWER = 0b00000000111111110000000000000000; + private static final int FLAGS_MASK_SIGN = 0b10000000000000000000000000000000; + + private static final BigInteger MAGNITUDE_MAX = new BigInteger(new byte[] { + (byte)0x00, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF }); + + private static final BigInteger MAGNITUDE_MIN = new BigInteger(new byte[] { + (byte)0xFF, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01 }); + + private static final MathContext REDUCED_PRECISION = new MathContext(28, RoundingMode.HALF_EVEN); + + private static final int SCALE_MAX = 28; + private static final int SCALE_MIN = 0; + private static final int SCALE_SHIFT = 16; + + private static final int VALUE_LENGTH = 3 * Integer.BYTES; + private static final int[] VALUE_OFFSETS = { /* hi */ 0, /* lo */ 2 * Integer.BYTES, /* mid */ Integer.BYTES }; + + private DecimalCodec() { + } + + /** + * Decode an {@link BigDecimal} serialized like a {@code System.Decimal} by {@code MemoryMarshal.Write}. + * + * @param bytes an array containing the serialized {@code System.Decimal} to be decoded. + * @return a new {@link BigDecimal}. + * @see struct Decimal source + */ + public static BigDecimal decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode an {@link BigDecimal} serialized like a {@code System.Decimal} by {@code MemoryMarshal.Write}. + * + * @param in a {@link ByteBuf} containing the serialized {@code System.Decimal} to be decoded. + * @return a new {@link BigDecimal}. + * @see struct Decimal source + */ + public static BigDecimal decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + // The flags field is interpreted as follows + // + // Bits Interpretation + // ----- -------------------------------------------------------------------------------------------- + // 00-15 unused and must be zero + // 16-23 a value between 0 and 28 specifying the number of digits to the right of the decimal point + // 24-30 unused and must be zero + // 31-31 specifies the sign of the value, 1 meaning negative and 0 meaning non-negative + + final int flags = in.readIntLE(); + checkState((flags & FLAGS_MASK_INVALID) == 0, "invalid flags field: %s", flags); + + final int scale = (flags & FLAGS_MASK_POWER) >>> SCALE_SHIFT; + checkState(scale <= SCALE_MAX); + + final int signum = (flags & FLAGS_MASK_SIGN) == 0 ? 1 : -1; + final byte[] magnitude = new byte[VALUE_LENGTH]; + final int source = in.readerIndex(); + int target = 0; + + for (int offset : VALUE_OFFSETS) { + final int start = target; + in.forEachByteDesc(source + offset, Integer.BYTES, new ByteProcessor() { + int index = start; + @Override + public boolean process(byte value) { + magnitude[this.index++] = value; + return true; + } + }); + target += Integer.BYTES; + } + + return new BigDecimal(new BigInteger(signum, magnitude), scale); + } + + /** + * Encode a {@link BigDecimal} like a {@code System.Decimal} serialized by {@code MemoryMarshal.Write}. + * + * @param bigDecimal a {@link BigDecimal} to be encoded. + * @return a new byte array containing the encoded {@code bigDecimal}. + * @see struct Decimal source + */ + public static byte[] encode(final BigDecimal bigDecimal) { + ByteBuf buffer = Unpooled.wrappedBuffer(new byte[BYTES]).clear(); + encode(bigDecimal, buffer); + return buffer.array(); + } + + /** + * Encode a {@link BigDecimal} like a {@code System.Decimal} serialized by {@code MemoryMarshal.Write}. + * + * @param value a {@link BigDecimal} to be encoded. + * @param out an output {@link ByteBuf}. + * @see struct Decimal source + */ + public static void encode(@Nonnull BigDecimal value, @Nonnull final ByteBuf out) { + + checkNotNull(value, "expected non-null value"); + checkNotNull(value, "expected non-null out"); + + final int signum = value.signum(); + + if (signum == 0) { + out.writeZero(BYTES); + return; + } + + BigInteger unscaledValue = value.unscaledValue(); + + if (unscaledValue.compareTo(MAGNITUDE_MIN) < 0 || unscaledValue.compareTo(MAGNITUDE_MAX) > 0) { + value = value.stripTrailingZeros(); + unscaledValue = value.unscaledValue(); + if (unscaledValue.compareTo(MAGNITUDE_MIN) < 0 || unscaledValue.compareTo(MAGNITUDE_MAX) > 0) { + value = new BigDecimal(unscaledValue, min(max(value.scale(), SCALE_MIN), SCALE_MAX), REDUCED_PRECISION); + unscaledValue = value.unscaledValue(); + } + } + + if (value.scale() < SCALE_MIN) { + value = value.setScale(SCALE_MIN, RoundingMode.HALF_EVEN); + unscaledValue = value.unscaledValue(); + } else if (value.scale() > SCALE_MAX) { + value = value.setScale(SCALE_MAX, RoundingMode.HALF_EVEN); + unscaledValue = value.unscaledValue(); + } + + final byte[] decimalParts = new byte[VALUE_LENGTH]; + final byte[] bytes; + final int flags; + + if (signum > 0) { + flags = value.scale() << SCALE_SHIFT; + bytes = unscaledValue.toByteArray(); + } else { + flags = value.scale() << SCALE_SHIFT | FLAGS_MASK_SIGN; + bytes = unscaledValue.abs().toByteArray(); + } + + out.writeIntLE(flags); + + for (int i = bytes.length, j = 0; i > 0 && j < decimalParts.length; ) { + decimalParts[j++] = bytes[--i]; + } + + out.writeBytes(decimalParts, 2 * Integer.BYTES, Integer.BYTES); // high + out.writeBytes(decimalParts, 0, Integer.BYTES); // low + out.writeBytes(decimalParts, Integer.BYTES, Integer.BYTES); // mid + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/Float128Codec.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/Float128Codec.java new file mode 100644 index 0000000..8bc78ae --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/Float128Codec.java @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class Float128Codec { + + public static final int BYTES = 2 * Long.BYTES; + + private Float128Codec() { + } + + /** + * Decode a {@link Float128} from a sequence of two {@code long}s in little endian format. + * + * @param bytes an array containing the serialized {@link Float128} to be decoded. + * @return a new {@link Float128}. + */ + public static Float128 decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode a {@link Float128} from a sequence of two {@code long}s in little endian format. + * + * @param in a {@link ByteBuf} containing the serialized {@link Float128} to be decoded. + * @return a new {@link Float128}. + */ + public static Float128 decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s", + BYTES, + in.readableBytes()); + + return new Float128(in.readLongLE(), in.readLongLE()); + } + + /** + * Encodes a {@link Float128} as a sequence of two {@code long}s in little endian format. + * + * @param value a {@link Float128} to be encoded. + * @return a new byte array containing the encoded. + */ + public static byte[] encode(final Float128 value) { + final byte[] bytes = new byte[BYTES]; + encode(value, Unpooled.wrappedBuffer(bytes)); + return bytes; + } + + /** + * Encodes a {@link Float128} as a sequence of two {@code long}s in little endian format. + * + * @param value a {@link Float128} to be encoded. + * @param out an output {@link ByteBuf}. + */ + public static void encode(final Float128 value, final ByteBuf out) { + out.writeLongLE(value.high()); + out.writeLongLE(value.low()); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodec.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodec.java new file mode 100644 index 0000000..4a79b16 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodec.java @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import java.util.UUID; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Provides static methods for encoding and decoding {@link UUID}s serialized as {@code System.Guid}s + * + * {@link UUID}s are serialized like {@code System.Guid}s read and written by {@code MemoryMarshal.Read} and + * {@code MemoryMarshal.Write}. + * + * + * + * + * + * + * + * + *
+ * Bits 00-31 + * + * Contain an unsigned 32-bit int serialized in little-endian format. + *
+ * Bits 32-47 + * + * Contain an unsigned 16-bit int serialized in little-endian format. + *
+ * Bits 48-63 + * + * Contain an unsigned 16-bit int serialized in little-endian format. + *
+ * Bits 64-127 + * + * Contain an unsigned 64-bit int serialized in big-endian format. + *
+ * + * @see struct Guid source + */ +public final class GuidCodec { + + public static final int BYTES = 2 * Long.BYTES; + public static final UUID EMPTY = new UUID(0L, 0L); + + private GuidCodec() { + } + + /** + * Decode a {@link UUID} serialized like a {@code System.Guid} by {@code MemoryMarshal.Write}. + * + * @param bytes an array containing the serialized {@link UUID} to be decoded. + * @return a new {@link UUID}. + */ + public static UUID decode(@Nonnull final byte[] bytes) { + checkNotNull(bytes); + return decode(Unpooled.wrappedBuffer(bytes)); + } + + /** + * Decode a {@link UUID} serialized like a {@code System.Guid} by {@code MemoryMarshal.Write}. + * + * @param in a {@link ByteBuf} containing the serialized {@link UUID} to be decoded. + * @return a new {@link UUID}. + */ + public static UUID decode(@Nonnull final ByteBuf in) { + + checkNotNull(in, "expected non-null in"); + + checkArgument(in.readableBytes() >= BYTES, "expected %s readable bytes, not %s bytes", + BYTES, in.readableBytes()); + + final long mostSignificantBits = in.readUnsignedIntLE() << Integer.SIZE + | (0x000000000000FFFFL & in.readShortLE()) << Short.SIZE + | (0x000000000000FFFFL & in.readShortLE()); + + return new UUID(mostSignificantBits, in.readLong()); + } + + /** + * Encodes a {@link UUID} like a {@code System.Guid} serialized by {@code MemoryMarshal.Write}. + * + * @param uuid a {@link UUID} to be encoded. + * @return a new byte array containing the encoded. + */ + public static byte[] encode(final UUID uuid) { + final byte[] bytes = new byte[BYTES]; + encode(uuid, Unpooled.wrappedBuffer(bytes).clear()); + return bytes; + } + + /** + * Encodes a {@link UUID} like a {@code System.Guid} serialized by {@code MemoryMarshal.Write}. + * + * @param uuid a {@link UUID} to be encoded. + * @param out an output {@link ByteBuf}. + */ + public static void encode(final UUID uuid, final ByteBuf out) { + + final long mostSignificantBits = uuid.getMostSignificantBits(); + + out.writeIntLE((int) ((mostSignificantBits & 0xFFFFFFFF00000000L) >>> 32)); + out.writeShortLE((short) ((mostSignificantBits & 0x00000000FFFF0000L) >>> 16)); + out.writeShortLE((short) (mostSignificantBits & 0x000000000000FFFFL)); + + out.writeLong(uuid.getLeastSignificantBits()); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/internal/Murmur3Hash.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/internal/Murmur3Hash.java new file mode 100644 index 0000000..6805335 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/internal/Murmur3Hash.java @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.internal; + +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.HashCode128; +import com.google.common.base.Utf8; +import com.google.common.hash.HashCode; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hashing; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.Immutable; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.lenientFormat; +import static java.nio.charset.StandardCharsets.UTF_8; + +/** + * Murmur3Hash for x86_64 (little endian). + * + * @see MurmurHash + *

+ */ +@SuppressWarnings("UnstableApiUsage") +@Immutable +public final class Murmur3Hash { + + private static final ByteBuf FALSE = Constant.add(false); + private static final ByteBuf TRUE = Constant.add(true); + private static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + private static final ByteBuf EMPTY_STRING = Constant.add(""); + + /** + * Computes a 128-bit Murmur3Hash 128-bit value for a data item. + * + * @param item The data to hash + * @param seed The seed with which to initialize + * @return The 128-bit hash represented as two 64-bit words encapsulated by a {@link HashCode128} instance + */ + @SuppressWarnings("ConstantConditions") + public static HashCode128 Hash128(@Nonnull final String item, @Nonnull final HashCode128 seed) { + + checkNotNull(item, "expected non-null item"); + checkNotNull(seed, "expected non-null seed"); + + if (item.isEmpty()) { + return Hash128(EMPTY_STRING, seed); + } + + Utf8String value = Utf8String.transcodeUtf16(item); + + try { + return Hash128(value.content(), seed); + } finally { + value.release(); + } + } + + /** + * Computes a 128-bit Murmur3Hash 128-bit value for a {@code boolean} data item. + * + * @param item The data to hash. + * @param seed The seed with which to initialize. + * @return The 128-bit hash represented as two 64-bit words encapsulated by a {@link HashCode128} instance. + */ + public static HashCode128 Hash128(final boolean item, final HashCode128 seed) { + return Murmur3Hash.Hash128(item ? TRUE : FALSE, seed); + } + + public static HashCode128 Hash128(short item, HashCode128 seed) { + ByteBuf buffer = Unpooled.wrappedBuffer(new byte[Integer.BYTES]).writeShortLE(item); + return Murmur3Hash.Hash128(buffer, seed); + } + + public static HashCode128 Hash128(byte item, HashCode128 seed) { + ByteBuf buffer = Unpooled.wrappedBuffer(new byte[Integer.BYTES]).writeByte(item); + return Murmur3Hash.Hash128(buffer, seed); + } + + public static HashCode128 Hash128(int item, HashCode128 seed) { + ByteBuf buffer = Unpooled.wrappedBuffer(new byte[Integer.BYTES]).writeIntLE(item); + return Murmur3Hash.Hash128(buffer, seed); + } + + /** + * Computes a 128-bit Murmur3Hash 128-bit value for a {@link ByteBuf} data item. + * + * @param item The data to hash + * @param seed The seed with which to initialize + * @return The 128-bit hash represented as two 64-bit words encapsulated by a {@link HashCode128} instance. + */ + public static HashCode128 Hash128(ByteBuf item, HashCode128 seed) { + // TODO: DANOBLE: Support 128-bit hash code seeds by bringing in the murmur3 hash code from the Cosmos Java SDK + HashFunction hashFunction = Hashing.murmur3_128(Long.valueOf(seed.high() | 0xFFFFFFFFL).intValue()); + HashCode hashCode = hashFunction.hashBytes(item.array()); + return HashCode128.from(hashCode.asBytes()); + } + + private static final class Constant { + + private static ByteBuf constants = allocator.heapBuffer(); + + private Constant() { + } + + static ByteBuf add(final boolean value) { + final int start = constants.writerIndex(); + constants.writeByte(value ? 1 : 0); + return constants.slice(start, Byte.BYTES).asReadOnly(); + } + + static ByteBuf add(final String value) { + + final int start = constants.writerIndex(); + final int encodedLength = Utf8.encodedLength(value); + final ByteBuf buffer = allocator.buffer(encodedLength, encodedLength); + + final int count = buffer.writeCharSequence(value, UTF_8); + assert count == encodedLength : lenientFormat("count: %s, encodedLength: %s"); + + return constants.slice(start, encodedLength); + } + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/DataItem.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/DataItem.java new file mode 100644 index 0000000..0a9eb50 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/DataItem.java @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; + +import javax.annotation.Nonnull; +import java.util.Collection; +import java.util.List; +import java.util.function.Supplier; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A path/type/value triplet representing a field in a HybridRow. + */ +public class DataItem { + + @JsonProperty + private final List nodes; + + @JsonProperty + private final LayoutCode type; + + @JsonProperty + private final Object value; + + private final Supplier name; + private final Supplier path; + + @SuppressWarnings("UnstableApiUsage") + DataItem( + @Nonnull final Collection nodes, + @Nonnull final Utf8String name, + @Nonnull final LayoutCode type, + @Nonnull final Object value) { + + checkNotNull(nodes, "expected non-null nodes"); + checkNotNull(name, "expected non-null name"); + checkNotNull(type, "expected non-null type"); + checkNotNull(value, "expected non-null value"); + + //noinspection ConstantConditions + this.nodes = ImmutableList.builderWithExpectedSize(nodes.size() + 1) + .addAll(nodes.stream().map(Utf8String::toUtf16).iterator()) + .add(name.toUtf16()) + .build(); + + this.type = type; + this.value = value; + + this.name = Suppliers.memoize(() -> this.nodes.get(this.nodes.size() - 1)); + + this.path = Suppliers.memoize(() -> { + + if (this.nodes.size() == 1) { + return this.nodes.get(0); + } + + StringBuilder builder = new StringBuilder(this.nodes.stream() + .map(String::length) + .reduce(this.nodes.size() - 1, Integer::sum) + ); + + int i; + + for (i = 0; i < this.nodes.size() - 1; ++i) { + builder.append(this.nodes.get(i)); + if (this.nodes.get(i + 1).charAt(0) != '[') { + builder.append('.'); + } + } + + return builder.append(this.nodes.get(i)).toString(); + }); + } + + public String name() { + return this.name.get(); + } + + public List nodes() { + return this.nodes; + } + + public String path() { + return this.path.get(); + } + + @Override + public String toString() { + return Json.toString(this); + } + + public LayoutCode type() { + return this.type; + } + + public Object value() { + return this.value; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java new file mode 100644 index 0000000..75d85b3 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReader.java @@ -0,0 +1,1274 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBinary; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutBoolean; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutDecimal; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat128; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutFloat64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutGuid; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt16; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutInt8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutListReadable; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutNull; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutNullable; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypePrimitive; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUDT; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt16; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt32; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt64; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUInt8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUtf8; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutVarInt; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutVarUInt; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; +import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import io.netty.buffer.ByteBuf; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.IOException; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.UUID; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.lenientFormat; + +/** + * A forward-only, streaming, field reader for {@link RowBuffer}. + *

+ * A {@link RowReader} allows the traversal in a streaming, left to right fashion, of an entire HybridRow. The row's + * layout provides decoding for any schematized portion of the row. However, unschematized sparse fields are read + * directly from the sparse segment with or without schematization allowing all fields within the row, both known and + * unknown, to be read. + *

+ * Modifying a {@link RowBuffer} invalidates any reader or child reader associated with it. In general{@link RowBuffer}s + * should not be mutated while being enumerated. + */ +@JsonSerialize(using = RowReader.JsonSerializer.class) +public final class RowReader { + + private int columnIndex; + private List columns; + private RowCursor cursor; + private RowBuffer buffer; + private int schematizedCount; + private States state; + + /** + * Initializes a new instance of the {@link RowReader} class. + * + * @param buffer The row to be read + */ + public RowReader(@Nonnull RowBuffer buffer) { + this(buffer, RowCursor.create(buffer)); + } + + /** + * Initializes a new instance of the {@link RowReader} class. + * + * @param buffer The buffer to be read + * @param checkpoint Initial state of the reader + */ + public RowReader(@Nonnull final RowBuffer buffer, @Nonnull final Checkpoint checkpoint) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(checkpoint, "expected non-null checkpoint"); + + this.buffer = buffer; + this.columns = checkpoint.cursor().layout().columns(); + this.schematizedCount = checkpoint.cursor().layout().numFixed() + checkpoint.cursor().layout().numVariable(); + + this.state = checkpoint.state(); + this.cursor = checkpoint.cursor(); + this.columnIndex = checkpoint.columnIndex(); + } + + /** + * Initializes a new instance of the {@link RowReader} class. + * + * @param buffer The buffer to be read. + * @param scope Cursor defining the scope of the fields to be read. + *

+ * A {@link RowReader} instance traverses all of the top-level fields of a given scope. If the root + * scope is provided then all top-level fields in the buffer are enumerated. Nested child + * {@link RowReader} instances can be access through the {@link RowReader#readScope} method to process + * nested content. + */ + private RowReader(@Nonnull final RowBuffer buffer, @Nonnull final RowCursor scope) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + + this.cursor = scope; + this.buffer = buffer; + this.columns = this.cursor.layout().columns(); + this.schematizedCount = this.cursor.layout().numFixed() + this.cursor.layout().numVariable(); + + this.state = States.NONE; + this.columnIndex = -1; + } + + /** + * Read the current field as a fixed length {@code MongoDbObjectId} value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result ReadMongoDbObjectId(Out value) { + // TODO: DANOBLE: Resurrect this method + // switch (this.state) { + // + // case Schematized: + // return this.readPrimitiveValue(value); + // + // case Sparse: + // if (!(this.cursor.cellType() instanceof LayoutMongoDbObjectId)) { + // value.set(null); + // return Result.TYPE_MISMATCH; + // } + // value.set(this.row.readSparseMongoDbObjectId(this.cursor)); + // return Result.SUCCESS; + // + // default: + // value.set(null); + // return Result.FAILURE; + // } + throw new UnsupportedOperationException(); + } + + public boolean isDone() { + return this.state == States.DONE; + } + + /** + * {@code true} if field has a value--if positioned on a field--undefined otherwise. + *

+ * If the current field is a Nullable scope, this method return true if the value is not null. If the current field + * is a nullable Null primitive value, this method return true if the value is set (even though its values is set + * to null). + * + * @return {@code true} if field has a value, {@code false} otherwise. + */ + public boolean hasValue() { + + switch (this.state) { + + case SCHEMATIZED: + return true; + + case SPARSE: + if (this.cursor.cellType() instanceof LayoutNullable) { + RowCursor nullableScope = this.buffer.sparseIteratorReadScope(this.cursor, true); + return LayoutNullable.hasValue(this.buffer, nullableScope) == Result.SUCCESS; + } + return true; + + default: + return false; + } + } + + /** + * Zero-based index, relative to the scope, of the field--if positioned on a field--undefined otherwise. + *

+ * When enumerating a non-indexed scope, this value is always zero. + * + * @return zero-based index of the field relative to the scope, if positioned on a field; otherwise undefined. + * @see #path() + */ + public int index() { + return this.state == States.SPARSE ? this.cursor.index() : 0; + } + + /** + * The length of row in bytes. + * + * @return length of the current row in bytes. + */ + public int length() { + return this.buffer.length(); + } + + /** + * The path, relative to the scope, of the field--if positioned on a field--undefined otherwise. + *

+ * When enumerating an indexed scope, this value is always null. + * + * @return path of the field relative to the scope, if positioned on a field; otherwise undefined. + * @see #index + */ + @Nonnull + public Utf8String path() { + switch (this.state) { + case SCHEMATIZED: + return this.columns.get(this.columnIndex).path(); + case SPARSE: + return this.buffer.readSparsePath(this.cursor); + default: + return Utf8String.NULL; + } + } + + /** + * Advances the reader to the next field. + * + * @return {@code true}, if there is another field to be read; {@code false} otherwise. + */ + public boolean read() { + + while (this.state != States.DONE) { + + switch (this.state) { + + case NONE: { + this.state = this.cursor.scopeType() instanceof LayoutUDT ? States.SCHEMATIZED : States.SPARSE; + break; + } + case SCHEMATIZED: { + + this.columnIndex++; + + if (this.columnIndex >= this.schematizedCount) { + this.state = States.SPARSE; + break; + } + + checkState(this.cursor.scopeType() instanceof LayoutUDT); + LayoutColumn column = this.columns.get(this.columnIndex); + + if (!this.buffer.readBit(this.cursor.start(), column.nullBit())) { + break; // to skip schematized values if they aren't present + } + + return true; + } + case SPARSE: { + + if (!RowCursors.moveNext(this.cursor, this.buffer)) { + this.state = States.DONE; + break; + } + return true; + } + } + } + + return false; + } + + /** + * Read the current field as a variable length, sequence of bytes. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readBinary(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + + if (!(this.cursor.cellType() instanceof LayoutBinary)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + + value.set(this.buffer.readSparseBinary(this.cursor)); + return Result.SUCCESS; + + default: + value.set(null); + return Result.FAILURE; + } + } + + /** + * Read the current field as a variable length, sequence of bytes. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readBinaryArray(Out value) { + + Out buffer = new Out<>(); + Result result = this.readBinary(buffer); + + if (result == Result.SUCCESS) { + byte[] array = new byte[buffer.get().writerIndex()]; + buffer.get().getBytes(0, array); + value.set(array); + } + + return result; + } + + /** + * Read the current field as a {@link Boolean}. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readBoolean(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutBoolean)) { + value.set(false); + return Result.TYPE_MISMATCH; + } + + value.set(this.buffer.readSparseBoolean(this.cursor)); + return Result.SUCCESS; + + default: + value.set(false); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length {@code DateTime} value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readDateTime(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutDateTime)) { + value.set(OffsetDateTime.MIN); + return Result.TYPE_MISMATCH; + } + + value.set(this.buffer.readSparseDateTime(this.cursor)); + return Result.SUCCESS; + + default: + value.set(OffsetDateTime.MIN); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length decimal value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readDecimal(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutDecimal)) { + value.set(new BigDecimal(0)); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseDecimal(this.cursor)); + return Result.SUCCESS; + + default: + value.set(new BigDecimal(0)); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 128-bit, IEEE-encoded floating point value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readFloat128(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutFloat128)) { + value.setAndGet(null); + return Result.TYPE_MISMATCH; + } + value.setAndGet(this.buffer.readSparseFloat128(this.cursor)); + return Result.SUCCESS; + + default: + value.setAndGet(null); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 32-bit, IEEE-encoded floating point value + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readFloat32(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutFloat32)) { + value.set(0F); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseFloat32(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0F); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 64-bit, IEEE-encoded floating point value + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readFloat64(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutFloat64)) { + value.set(0D); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseFloat64(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0D); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length GUID value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readGuid(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutGuid)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + + value.set(this.buffer.readSparseGuid(this.cursor)); + return Result.SUCCESS; + + default: + value.set(null); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 16-bit, signed integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readInt16(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutInt16)) { + value.set((short)0); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseInt16(this.cursor)); + return Result.SUCCESS; + + default: + value.set((short)0); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 32-bit, signed integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readInt32(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutInt32)) { + value.set(0); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseInt32(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 64-bit, signed integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readInt64(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutInt64)) { + value.setAndGet(0L); + return Result.TYPE_MISMATCH; + } + value.setAndGet(this.buffer.readSparseInt64(this.cursor)); + return Result.SUCCESS; + + default: + value.setAndGet(0L); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 8-bit, signed integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readInt8(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutInt8)) { + value.set((byte)0); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseInt8(this.cursor)); + return Result.SUCCESS; + + default: + value.set((byte)0); + return Result.FAILURE; + } + } + + /** + * Read the current field as a null. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readNull(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutNull)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseNull(this.cursor)); + return Result.SUCCESS; + + default: + value.set(null); + return Result.FAILURE; + } + } + + /** + * Read the current field as a nested, structured, sparse scope. + *

+ * Child readers can be used to read all sparse scope types including typed and untyped objects, arrays, tuples, + * set, and maps. + * + * @param a reader context type. + * @param context a reader context. + * @param func a reader function. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + @Nonnull + public Result readScope(@Nullable final TContext context, @Nullable final ReaderFunc func) { + + final RowCursor childScope = this.buffer.sparseIteratorReadScope(this.cursor, true); + final RowReader nestedReader = new RowReader(this.buffer, childScope); + final Result result = func == null ? null : func.invoke(nestedReader, context); + + if (!(result == null || result == Result.SUCCESS)) { + return result; + } + + RowCursors.skip(this.cursor, this.buffer, nestedReader.cursor); + return Result.SUCCESS; + } + + /** + * Read the current field as a nested, structured, sparse scope. + *

+ * Child readers can be used to read all sparse scope types including typed and untyped objects, arrays, tuples, + * set, and maps. Nested child readers are independent of their parent. + * + * @return a new {@link RowReader}. + */ + public @Nonnull RowReader readScope() { + RowCursor scope = this.buffer.sparseIteratorReadScope(this.cursor, true); + return new RowReader(this.buffer, scope); + } + + /** + * Read the current field as a variable length, UTF-8 encoded string value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readString(Out value) { + + Out string = new Out<>(); + Result result = this.readUtf8String(string); + value.set((result == Result.SUCCESS) ? string.get().toUtf16() : null); + string.get().release(); + + return result; + } + + /** + * Read the current field as a variable length, UTF-8 encoded, string value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readUtf8String(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutUtf8)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseString(this.cursor)); + return Result.SUCCESS; + + default: + value.set(null); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 16-bit, unsigned integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readUInt16(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutUInt16)) { + value.set(0); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseUInt16(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 32-bit, unsigned integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readUInt32(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutUInt32)) { + value.set(0L); + return Result.TYPE_MISMATCH; + } + + value.set(this.buffer.readSparseUInt32(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0L); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 64-bit, unsigned integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readUInt64(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutUInt64)) { + value.set(0L); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseUInt64(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0L); + return Result.FAILURE; + } + } + + /** + * Read the current field as a fixed length, 8-bit, unsigned integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + @Nonnull + public Result readUInt8(@Nonnull Out value) { + + checkNotNull(value, "expected non-null value"); + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutUInt8)) { + value.set((short)0); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseUInt8(this.cursor)); + return Result.SUCCESS; + + default: + value.set((short)0); + return Result.FAILURE; + } + } + + /** + * Returns a string representation of the object. In general, the + * {@code toString} method returns a string that + * "textually represents" this object. The result should + * be a concise but informative representation that is easy for a + * person to read. + * It is recommended that all subclasses override this method. + *

+ * The {@code toString} method for class {@code Object} + * returns a string consisting of the name of the class of which the + * object is an instance, the at-sign character `{@code @}', and + * the unsigned hexadecimal representation of the hash code of the + * object. In other words, this method returns a string equal to the + * value of: + *

+ *
+     * getClass().getName() + '@' + Integer.toHexString(hashCode())
+     * 
+ * + * @return a string representation of the object. + */ + @Override + public String toString() { + return Json.toString(this); + } + + /** + * Read the current field as a fixed length {@link UnixDateTime} value. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readUnixDateTime(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutUnixDateTime)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseUnixDateTime(this.cursor)); + return Result.SUCCESS; + + default: + value.set(null); + return Result.FAILURE; + } + } + + /** + * Read the current field as a variable length, 7-bit encoded, signed integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readVarInt(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutVarInt)) { + value.set(0L); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseVarInt(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0L); + return Result.FAILURE; + } + } + + /** + * Read the current field as a variable length, 7-bit encoded, unsigned integer. + * + * @param value On success, receives the value, undefined otherwise. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result readVarUInt(Out value) { + + switch (this.state) { + + case SCHEMATIZED: + return this.readPrimitiveValue(value); + + case SPARSE: + if (!(this.cursor.cellType() instanceof LayoutVarUInt)) { + value.set(0L); + return Result.TYPE_MISMATCH; + } + value.set(this.buffer.readSparseVarUInt(this.cursor)); + return Result.SUCCESS; + + default: + value.set(0L); + return Result.FAILURE; + } + } + + public Checkpoint saveCheckpoint() { + return new Checkpoint(this.state, this.columnIndex, this.cursor); + } + + /** + * Advance a reader to the end of a child reader. + *

+ * The child reader is also advanced to the end of its scope. The reader must not have been advanced since the child + * reader was created with {@link #readScope}. This method can be used when the overload of {@link #readScope} that + * takes a {@link ReaderFunc} is not an option. + * + * @param nestedReader nested (child) reader to be advanced. + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + public Result skipScope(@Nonnull final RowReader nestedReader) { + if (nestedReader.cursor.start() != this.cursor.valueOffset()) { + return Result.FAILURE; + } + RowCursors.skip(this.cursor, this.buffer, nestedReader.cursor); + return Result.SUCCESS; + } + + /** + * The storage placement of the field--if positioned on a field--undefined otherwise. + * + * @return storage kind. + */ + public StorageKind storage() { + switch (this.state) { + case SCHEMATIZED: + return this.columns.get(this.columnIndex).storage(); + case SPARSE: + return StorageKind.SPARSE; + default: + return null; + } + } + + /** + * The type of the field--if positioned on a field--undefined otherwise. + * + * @return layout type or {@code null}. + */ + @Nullable + public LayoutType type() { + + switch (this.state) { + case SCHEMATIZED: + return this.columns.get(this.columnIndex).type(); + case SPARSE: + return this.cursor.cellType(); + default: + return null; + } + } + + /** + * The type arguments of the field, if positioned on a field, undefined otherwise. + * + * @return type argument list. + */ + public TypeArgumentList typeArgs() { + + switch (this.state) { + case SCHEMATIZED: + return this.columns.get(this.columnIndex).typeArgs(); + case SPARSE: + return this.cursor.cellTypeArgs(); + default: + return TypeArgumentList.EMPTY; + } + } + + /** + * Reads a generic schematized field value via the scope's layout + * + * @param value On success, receives the value, undefined otherwise + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + @Nonnull + private Result readPrimitiveValue(@Nonnull Out value) { + + final LayoutColumn column = this.columns.get(this.columnIndex); + final LayoutType type = this.columns.get(this.columnIndex).type(); + + if (!(type instanceof LayoutTypePrimitive)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + + final StorageKind storage = column == null ? StorageKind.NONE : column.storage(); + + switch (storage) { + case FIXED: + return type.>typeAs().readFixed(this.buffer, this.cursor, column, value); + case VARIABLE: + return type.>typeAs().readVariable(this.buffer, this.cursor, column, value); + default: + String message = lenientFormat("expected FIXED or VARIABLE column storage, not %s", storage); + throw new IllegalStateException(message); + } + } + +// /** +// * Reads a generic schematized field value via the scope's layout +// * +// * @param value On success, receives the value, undefined otherwise +// * @return {@link Result#SUCCESS} if the read is successful; an error {@link Result} otherwise +// */ +// private Result readPrimitiveValue(Out value) { +// +// LayoutColumn column = this.columns.get(this.columnIndex); +// LayoutType type = this.columns.get(this.columnIndex).type(); +// +// if (!(type instanceof LayoutUtf8Readable)) { +// value.set(null); +// return Result.TYPE_MISMATCH; +// } +// +// StorageKind storage = column == null ? StorageKind.NONE : column.storage(); +// +// switch (storage) { +// +// case FIXED: +// return type.typeAs().readFixed(this.row, this.cursor, column, value); +// +// case VARIABLE: +// return type.typeAs().readVariable(this.row, this.cursor, column, value); +// +// default: +// assert false : lenientFormat("expected FIXED or VARIABLE column storage, not %s", storage); +// value.set(null); +// return Result.FAILURE; +// } +// } +// + /** + * Reads a generic schematized field value via the scope's layout + * + * @param The sub-element type of the field + * @param value On success, receives the value, undefined otherwise + * @return {@link Result#SUCCESS} if the read is successful, an error {@link Result} otherwise. + */ + private Result readPrimitiveValueList(Out> value) { + + LayoutColumn column = this.columns.get(this.columnIndex); + LayoutType type = this.columns.get(this.columnIndex).type(); + + if (!(type instanceof LayoutListReadable)) { + value.set(null); + return Result.TYPE_MISMATCH; + } + + StorageKind storage = column == null ? StorageKind.NONE : column.storage(); + + switch (storage) { + + case FIXED: + return type.>typeAs().readFixedList(this.buffer, this.cursor, column, value); + + case VARIABLE: + return type.>typeAs().readVariableList(this.buffer, this.cursor, column, value); + + default: + assert false : lenientFormat("expected FIXED or VARIABLE column storage, not %s", storage); + value.set(null); + return Result.FAILURE; + } + } + + /** + * The current traversal state of the reader. + */ + public enum States { + /** + * The reader has not be started yet. + */ + NONE, + + /** + * Enumerating schematized fields (fixed and variable) from left to right. + */ + SCHEMATIZED, + + /** + * Enumerating top-level fields of the current scope. + */ + SPARSE, + + /** + * The reader has completed the scope. + */ + DONE; + + public static final int BYTES = Byte.BYTES; + private final String friendlyName; + + States() { + this.friendlyName = this.name().toLowerCase(); + } + + public String friendlyName() { + return this.friendlyName; + } + + public static States from(byte value) { + return values()[value]; + } + + /** + * Returns the friendly name of this enum constant, as returned by {@link #friendlyName()}. + * + * @return the friendly name of this enum constant + */ + @Override + public String toString() { + return this.friendlyName; + } + + public byte value() { + return (byte) this.ordinal(); + } + } + + /** + * A functional interface for reading content from a {@link RowBuffer} + * + * @param The type of the context value passed by the caller + */ + @FunctionalInterface + public interface ReaderFunc { + /** + * The read {@link Result} + * + * @param reader the current reader + * @param context the current reader context + * @return the read result + */ + Result invoke(RowReader reader, TContext context); + } + + /** + * An encapsulation of the current state of a {@link RowReader} + *

+ * This value can be used to recreate the {@link RowReader} in the same logical position. + */ + public final static class Checkpoint { + + private int columnIndex; + private RowCursor cursor; + private States state; + + public Checkpoint(States state, int columnIndex, RowCursor cursor) { + this.state(state); + this.columnIndex(columnIndex); + this.cursor(cursor); + } + + public int columnIndex() { + return this.columnIndex; + } + + public Checkpoint columnIndex(int columnIndex) { + this.columnIndex = columnIndex; + return this; + } + + public RowCursor cursor() { + return this.cursor; + } + + public Checkpoint cursor(RowCursor cursor) { + this.cursor = cursor; + return this; + } + + public States state() { + return this.state; + } + + public Checkpoint state(States state) { + this.state = state; + return this; + } + } + + static final class JsonSerializer extends StdSerializer { + + JsonSerializer() { + super(RowReader.class); + } + + @Override + public void serialize(RowReader value, JsonGenerator generator, SerializerProvider provider) throws IOException { + generator.writeStartObject(); + generator.writeStringField("path", value.path().toUtf16()); + generator.writeStringField("state", value.state == null ? null : value.state.friendlyName); + generator.writeObjectFieldStart("span"); + generator.writeNumberField("start", value.cursor.start()); + generator.writeNumberField("end", value.cursor.endOffset()); + generator.writeEndObject(); + LayoutColumn column = value.columns.get(value.columnIndex); + generator.writeObjectFieldStart("column"); + generator.writeStringField("fullPath", column.fullPath().toUtf16()); + generator.writeStringField("type", column.type().name()); + generator.writeNumberField("index", column.index()); + generator.writeNumberField("offset", column.offset()); + generator.writeEndObject(); + generator.writeEndObject(); + } + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderExtensions.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderExtensions.java new file mode 100644 index 0000000..395fe76 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderExtensions.java @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; + +public final class RowReaderExtensions { + /** + * Read the current field as a nested, structured, sparse scope containing a linear collection of zero or more + * items. + * @param The type of the items within the collection. + * + * @param reader A forward-only cursor for reading the collection. + * @param deserializer A function that reads one item from the collection. + * @param list On success, the collection of materialized items. + * @return The result. + */ + @Nonnull + public static Result readList(RowReader reader, DeserializerFunc deserializer, Out> list) { + + // Pass the context as a struct by value to avoid allocations + + final ListContext context = new ListContext(deserializer, new ArrayList()); + final Out item = new Out<>(); + + Result result = reader.readScope(context, (arrayReader, arrayContext) -> { + while (arrayReader.read()) { + Result arrayResult = arrayReader.readScope(arrayContext, (itemReader, itemContext) -> { + Result itemResult = itemContext.deserializer().invoke(itemReader, item); + if (itemResult != Result.SUCCESS) { + return itemResult; + } + itemContext.items().add(item.get()); + return Result.SUCCESS; + }); + if (arrayResult != Result.SUCCESS) { + return arrayResult; + } + } + return Result.SUCCESS; + }); + + if (result != Result.SUCCESS) { + list.set(null); + return result; + } + + list.set(context.items()); + return Result.SUCCESS; + } + + /** + * A functional interface to read content from a {@link RowReader} + * + * @param The type of item to read + * + */ + @FunctionalInterface + public interface DeserializerFunc { + /** + * Read a row from a {@link RowReader} + * + * @param reader A forward-only cursor for reading the item + * @param item On success, the item read + * @return The result + */ + @Nonnull + Result invoke(@Nonnull RowReader reader, @Nonnull Out item); + } + + private final static class ListContext { + + private final DeserializerFunc deserializer; + private final List items; + + ListContext(DeserializerFunc deserializer, List items) { + this.deserializer = deserializer; + this.items = items; + } + + public DeserializerFunc deserializer() { + return this.deserializer; + } + + public List items() { + return this.items; + } + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowScanner.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowScanner.java new file mode 100644 index 0000000..5d72d99 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowScanner.java @@ -0,0 +1,545 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolverNamespace; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BiFunction; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.lenientFormat; +import static java.util.Objects.requireNonNull; + +public class RowScanner implements AutoCloseable, Iterable { + + private final AtomicBoolean closed; + private final ByteBuf data; + private final LayoutResolver resolver; + + private RowScanner(LayoutResolver resolver, ByteBuf data) { + this.closed = new AtomicBoolean(); + this.data = data.retain(); + this.resolver = resolver; + } + + @Override + public void close() { + if (this.closed.compareAndSet(false, true)) { + this.data.release(); + } + } + + @Override + @Nonnull + public Iterator iterator() { + + checkState(!this.closed.get(), "RowScanner is closed"); + + final RowBuffer buffer = new RowBuffer(this.data, HybridRowVersion.V1, this.resolver); + final RowReader reader = new RowReader(buffer); + + return new DataItemIterator(reader); + } + + public static RowScanner open(@Nonnull Namespace namespace, @Nonnull File file) throws IOException { + + checkNotNull(file, "expected non-null file"); + + final long length = file.length(); + checkArgument(0 < length, "file does not exist: %s", file); + checkArgument(length <= Integer.MAX_VALUE, "expected file length <= %s, not %s", Integer.MAX_VALUE, length); + + ByteBuf data = Unpooled.buffer((int) length); + + try (InputStream stream = Files.newInputStream(file.toPath())) { + data.writeBytes(stream, (int) length); + } + + LayoutResolverNamespace resolver = new LayoutResolverNamespace(namespace); + return new RowScanner(resolver, data); + } + + public static RowScanner open(@Nonnull Namespace namespace, @Nonnull Path path) throws IOException { + return RowScanner.open(namespace, requireNonNull(path, "expected non-null path").toFile()); + } + + public static RowScanner open(@Nonnull Namespace namespace, @Nonnull String path) throws IOException { + return RowScanner.open(namespace, new File(requireNonNull(path, "expected non-null path"))); + } + + public Result visit(BiFunction accept, TContext context) { + + checkState(!this.closed.get(), "RowScanner is closed"); + + final RowBuffer buffer = new RowBuffer(this.data, HybridRowVersion.V1, this.resolver); + final RowReader reader = new RowReader(buffer); + + return visit(reader, new DataItemVisitor<>(accept, context)); + } + + @SuppressWarnings("unchecked") + private static Result visit(RowReader reader, DataItemVisitor visitor) { + + final Out value = new Out(); + + while (reader.read()) { + + Utf8String path = reader.path(); + checkState(!path.isNull(), "expected non-null value for path"); + + LayoutType type = reader.type(); + checkState(type != null, "expected non-null type"); + + final Result result; + value.set(null); + + switch (type.layoutCode()) { + + case NULL: { + result = reader.readNull(value); + break; + } + case BOOLEAN: { + result = reader.readBoolean(value); + break; + } + case INT_8: { + result = reader.readInt8(value); + break; + } + case INT_16: { + result = reader.readInt16(value); + break; + } + case INT_32: { + result = reader.readInt32(value); + break; + } + case INT_64: { + result = reader.readInt64(value); + break; + } + case VAR_INT: { + result = reader.readVarInt(value); + break; + } + case UINT_8: { + result = reader.readUInt8(value); + break; + } + case UINT_16: { + result = reader.readUInt16(value); + break; + } + case UINT_32: { + result = reader.readUInt32(value); + break; + } + case UINT_64: { + result = reader.readUInt64(value); + break; + } + case VAR_UINT: { + result = reader.readVarUInt(value); + break; + } + case FLOAT_32: { + result = reader.readFloat32(value); + break; + } + case FLOAT_64: { + result = reader.readFloat64(value); + break; + } + case FLOAT_128: { + result = reader.readFloat128(value); + break; + } + case DECIMAL: { + result = reader.readDecimal(value); + break; + } + case GUID: { + result = reader.readGuid(value); + break; + } + case DATE_TIME: { + result = reader.readDateTime(value); + break; + } + case UNIX_DATE_TIME: { + result = reader.readUnixDateTime(value); + break; + } + case BINARY: { + result = reader.readBinary(value); + break; + } + case UTF_8: { + result = reader.readUtf8String(value); + break; + } + case NULLABLE_SCOPE: + case IMMUTABLE_NULLABLE_SCOPE: { + if (!reader.hasValue()) { + result = Result.SUCCESS; + break; + } + } + case ARRAY_SCOPE: + case IMMUTABLE_ARRAY_SCOPE: + + case MAP_SCOPE: + case IMMUTABLE_MAP_SCOPE: + + case OBJECT_SCOPE: + case IMMUTABLE_OBJECT_SCOPE: + + case SCHEMA: + case IMMUTABLE_SCHEMA: + + case SET_SCOPE: + case IMMUTABLE_SET_SCOPE: + + case TAGGED2_SCOPE: + case IMMUTABLE_TAGGED2_SCOPE: + + case TAGGED_SCOPE: + case IMMUTABLE_TAGGED_SCOPE: + + case TUPLE_SCOPE: + case IMMUTABLE_TUPLE_SCOPE: + + case TYPED_ARRAY_SCOPE: + case IMMUTABLE_TYPED_ARRAY_SCOPE: + + case TYPED_MAP_SCOPE: + case IMMUTABLE_TYPED_MAP_SCOPE: + + case TYPED_SET_SCOPE: + case IMMUTABLE_TYPED_SET_SCOPE: + + case TYPED_TUPLE_SCOPE: + case IMMUTABLE_TYPED_TUPLE_SCOPE: { + + visitor.nodes().push(path.isEmpty() + ? Utf8String.transcodeUtf16(lenientFormat("[%s]", reader.index())) + : path); + + result = reader.readScope(visitor, RowScanner::visit); + visitor.nodes().pop(); + + if (result != Result.SUCCESS) { + return result; + } + + continue; + } + case MONGODB_OBJECT_ID: { + throw new IllegalStateException(lenientFormat("unsupported layout type: %s", type)); + } + case BOOLEAN_FALSE: + case END_SCOPE: + case INVALID: { + throw new IllegalStateException(lenientFormat("unexpected layout type: %s", type)); + } + default: { + throw new IllegalStateException(lenientFormat("unknown layout type: %s", type)); + } + } + + if (result != Result.SUCCESS) { + return result; + } + + DataItem item = new DataItem(visitor.nodes(), path, type.layoutCode(), value.get()); + visitor.accept().apply(item, visitor.context()); + } + + return Result.SUCCESS; + } + + private static class DataItemIterator implements Iterator { + + final Deque nodes; + final Deque readers; + final Out value; + + DataItem dataItem; + RowReader reader; + + DataItemIterator(RowReader reader) { + this.readers = new ArrayDeque<>(); + this.nodes = new ArrayDeque<>(); + this.value = new Out(); + this.reader = reader; + } + + @Override + public boolean hasNext() { + + while (this.dataItem == null) { + if (this.reader == null) { + return false; + } + this.advance(); + } + return true; + } + + /** + * Returns the next element in the iteration. + * + * @return the next element in the iteration + * @throws NoSuchElementException if the iteration has no more elements + */ + @Override + public DataItem next() { + + while (this.dataItem == null) { + if (this.reader == null) { + throw new NoSuchElementException(); + } + this.advance(); + } + + DataItem dataItem = this.dataItem; + this.dataItem = null; + + return dataItem; + } + + @SuppressWarnings("unchecked") + private void advance() { + + do { + while (this.reader.read()) { + + final Result result; + + Utf8String path = this.reader.path(); + checkState(!path.isNull(), "expected non-null value for path"); + + LayoutType type = this.reader.type(); + checkState(type != null, "expected non-null type"); + + switch (type.layoutCode()) { + + case NULL: { + result = this.reader.readNull(this.value); + break; + } + case BOOLEAN: { + result = this.reader.readBoolean(this.value); + break; + } + case INT_8: { + result = this.reader.readInt8(this.value); + break; + } + case INT_16: { + result = this.reader.readInt16(this.value); + break; + } + case INT_32: { + result = this.reader.readInt32(this.value); + break; + } + case INT_64: { + result = this.reader.readInt64(this.value); + break; + } + case VAR_INT: { + result = this.reader.readVarInt(this.value); + break; + } + case UINT_8: { + result = this.reader.readUInt8(this.value); + break; + } + case UINT_16: { + result = this.reader.readUInt16(this.value); + break; + } + case UINT_32: { + result = this.reader.readUInt32(this.value); + break; + } + case UINT_64: { + result = this.reader.readUInt64(this.value); + break; + } + case VAR_UINT: { + result = this.reader.readVarUInt(this.value); + break; + } + case FLOAT_32: { + result = this.reader.readFloat32(this.value); + break; + } + case FLOAT_64: { + result = this.reader.readFloat64(this.value); + break; + } + case FLOAT_128: { + result = this.reader.readFloat128(this.value); + break; + } + case DECIMAL: { + result = this.reader.readDecimal(this.value); + break; + } + case GUID: { + result = this.reader.readGuid(this.value); + break; + } + case DATE_TIME: { + result = this.reader.readDateTime(this.value); + break; + } + case UNIX_DATE_TIME: { + result = this.reader.readUnixDateTime(this.value); + break; + } + case BINARY: { + result = this.reader.readBinary(this.value); + break; + } + case UTF_8: { + result = this.reader.readUtf8String(this.value); + break; + } + case NULLABLE_SCOPE: + case IMMUTABLE_NULLABLE_SCOPE: { + if (!this.reader.hasValue()) { + result = Result.SUCCESS; + break; + } + } + case ARRAY_SCOPE: + case IMMUTABLE_ARRAY_SCOPE: + + case MAP_SCOPE: + case IMMUTABLE_MAP_SCOPE: + + case OBJECT_SCOPE: + case IMMUTABLE_OBJECT_SCOPE: + + case SCHEMA: + case IMMUTABLE_SCHEMA: + + case SET_SCOPE: + case IMMUTABLE_SET_SCOPE: + + case TAGGED2_SCOPE: + case IMMUTABLE_TAGGED2_SCOPE: + + case TAGGED_SCOPE: + case IMMUTABLE_TAGGED_SCOPE: + + case TUPLE_SCOPE: + case IMMUTABLE_TUPLE_SCOPE: + + case TYPED_ARRAY_SCOPE: + case IMMUTABLE_TYPED_ARRAY_SCOPE: + + case TYPED_MAP_SCOPE: + case IMMUTABLE_TYPED_MAP_SCOPE: + + case TYPED_SET_SCOPE: + case IMMUTABLE_TYPED_SET_SCOPE: + + case TYPED_TUPLE_SCOPE: + case IMMUTABLE_TYPED_TUPLE_SCOPE: { + + this.readers.push(this.reader); + + this.nodes.push(path.isEmpty() + ? Utf8String.transcodeUtf16(lenientFormat("[%s]", this.reader.index())) + : path); + + this.reader = this.reader.readScope(); + continue; + } + case MONGODB_OBJECT_ID: { + throw new IllegalStateException(lenientFormat("unsupported layout type: %s", type)); + } + case BOOLEAN_FALSE: + case END_SCOPE: + case INVALID: { + throw new IllegalStateException(lenientFormat("unexpected layout type: %s", type)); + } + default: { + throw new IllegalStateException(lenientFormat("unknown layout type: %s", type)); + } + } + + if (result != Result.SUCCESS) { + String message = lenientFormat("failed to read %s value for %s", type.layoutCode(), path); + throw new IllegalStateException(message); + } + + this.dataItem = new DataItem(this.nodes, path, type.layoutCode(), this.value.get()); + return; + } + + if (this.readers.isEmpty()) { + this.reader = null; + } else { + this.reader = this.readers.pop(); + this.nodes.pop(); + } + } + while (this.reader != null); + } + } + + private static class DataItemVisitor { + + private final BiFunction accept; + private final TContext context; + private final Deque nodes; + + DataItemVisitor(BiFunction accept, TContext context) { + this.accept = accept; + this.context = context; + this.nodes = new ArrayDeque<>(); + } + + BiFunction accept() { + return this.accept; + } + + TContext context() { + return this.context; + } + + Deque nodes() { + return this.nodes; + } + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowSerializable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowSerializable.java new file mode 100644 index 0000000..166c6a8 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowSerializable.java @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; + +/** + * A type may implement this interface to support serialization into a HybridRow. + */ +public interface RowSerializable { + /** + * Writes the current instance into the row + * + * @param writer A writer for the current row scope + * @param typeArg The schematized layout type, if a schema is available + * @return Success if the write is successful, the error code otherwise + */ + Result write(RowWriter writer, TypeArgument typeArg); +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java new file mode 100644 index 0000000..e31ea7f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/RowWriter.java @@ -0,0 +1,794 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.core.UtfAnyString; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutArray; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutColumn; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutListWritable; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutNullable; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutObject; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTagged; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTagged2; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTuple; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypePrimitive; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypeScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedArray; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedMap; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedSet; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypedTuple; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutTypes; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUDT; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUniqueScope; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutUtf8Writable; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgument; +import com.azure.data.cosmos.serialization.hybridrow.layouts.TypeArgumentList; +import com.azure.data.cosmos.serialization.hybridrow.layouts.UpdateOptions; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.math.BigDecimal; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Consumer; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.lenientFormat; + +public final class RowWriter { + + private RowCursor cursor; + private RowBuffer row; + + /** + * Initializes a new instance of the {@link RowWriter} class. + * + * @param row The row to be read. + * @param scope The scope into which items should be written. + *

+ * A {@link RowWriter} instance writes the fields of a given scope from left to right in a forward only + * manner. If the root scope is provided then all top-level fields in the row can be + */ + private RowWriter(RowBuffer row, RowCursor scope) { + this.row = row; + this.cursor = scope; + } + + /** + * The active layout of the current writer scope. + * + * @return layout of the current writer scope. + */ + public Layout layout() { + return this.cursor.layout(); + } + + /** + * The length of row in bytes. + * + * @return length of the row in bytes. + */ + public int length() { + return this.row.length(); + } + + /** + * The resolver for UDTs. + * + * @return the resolver of UDTs. + */ + public LayoutResolver resolver() { + return this.row.resolver(); + } + + /** + * Write a field as a variable length, sequence of bytes. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeBinary(UtfAnyString path, byte[] value) { + return this.writeBinary(path, Unpooled.wrappedBuffer(value)); + } + + /** + * Write a field as a variable length, sequence of bytes. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeBinary(UtfAnyString path, ByteBuf value) { + return this.writePrimitive(path, value, LayoutTypes.BINARY, + field -> this.row.writeSparseBinary(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a {@link Boolean}. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeBoolean(UtfAnyString path, boolean value) { + return this.writePrimitive(path, value, LayoutTypes.BOOLEAN, + field -> this.row.writeSparseBoolean(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write an entire buffer in a streaming left-to-right way. + * + * @param The type of the context value to pass to {@code func}. + * @param buffer The buffer to write. + * @param context A context value to pass to {@code func}. + * @param func A function to write the entire buffer. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public static Result writeBuffer( + @Nonnull final RowBuffer buffer, final @Nonnull TContext context, @Nonnull final WriterFunc func) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(context, "expected non-null context"); + checkNotNull(func, "expected non-null func"); + + RowCursor scope = RowCursor.create(buffer); + RowWriter writer = new RowWriter(buffer, scope); + TypeArgument typeArg = new TypeArgument(LayoutTypes.UDT, new TypeArgumentList(scope.layout().schemaId())); + + return func.invoke(writer, typeArg, context); + } + + /** + * Write a field as a fixed length {@code DateTime} value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeDateTime(UtfAnyString path, OffsetDateTime value) { + return this.writePrimitive(path, value, LayoutTypes.DATE_TIME, + field -> this.row.writeSparseDateTime(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length {@code Decimal} value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeDecimal(UtfAnyString path, BigDecimal value) { + return this.writePrimitive(path, value, LayoutTypes.DECIMAL, + field -> this.row.writeSparseDecimal(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 128-bit, IEEE-encoded floating point value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeFloat128(UtfAnyString path, Float128 value) { + return this.writePrimitive(path, value, LayoutTypes.FLOAT_128, + field -> this.row.writeSparseFloat128(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 32-bit, IEEE-encoded floating point value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeFloat32(UtfAnyString path, float value) { + return this.writePrimitive(path, value, LayoutTypes.FLOAT_32, + field -> this.row.writeSparseFloat32(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 64-bit, IEEE-encoded floating point value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeFloat64(UtfAnyString path, double value) { + return this.writePrimitive(path, value, LayoutTypes.FLOAT_64, + field -> this.row.writeSparseFloat64(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length {@code Guid} value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeGuid(UtfAnyString path, UUID value) { + return this.writePrimitive(path, value, LayoutTypes.GUID, + field -> this.row.writeSparseGuid(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 16-bit, signed integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeInt16(UtfAnyString path, short value) { + return this.writePrimitive(path, value, LayoutTypes.INT_16, + field -> this.row.writeSparseInt16(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 32-bit, signed integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeInt32(UtfAnyString path, int value) { + return this.writePrimitive(path, value, LayoutTypes.INT_32, + field -> this.row.writeSparseInt32(this.cursor, field, UpdateOptions.UPSERT)); + } + + /** + * Write a field as a fixed length, 64-bit, signed integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeInt64(UtfAnyString path, long value) { + return this.writePrimitive(path, value, LayoutTypes.INT_64, + field -> this.row.writeSparseInt64(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 8-bit, signed integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeInt8(UtfAnyString path, byte value) { + return this.writePrimitive(path, value, LayoutTypes.INT_8, + field -> this.row.writeSparseInt8(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + // TODO: DANOBLE: Resurrect this method + // /** + // * Write a field as a fixed length {@link MongoDbObjectId} value. + // * + // * @param path The scope-relative path of the field to write. + // * @param value The value to write. + // * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + // */ + // public Result WriteMongoDbObjectId(UtfAnyString path, MongoDbObjectId value) { + // throw new UnsupportedOperationException(); + // // return this.writePrimitive(path, value, LayoutTypes.MongoDbObjectId, (ref RowWriter w, MongoDbObjectId v) -> w.row.writeSparseMongoDbObjectId(ref w.cursor, v, UpdateOptions.UPSERT)); + // } + + /** + * Write a field as a {@code null}. + * + * @param path The scope-relative path of the field to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeNull(UtfAnyString path) { + return this.writePrimitive(path, NullValue.DEFAULT, LayoutTypes.NULL, + field -> this.row.writeSparseNull(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + public Result writeScope( + @Nonnull final UtfAnyString path, + @Nonnull final TypeArgument typeArg, + @Nullable final TContext context, + @Nullable final WriterFunc func) { + + checkNotNull(path, "expected non-null path"); + checkNotNull(typeArg, "expected non-null typeArg"); + + Result result = this.prepareSparseWrite(path, typeArg); + + if (result != Result.SUCCESS) { + return result; + } + + final UpdateOptions options = UpdateOptions.UPSERT; + final LayoutType type = typeArg.type(); + final RowCursor nestedScope; + + if (type instanceof LayoutObject) { + + nestedScope = this.row.writeSparseObject(this.cursor, (LayoutObject) type, options); + + } else if (type instanceof LayoutArray) { + + nestedScope = this.row.writeSparseArray(this.cursor, (LayoutArray) type, options); + + } else if (type instanceof LayoutTypedArray) { + + nestedScope = this.row.writeTypedArray(this.cursor, (LayoutTypedArray) type, typeArg.typeArgs(), options); + + } else if (type instanceof LayoutTuple) { + + nestedScope = this.row.writeSparseTuple(this.cursor, (LayoutTuple) type, typeArg.typeArgs(), options); + + } else if (type instanceof LayoutTypedTuple) { + + nestedScope = this.row.writeTypedTuple(this.cursor, (LayoutTypedTuple) type, typeArg.typeArgs(), options); + + } else if (type instanceof LayoutTagged) { + + nestedScope = this.row.writeTypedTuple(this.cursor, (LayoutTagged) type, typeArg.typeArgs(), options); + + } else if (type instanceof LayoutTagged2) { + + nestedScope = this.row.writeTypedTuple(this.cursor, (LayoutTagged2) type, typeArg.typeArgs(), options); + + } else if (type instanceof LayoutNullable) { + + nestedScope = this.row.writeNullable(this.cursor, (LayoutNullable) type, typeArg.typeArgs(), options, + func != null); + + } else if (type instanceof LayoutUDT) { + + LayoutUDT scopeType = (LayoutUDT) type; + Layout udt = this.row.resolver().resolve(typeArg.typeArgs().schemaId()); + nestedScope = this.row.writeSparseUDT(this.cursor, scopeType, udt, options); + + } else if (type instanceof LayoutTypedSet) { + + LayoutTypedSet scopeType = (LayoutTypedSet) type; + nestedScope = this.row.writeTypedSet(this.cursor, scopeType, typeArg.typeArgs(), options); + + } else if (type instanceof LayoutTypedMap) { + + LayoutTypedMap scopeType = (LayoutTypedMap) type; + nestedScope = this.row.writeTypedMap(this.cursor, scopeType, typeArg.typeArgs(), options); + + } else { + + throw new IllegalStateException(lenientFormat("expected type argument of %s, not %s", + LayoutTypeScope.class, + type.getClass())); + } + + RowWriter nestedWriter = new RowWriter(this.row, nestedScope); + result = func == null ? null : func.invoke(nestedWriter, typeArg, context); + + if (result == null) { + result = Result.SUCCESS; + } + + this.row = nestedWriter.row; + nestedScope.count(nestedWriter.cursor.count()); + + if (result != Result.SUCCESS) { + // TODO: what about unique violations here? + return result; + } + + if (type instanceof LayoutUniqueScope) { + result = this.row.typedCollectionUniqueIndexRebuild(nestedScope); + if (result != Result.SUCCESS) { + // TODO: If the index rebuild fails then the row is corrupted. Should we automatically clean up here? + return result; + } + } + + RowCursors.moveNext(this.cursor, this.row, nestedWriter.cursor); + return Result.SUCCESS; + } + + /** + * Write a field as a variable length, UTF8 encoded, string value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeString(UtfAnyString path, String value) { + + // TODO: DANOBLE: RowBuffer should support writing String values directly (without conversion to Utf8String) + + Utf8String string = Utf8String.transcodeUtf16(value); + assert string != null; + + try { + return this.writePrimitive(path, value, LayoutTypes.UTF_8, + field -> this.row.writeSparseString(this.cursor, string, UpdateOptions.UPSERT) + ); + } finally { + string.release(); + } + } + + /** + * Write a field as a variable length, UTF8 encoded, string value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeString(UtfAnyString path, Utf8String value) { + // TODO: DANOBLE: BUG FIX: this.writePrimitive should write Utf8String as well as String + // note incorrect use of string "value" as the value argument + return this.writePrimitive(path, "value", LayoutTypes.UTF_8, + field -> this.row.writeSparseString(this.cursor, value, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 16-bit, unsigned integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeUInt16(UtfAnyString path, short value) { + return this.writePrimitive(path, (int) value, LayoutTypes.UINT_16, + field -> this.row.writeSparseUInt16(this.cursor, field.shortValue(), UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 32-bit, unsigned integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeUInt32(UtfAnyString path, long value) { + return this.writePrimitive(path, value, LayoutTypes.UINT_32, field -> + this.row.writeSparseUInt32(this.cursor, field.intValue(), UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 64-bit, unsigned integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeUInt64(UtfAnyString path, long value) { + return this.writePrimitive(path, value, LayoutTypes.UINT_64, field -> + this.row.writeSparseUInt64(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length, 8-bit, unsigned integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeUInt8(UtfAnyString path, byte value) { + return this.writePrimitive(path, (short) value, LayoutTypes.UINT_8, + field -> this.row.writeSparseUInt8(this.cursor, field.byteValue(), UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a fixed length {@link UnixDateTime} value. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeUnixDateTime(UtfAnyString path, UnixDateTime value) { + return this.writePrimitive(path, value, LayoutTypes.UNIX_DATE_TIME, + field -> this.row.writeSparseUnixDateTime(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a variable length, 7-bit encoded, signed integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeVarInt(UtfAnyString path, long value) { + return this.writePrimitive(path, value, LayoutTypes.VAR_INT, + field -> this.row.writeSparseVarInt(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Write a field as a variable length, 7-bit encoded, unsigned integer. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + public Result writeVarUInt(UtfAnyString path, long value) { + return this.writePrimitive(path, value, LayoutTypes.VAR_UINT, + field -> this.row.writeSparseVarUInt(this.cursor, field, UpdateOptions.UPSERT) + ); + } + + /** + * Helper for preparing the write of a sparse field. + * + * @param path The path identifying the field to write. + * @param typeArg The (optional) type constraints. + * @return Success if the write is permitted, the error code otherwise. + */ + private Result prepareSparseWrite(UtfAnyString path, TypeArgument typeArg) { + + if (this.cursor.scopeType().isFixedArity() && !(this.cursor.scopeType() instanceof LayoutNullable)) { + if ((this.cursor.index() < this.cursor.scopeTypeArgs().count()) && !typeArg.equals(this.cursor.scopeTypeArgs().get(this.cursor.index()))) { + return Result.TYPE_CONSTRAINT; + } + } else if (this.cursor.scopeType() instanceof LayoutTypedMap) { + if (!typeArg.equals(this.cursor.scopeType().typeAs().fieldType(this.cursor))) { + return Result.TYPE_CONSTRAINT; + } + } else if (this.cursor.scopeType().isTypedScope() && !typeArg.equals(this.cursor.scopeTypeArgs().get(0))) { + return Result.TYPE_CONSTRAINT; + } + + this.cursor.writePath(path); + return Result.SUCCESS; + } + + // TODO: DANOBLE: Does Java implementation need this method? + /** + * Helper for writing a primitive value. + * + * @param The type of layout type. + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @param type The layout type. + * @param sparse The {@link RowBuffer} access method for {@code type}. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + private + Result writePrimitive(UtfAnyString path, Utf8String value, TLayoutType type, Consumer sparse) { + + Result result = Result.NOT_FOUND; + + if (this.cursor.scopeType() instanceof LayoutUDT) { + result = this.writeSchematizedValue(path, value); + } + + if (result == Result.NOT_FOUND) { + + result = this.prepareSparseWrite(path, type.typeArg()); + + if (result != Result.SUCCESS) { + return result; + } + + sparse.accept(value); + RowCursors.moveNext(this.cursor, this.row); + } + + return result; + } + + // TODO: DANOBLE: Does Java implementation need this method? + /** + * Helper for writing a primitive value. + * + * @param The type of layout type. + * @param The sub-element type of the field. + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @param type The layout type. + * @param sparse The {@link RowBuffer} access method for {@code type}. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + private , TValue> + Result writePrimitiveList(UtfAnyString path, List value, TLayoutType type, Consumer> sparse) { + + Result result = Result.NOT_FOUND; + + if (this.cursor.scopeType() instanceof LayoutUDT) { + result = this.writeSchematizedValue(path, value); + } + + if (result == Result.NOT_FOUND) { + + result = this.prepareSparseWrite(path, type.typeArg()); + + if (result != Result.SUCCESS) { + return result; + } + + sparse.accept(value); + RowCursors.moveNext(this.cursor, this.row); + } + + return result; + } + + /** + * Helper for writing a primitive value. + * + * @param The type of the primitive value. + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @param type The layout type. + * @param sparse The {@link RowBuffer} access method for {@code type}. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + private Result writePrimitive( + UtfAnyString path, TValue value, LayoutTypePrimitive type, Consumer sparse) { + + Result result = Result.NOT_FOUND; + + if (this.cursor.scopeType() instanceof LayoutUDT) { + result = this.writeSchematizedValue(path, value); + } + + if (result == Result.NOT_FOUND) { + + result = this.prepareSparseWrite(path, type.typeArg()); + + if (result != Result.SUCCESS) { + return result; + } + + sparse.accept(value); + RowCursors.moveNext(this.cursor, this.row); + } + + return result; + } + + /** + * Write a generic schematized field value via the scope's layout. + * + * @param The expected type of the field. + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + private Result writeSchematizedValue(UtfAnyString path, TValue value) { + + final Optional column = this.cursor.layout().tryFind(path); + + if (!column.isPresent()) { + return Result.NOT_FOUND; + } + + // TODO: DANOBLE: Add a mechanism for performing the equivalent of this type check + // if (!(column.Type is LayoutTypePrimitive t)) { + // return Result.NotFound; + // } + // Type erasure prevents this test: + // column.type instanceof LayoutTypePrimitive + // Reason: Runtime does not instantiate or otherwise represent or identify instances of a generic type. + + if (!(column.get().type() instanceof LayoutTypePrimitive)) { + return Result.NOT_FOUND; + } + + @SuppressWarnings("unchecked") + LayoutTypePrimitive type = (LayoutTypePrimitive)column.get().type(); + + switch (column.get().storage()) { + case FIXED: + return type.writeFixed(this.row, this.cursor, column.get(), value); + case VARIABLE: + return type.writeVariable(this.row, this.cursor, column.get(), value); + } + + return Result.NOT_FOUND; + } + + /** + * Write a generic schematized field value via the scope's layout. + * + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + private Result writeSchematizedValue(UtfAnyString path, Utf8String value) { + + final Optional column = this.cursor.layout().tryFind(path); + + if (!column.isPresent()) { + return Result.NOT_FOUND; + } + + final LayoutType type = column.get().type(); + + if (!(type instanceof LayoutUtf8Writable)) { + return Result.NOT_FOUND; + } + + switch (column.get().storage()) { + case FIXED: + return type.typeAs().writeFixed(this.row, this.cursor, column.get(), value); + case VARIABLE: + return type.typeAs().writeVariable(this.row, this.cursor, column.get(), value); + } + + return Result.NOT_FOUND; + } + + /** + * Write a generic schematized field value via the scope's layout. + * + * @param The sub-element type of the field. + * @param path The scope-relative path of the field to write. + * @param value The value to write. + * @return {@link Result#SUCCESS} if the write is successful, an error {@link Result} otherwise. + */ + private Result writeSchematizedValue(UtfAnyString path, List value) { + + final Optional column = this.cursor.layout().tryFind(path); + + if (!column.isPresent()) { + return Result.NOT_FOUND; + } + + final LayoutType type = column.get().type(); + + if (!(type instanceof LayoutListWritable)) { + return Result.NOT_FOUND; + } + + switch (column.get().storage()) { + case FIXED: + return type.>typeAs().writeFixedList(this.row, this.cursor, column.get(), value); + case VARIABLE: + return type.>typeAs().writeVariableList(this.row, this.cursor, column.get(), value); + } + + return Result.NOT_FOUND; + } + + /** + * Functional interface for writing content to a {@link RowBuffer}. + */ + @FunctionalInterface + public interface WriterFunc { + /** + * Write content using the specified writer, type argument, and context. + * + * @param writer writes content. + * @param typeArg specifies a type argument. + * @param context provides context for the write operation. + * @return a result code + */ + Result invoke(RowWriter writer, TypeArgument typeArg, TContext context); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/Segment.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/Segment.java new file mode 100644 index 0000000..106c54f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/io/Segment.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +public final class Segment { + + private String comment; + private int length; + private String sdl; + + public Segment(String comment, String sdl) { + this.comment = comment; + this.sdl = sdl; + this.length = 0; + } + + public String comment() { + return this.comment; + } + + public Segment comment(String value) { + this.comment = value; + return this; + } + + public int length() { + return this.length; + } + + public Segment length(int value) { + this.length = value; + return this; + } + public String sdl() { + return this.sdl; + } + + public Segment sdl(String value) { + this.sdl = value; + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonExtensions.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonExtensions.java new file mode 100644 index 0000000..f153e2d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonExtensions.java @@ -0,0 +1,441 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.json; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; +import com.azure.data.cosmos.serialization.hybridrow.io.RowReader; +import org.checkerframework.checker.nullness.qual.NonNull; + +import javax.annotation.Nonnull; +import java.util.Objects; + +import static com.google.common.base.Strings.lenientFormat; + +public final class RowReaderJsonExtensions { + /** + * Project a JSON document from a HybridRow {@link RowReader}. + * + * @param reader The reader to project to JSON. + * @param string If {@link Result#SUCCESS}, the JSON document that corresponds to the {@code reader}. + * @return The result. + */ + @Nonnull + public static Result toJson(@Nonnull final RowReader reader, @Nonnull final Out string) { + return RowReaderJsonExtensions.toJson(reader, new RowReaderJsonSettings(" "), string); + } + + /** + * Project a JSON document from a HybridRow {@link RowReader}. + * + * @param reader The reader to project to JSON. + * @param settings Settings that control how the JSON document is formatted. + * @param string If {@link Result#SUCCESS}, the JSON document that corresponds to the {@code reader}. + * @return The result. + */ + @Nonnull + public static Result toJson( + @Nonnull final RowReader reader, + @Nonnull final RowReaderJsonSettings settings, + @Nonnull final Out string) { + + final ReaderStringContext context = new ReaderStringContext( + new StringBuilder(), + new RowReaderJsonSettings( + settings.indentChars(), + settings.quoteChar() == '\'' ? '\'' : '"'), + 1); + + context.builder().append("{"); + Result result = RowReaderJsonExtensions.toJson(reader, context); + + if (result != Result.SUCCESS) { + string.set(null); + return result; + } + + context.builder().append(context.newline()); + context.builder().append("}"); + + string.set(context.builder().toString()); + return Result.SUCCESS; + } + + @Nonnull + private static Result toJson(@Nonnull final RowReader reader, @Nonnull final ReaderStringContext context) { + + int index = 0; + + while (reader.read()) { + String path = !reader.path().isNull() + ? lenientFormat("%s%s%s:", context.settings().quoteChar(), reader.path(), context.settings().quoteChar()) + : null; + if (index != 0) { + context.builder().append(','); + } + + index++; + context.builder().append(context.newline()); + context.writeIndent(); + + if (path != null) { + context.builder().append(path); + context.builder().append(context.separator()); + } + + final Out out = new Out<>(); + Result result; + char scopeBracket = '\0'; + char scopeCloseBracket = '\0'; + + switch (Objects.requireNonNull(reader.type()).layoutCode()) { + + case NULL: { + result = reader.readNull(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append("null"); + break; + } + + case BOOLEAN: { + result = reader.readBoolean(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case INT_8: { + result = reader.readInt8(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case INT_16: { + result = reader.readInt16(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case INT_32: { + result = reader.readInt32(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case INT_64: { + result = reader.readInt64(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case UINT_8: { + result = reader.readUInt8(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case UINT_16: { + result = reader.readUInt16(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case UINT_32: { + result = reader.readUInt32(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case UINT_64: { + result = reader.readUInt64(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case VAR_INT: { + result = reader.readVarInt(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case VAR_UINT: { + result = reader.readVarUInt(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case FLOAT_32: { + result = reader.readFloat32(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case FLOAT_64: { + result = reader.readFloat64(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case FLOAT_128: { + result = reader.readFloat128(out); + if (result != Result.SUCCESS) { + return result; + } + // context.Builder.AppendFormat("High: {0}, Low: {1}\n", value.High, value.Low); + throw new UnsupportedOperationException("Float128 values are not supported."); + } + + case DECIMAL: { + result = reader.readDecimal(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(out.get()); + break; + } + + case DATE_TIME: { + result = reader.readDateTime(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(context.settings().quoteChar()); + context.builder().append(out.get()); + context.builder().append(context.settings().quoteChar()); + break; + } + + case UNIX_DATE_TIME: { + result = reader.readUnixDateTime(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(((UnixDateTime)out.get()).milliseconds()); + break; + } + + case GUID: { + result = reader.readGuid(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(context.settings().quoteChar()); + context.builder().append(out.get()); + context.builder().append(context.settings().quoteChar()); + break; + } + + case MONGODB_OBJECT_ID: { + // TODO: DANOBLE: Resurrect this code block + // MongoDbObjectId value; + // Out tempOut_value18 = + // new Out(); + // result = reader.ReadMongoDbObjectId(tempOut_value18); + // value = tempOut_value18.get(); + // if (result != Result.SUCCESS) { + // return result; + // } + // + // context.builder().append(context.settings().quoteChar()); + // //C# TO JAVA CONVERTER WARNING: Unsigned integer types have no direct equivalent in Java: + // //ORIGINAL LINE: ReadOnlyMemory bytes = value.ToByteArray(); + // ReadOnlyMemory bytes = value.ToByteArray(); + // context.builder().append(bytes.Span.ToHexString()); + // context.builder().append(context.settings().quoteChar()); + break; + } + + case UTF_8: { + result = reader.readString(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(context.settings().quoteChar()); + context.builder().append(Json.toString(out)); + context.builder().append(context.settings().quoteChar()); + break; + } + + case BINARY: { + result = reader.readBinary(out); + if (result != Result.SUCCESS) { + return result; + } + context.builder().append(context.settings().quoteChar()); + context.builder().append(out.get()); + context.builder().append(context.settings().quoteChar()); + break; + } + + case NULLABLE_SCOPE: + case IMMUTABLE_NULLABLE_SCOPE: + if (!reader.hasValue()) { + context.builder().append("null"); + break; + } + + case ARRAY_SCOPE: + case IMMUTABLE_ARRAY_SCOPE: + case TYPED_ARRAY_SCOPE: + case IMMUTABLE_TYPED_ARRAY_SCOPE: + case TYPED_SET_SCOPE: + case IMMUTABLE_TYPED_SET_SCOPE: + case TYPED_MAP_SCOPE: + case IMMUTABLE_TYPED_MAP_SCOPE: + case TUPLE_SCOPE: + case IMMUTABLE_TUPLE_SCOPE: + case TYPED_TUPLE_SCOPE: + case IMMUTABLE_TYPED_TUPLE_SCOPE: + case TAGGED_SCOPE: + case IMMUTABLE_TAGGED_SCOPE: + case TAGGED2_SCOPE: + case IMMUTABLE_TAGGED2_SCOPE: + result = endScope(reader, context, scopeBracket = '[', scopeCloseBracket = ']'); + if (result != Result.SUCCESS) { + return result; + } + break; + case OBJECT_SCOPE: + case IMMUTABLE_OBJECT_SCOPE: + case SCHEMA: + case IMMUTABLE_SCHEMA: + result = endScope(reader, context, scopeBracket = '{', scopeCloseBracket = '}'); + if (result != Result.SUCCESS) { + return result; + } + break; + + case END_SCOPE: { + result = endScope(reader, context, scopeBracket, scopeCloseBracket); + if (result != Result.SUCCESS) { + return result; + } + break; + } + + default: { + throw new IllegalStateException(lenientFormat("Unknown type will be ignored: %s", + Objects.requireNonNull(reader.type()).layoutCode()) + ); + } + } + } + + return Result.SUCCESS; + } + + @NonNull + private static Result endScope( + @Nonnull RowReader reader, @Nonnull ReaderStringContext context, char scopeBracket, char scopeCloseBracket) { + + Result result; + context.builder().append(scopeBracket); + int snapshot = context.builder().length(); + + result = reader.readScope( + new ReaderStringContext( + context.builder(), + context.settings(), + context.indent() + 1), + RowReaderJsonExtensions::toJson); + + if (result != Result.SUCCESS) { + return result; + } + + if (context.builder().length() != snapshot) { + context.builder().append(context.newline()); + context.writeIndent(); + } + + context.builder().append(scopeCloseBracket); + return result; + } + + private final static class ReaderStringContext { + + private StringBuilder builder; + private int indent; + private String newline; + private String separator; + private RowReaderJsonSettings settings = new RowReaderJsonSettings(); + + public ReaderStringContext(StringBuilder builder, RowReaderJsonSettings settings, int indent) { + this.settings = settings; + this.separator = settings.indentChars() == null ? "" : " "; + this.newline = settings.indentChars() == null ? "" : "\n"; + this.indent = indent; + this.builder = builder; + } + + public StringBuilder builder() { + return this.builder; + } + + public int indent() { + return this.indent; + } + + public String newline() { + return this.newline; + } + + public String separator() { + return this.separator; + } + + public RowReaderJsonSettings settings() { + return this.settings; + } + + public void writeIndent() { + String indentChars = this.settings().indentChars() != null ? this.settings().indentChars() : ""; + for (int i = 0; i < this.indent(); i++) { + this.builder().append(indentChars); + } + } + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonSettings.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonSettings.java new file mode 100644 index 0000000..fb70769 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/json/RowReaderJsonSettings.java @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.json; + +public final class RowReaderJsonSettings { + + private String indentChars; + private char quoteChar; + + public RowReaderJsonSettings(String indentChars) { + this(indentChars, '"'); + } + + public RowReaderJsonSettings() { + this(" ", '"'); + } + + public RowReaderJsonSettings(String indentChars, char quoteChar) { + this.indentChars = indentChars; + this.quoteChar = quoteChar; + } + + /** + * If non-null then child objects are indented by one copy of this string per level. + * + * @return indentation characters. + */ + public String indentChars() { + return this.indentChars; + } + + /** + * The current quote character. + *

+ * May be double or single quote. + * + * @return quote character. + */ + public char quoteChar() { + return this.quoteChar; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/ILayoutType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/ILayoutType.java new file mode 100644 index 0000000..1c48809 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/ILayoutType.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +/** + * Marker interface for layout types. + */ +public interface ILayoutType { +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java new file mode 100644 index 0000000..cdbf88c --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/Layout.java @@ -0,0 +1,242 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.core.UtfAnyString; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Schema; +import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind; +import com.google.common.collect.ImmutableList; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A Layout describes the structure of a Hybrid Row. + *

+ * A layout indicates the number, order, and type of all schematized columns to be stored within a hybrid row. The + * order and type of columns defines the physical ordering of bytes used to encode the row and impacts the cost of + * updating the row. + *

+ * A layout is created by compiling a {@link Schema} through {@link Schema#compile(Namespace)} or by constructor through + * a {@link LayoutBuilder}. + * + * {@link Layout} is immutable. + */ +public final class Layout { + + public static final Layout EMPTY = SystemSchema.layoutResolver().resolve(SystemSchema.EMPTY_SCHEMA_ID); + + private final String name; + private final int numBitmaskBytes; + private final int numFixed; + private final int numVariable; + private final HashMap pathMap; + private final HashMap pathStringMap; + private final SchemaId schemaId; + private final int size; + private final StringTokenizer tokenizer; + private final ImmutableList topColumns; + + @SuppressWarnings("UnstableApiUsage") + public Layout( + @Nonnull final String name, + @Nonnull final SchemaId schemaId, + final int numBitmaskBytes, + final int minRequiredSize, + @Nonnull final ArrayList columns) { + + checkNotNull(name, "expected non-null name"); + checkNotNull(schemaId, "expected non-null schemaId"); + checkNotNull(columns, "expected non-null columns"); + + checkArgument(numBitmaskBytes >= 0, "expected non-negative numBitmaskBytes, not %s", numBitmaskBytes); + checkArgument(minRequiredSize >= 0, "expected non-negative minRequiredSize", minRequiredSize); + + this.name = name; + this.schemaId = schemaId; + this.numBitmaskBytes = numBitmaskBytes; + this.size = minRequiredSize; + this.tokenizer = new StringTokenizer(); + this.pathMap = new HashMap<>(columns.size()); + this.pathStringMap = new HashMap<>(columns.size()); + + ImmutableList.Builder builder = ImmutableList.builderWithExpectedSize(columns.size()); + int numFixed = 0; + int numVariable = 0; + + for (LayoutColumn column : columns) { + + this.tokenizer().add(column.path()); + this.pathMap.put(column.fullPath(), column); + this.pathStringMap.put(column.fullPath().toString(), column); + + if (column.storage() == StorageKind.FIXED) { + numFixed++; + } else if (column.storage() == StorageKind.VARIABLE) { + numVariable++; + } + + if (column.parent() == null) { + builder.add(column); + } + } + + this.numFixed = numFixed; + this.numVariable = numVariable; + this.topColumns = builder.build(); + } + + /** + * Finds a column specification for a column with a matching path. + * + * @param path path of the column to find + * @return {@link LayoutColumn}, if a column with the {@code path} is found, {@link Optional#empty()} + */ + public Optional tryFind(@Nonnull UtfAnyString path) { + + checkNotNull(path); + + if (path.isNull()) { + return Optional.empty(); + } + + if (path.isUtf8()) { + return Optional.ofNullable(this.pathMap.get(path.toUtf8())); + } + + return Optional.ofNullable(this.pathStringMap.get(path.toUtf16())); + } + + /** + * Finds a column specification for a column with a matching path. + * + * @param path The path of the column to find. + * @return True if a column with the path is found, otherwise false. + */ + public Optional tryFind(@Nonnull String path) { + checkNotNull(path); + return Optional.ofNullable(this.pathStringMap.get(path)); + } + + /** + * Top level columns defined by the current {@link Layout} in left-to-right order. + * + * @return Top level columns defined by the current {@link Layout} in left-to-right order + */ + public List columns() { + return this.topColumns; + } + + /** + * Name of the layout. + *

+ * Usually this is the name of the {@link Schema} from which this {@link Layout} was generated. + * + * @return name of the layout. + */ + public String name() { + return this.name; + } + + /** + * The number of bit mask bytes allocated within the layout. + *

+ * A presence bit is allocated for each fixed and variable-length field. Sparse columns never have presence bits. + * Fixed boolean allocate an additional bit from the bitmask to store their value. + * + * @return the number of bit mask bytes allocated with the layout. + */ + public int numBitmaskBytes() { + return this.numBitmaskBytes; + } + + /** + * The number of fixed columns. + * + * @return the number of fixed columns. + */ + public int numFixed() { + return this.numFixed; + } + + /** + * The number of variable-length columns. + * + * @return the number of variable-length columns. + */ + public int numVariable() { + return this.numVariable; + } + + /** + * Unique identifier of the schema from which this {@link Layout} was generated. + * + * @return the unique identifier of the schema from which this {@link Layout} was generated. + */ + public SchemaId schemaId() { + return this.schemaId; + } + + /** + * The minimum required size of a row with this layout. + *

+ * This size excludes all sparse columns, and assumes all columns (including variable) are + * null. + * + * @return the minimum required size of a row with this layout. + */ + public int size() { + return this.size; + } + + /** + * A human readable diagnostic string representing this {@link Layout}. + *

+ * This representation should only be used for debugging and diagnostic purposes. + * + * @return a human readable diagnostic string representing this {@link Layout}. + */ + @Override + @Nonnull + public String toString() { + + StringBuilder sb = new StringBuilder(); + + sb.append("Layout:\n"); + sb.append(String.format("\tCount: %1$s\n", this.topColumns.size())); + sb.append(String.format("\tFixedSize: %1$s\n", this.size())); + + for (LayoutColumn column : this.topColumns) { + if (column.type().isFixed()) { + if (column.type().isBoolean()) { + sb.append(String.format("\t%1$s: %2$s @ %3$s:%4$s:%5$s\n", column.fullPath(), column.type().name(), column.offset(), column.nullBit(), column.booleanBit())); + } else { + sb.append(String.format("\t%1$s: %2$s @ %3$s\n", column.fullPath(), column.type().name(), column.offset())); + } + } else { + sb.append(String.format("\t%1$s: %2$s[%4$s] @ %3$s\n", column.fullPath(), column.type().name(), column.offset(), column.size())); + } + } + + return sb.toString(); + } + + /** + * A {@linkplain StringTokenizer tokenizer} for path strings. + * + * @return a {@linkplain StringTokenizer tokenizer} for path strings. + */ + public StringTokenizer tokenizer() { + return this.tokenizer; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java new file mode 100644 index 0000000..7aa2166 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutArray.java @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.ARRAY_SCOPE; +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.IMMUTABLE_ARRAY_SCOPE; + +public final class LayoutArray extends LayoutIndexedScope { + + public LayoutArray(final boolean immutable) { + super(immutable ? IMMUTABLE_ARRAY_SCOPE : ARRAY_SCOPE, immutable, false, false, false, false); + } + + @Nonnull + public String name() { + return this.isImmutable() ? "im_array" : "array"; + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull TypeArgumentList typeArgs, @Nonnull UpdateOptions options, @Nonnull Out value) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + buffer.writeSparseArray(edit, this, options); + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java new file mode 100644 index 0000000..4ea5aea --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBinary.java @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import io.netty.buffer.ByteBuf; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutBinary extends LayoutTypePrimitive { + // implements + // LayoutListWritable, + // LayoutListReadable, + // ILayoutSequenceWritable { + + public LayoutBinary() { + super(LayoutCode.BINARY, 0); + } + + public boolean isFixed() { + return false; + } + + @Nonnull + public String name() { + return "binary"; + } + + @Override + @Nonnull + public Result readFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + checkArgument(column.size() >= 0); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(null); + return Result.NOT_FOUND; + } + + value.set(buffer.readFixedBinary(scope.start() + column.offset(), column.size())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse( + @Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit, @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + + final Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.readSparseBinary(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readVariable( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull LayoutColumn column, + @Nonnull Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(null); + return Result.NOT_FOUND; + } + + final int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + value.set(buffer.readVariableBinary(valueOffset)); + + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull LayoutColumn column, + @Nonnull ByteBuf value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + checkArgument(column.size() >= 0); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + final int valueOffset = scope.start() + column.offset(); + buffer.setBit(scope.start(), column.nullBit()); + + buffer.writeFixedBinary(valueOffset, value, column.size()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull ByteBuf value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } + + @Override + @Nonnull + public Result writeSparse( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull ByteBuf value, + @Nonnull UpdateOptions options) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseBinary(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeVariable( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull LayoutColumn column, + @Nonnull ByteBuf value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + if ((column.size() > 0) && (value.readableBytes() > column.size())) { + return Result.TOO_BIG; + } + + final boolean exists = buffer.readBit(scope.start(), column.nullBit()); + final int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + final Out shift = new Out<>(); + + buffer.writeVariableBinary(valueOffset, value, exists, shift); + buffer.setBit(scope.start(), column.nullBit()); + scope.metaOffset(scope.metaOffset() + shift.get()); + scope.valueOffset(scope.valueOffset() + shift.get()); + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBit.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBit.java new file mode 100644 index 0000000..d4e635d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBit.java @@ -0,0 +1,119 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutBit { + /** + * The empty bit. + */ + public static final LayoutBit INVALID = new LayoutBit(-1); + + private final int index; + + /** + * Initializes a new instance of the {@link LayoutBit} class. + * + * @param index The zero-based offset into the layout bitmask. + */ + public LayoutBit(int index) { + checkArgument(index >= -1); + this.index = index; + } + + /** + * Compute the division rounding up to the next whole number + * + * @param numerator The numerator to divide. + * @param divisor The divisor to divide by. + * @return The ceiling(numerator/divisor). + */ + public static int divCeiling(int numerator, int divisor) { + return (numerator + (divisor - 1)) / divisor; + } + + /** + * Zero-based bit from the beginning of the byte that contains this bit. + *

+ * Also see {@link #offset(int)} to identify relevant byte. + * + * @return The bit of the byte within the bitmask. + */ + public int bit() { + return this.index() % Byte.SIZE; + } + + /** + * Zero-based offset into the layout bitmask. + * + * @return zero-based offset into the layout bitmask. + */ + public int index() { + return this.index; + } + + public boolean isInvalid() { + return this.index == INVALID.index; + } + + /** + * Returns the zero-based byte offset from the beginning of the row or scope that contains the bit from the bitmask. + *

+ * Also see {@link #bit()} to identify. + * + * @param offset The byte offset from the beginning of the row where the scope begins. + * @return The byte offset containing this bit. + */ + public int offset(int offset) { + return offset + (this.index() / Byte.SIZE); + } + + @Override + public boolean equals(Object other) { + return other instanceof LayoutBit && this.equals((LayoutBit)other); + } + + public boolean equals(LayoutBit other) { + return other != null && this.index() == other.index(); + } + + @Override + public int hashCode() { + return Integer.valueOf(this.index()).hashCode(); + } + + /** + * Allocates layout bits from a bitmask. + */ + static class Allocator { + /** + * The next bit to allocate. + */ + private int next; + + /** + * Initializes a new instance of the {@link Allocator} class. + */ + public Allocator() { + this.next = 0; + } + + /** + * The number of bytes needed to hold all bits so far allocated. + */ + public final int numBytes() { + return LayoutBit.divCeiling(this.next, Byte.SIZE); + } + + /** + * Allocates a new bit from the bitmask. + * + * @return The allocated bit. + */ + public final LayoutBit allocate() { + return new LayoutBit(this.next++); + } + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBoolean.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBoolean.java new file mode 100644 index 0000000..23abd09 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBoolean.java @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutBoolean extends LayoutTypePrimitive implements ILayoutType { + + public LayoutBoolean(boolean value) { + super(value ? LayoutCode.BOOLEAN : LayoutCode.BOOLEAN_FALSE, 0); + } + + @Override + public boolean isBoolean() { + return true; + } + + @Override + public boolean isFixed() { + return true; + } + + @Override + @Nonnull + public String name() { + return "bool"; + } + + @Override + @Nonnull + public Result readFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(false); + return Result.NOT_FOUND; + } + + value.set(buffer.readBit(scope.start(), column.booleanBit())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + if (result != Result.SUCCESS) { + value.set(false); + return result; + } + + value.set(buffer.readSparseBoolean(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Boolean value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT, + "expected scope of %s, not %s", LayoutUDT.class, scope.scopeType().getClass()); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + if (value) { + buffer.setBit(scope.start(), column.booleanBit()); + } else { + buffer.unsetBit(scope.start(), column.booleanBit()); + } + + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final Boolean value, + @Nonnull final UpdateOptions options) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + checkNotNull(options, "expected non-null options"); + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseBoolean(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Boolean value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBuilder.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBuilder.java new file mode 100644 index 0000000..99a0f1e --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutBuilder.java @@ -0,0 +1,180 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.Stack; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutBuilder { + private LayoutBit.Allocator bitAllocator; + private ArrayList fixedColumns; + private int fixedCount; + private int fixedSize; + private String name; + private SchemaId schemaId; + private Stack scope; + private ArrayList sparseColumns; + private int sparseCount; + private ArrayList varColumns; + private int varCount; + + // [ + // + // ... + // ... + // ... + // ] + public LayoutBuilder(String name, SchemaId schemaId) { + this.name = name; + this.schemaId = schemaId; + this.reset(); + } + + public void addFixedColumn(@Nonnull String path, @Nonnull LayoutType type, boolean nullable, int length) { + + checkNotNull(path, "expected non-null path"); + checkNotNull(type, "expected non-null type"); + checkArgument(length >= 0); + checkArgument(!type.isVarint()); + + final LayoutColumn column; + + if (type.isNull()) { + checkArgument(nullable); + LayoutBit boolBit = this.bitAllocator.allocate(); + LayoutBit nullBit = LayoutBit.INVALID; + int offset = 0; + column = new LayoutColumn( + path, type, TypeArgumentList.EMPTY, StorageKind.FIXED, this.parent(), this.fixedCount, offset, + boolBit, nullBit, 0); + } else if (type.isBoolean()) { + LayoutBit nullBit = nullable ? this.bitAllocator.allocate() : LayoutBit.INVALID; + LayoutBit boolBit = this.bitAllocator.allocate(); + int offset = 0; + column = new LayoutColumn( + path, type, TypeArgumentList.EMPTY, StorageKind.FIXED, this.parent(), this.fixedCount, offset, + nullBit, boolBit, 0); + } else { + LayoutBit boolBit = LayoutBit.INVALID; + LayoutBit nullBit = nullable ? this.bitAllocator.allocate() : LayoutBit.INVALID; + int offset = this.fixedSize; + column = new LayoutColumn( + path, type, TypeArgumentList.EMPTY, StorageKind.FIXED, this.parent(), this.fixedCount, offset, + nullBit, boolBit, length); + this.fixedSize += type.isFixed() ? type.size() : length; + } + + this.fixedCount++; + this.fixedColumns.add(column); + } + + public void addObjectScope(String path, LayoutType type) { + + LayoutColumn column = new LayoutColumn(path, type, TypeArgumentList.EMPTY, StorageKind.SPARSE, this.parent(), + this.sparseCount, -1, LayoutBit.INVALID, LayoutBit.INVALID, 0); + + this.sparseCount++; + this.sparseColumns.add(column); + this.scope.push(column); + } + + public void addSparseColumn(@Nonnull final String path, @Nonnull final LayoutType type) { + + checkNotNull(path, "expected non-null path"); + checkNotNull(type, "expected non-null type"); + + final LayoutColumn column = new LayoutColumn( + path, type, TypeArgumentList.EMPTY, StorageKind.SPARSE, this.parent(), this.sparseCount, -1, + LayoutBit.INVALID, LayoutBit.INVALID, 0); + + this.sparseCount++; + this.sparseColumns.add(column); + } + + public void addTypedScope( + @Nonnull final String path, @Nonnull final LayoutType type, @Nonnull final TypeArgumentList typeArgs) { + + final LayoutColumn column = new LayoutColumn( + path, type, typeArgs, StorageKind.SPARSE, this.parent(), this.sparseCount, -1, LayoutBit.INVALID, + LayoutBit.INVALID, 0); + + this.sparseCount++; + this.sparseColumns.add(column); + } + + public void addVariableColumn(String path, LayoutType type, int length) { + + checkNotNull(path, "expected non-null path"); + checkNotNull(type, "expected non-null type"); + checkArgument(length >= 0); + checkArgument(type.allowVariable()); + + final LayoutColumn column = new LayoutColumn( + path, type, TypeArgumentList.EMPTY, StorageKind.VARIABLE, this.parent(), this.varCount, this.varCount, + this.bitAllocator.allocate(), LayoutBit.INVALID, length); + + this.varCount++; + this.varColumns.add(column); + } + + public Layout build() { + // Compute offset deltas. Offset bools by the present byte count, and fixed fields by the sum of the present + // and bool count. + int fixedDelta = this.bitAllocator.numBytes(); + int varIndexDelta = this.fixedCount; + + // Update the fixedColumns with the delta before freezing them. + ArrayList updatedColumns = + new ArrayList(this.fixedColumns.size() + this.varColumns.size()); + + for (LayoutColumn column : this.fixedColumns) { + column.offset(column.offset() + fixedDelta); + updatedColumns.add(column); + } + + for (LayoutColumn column : this.varColumns) { + // Adjust variable column indexes such that they begin immediately following the last fixed column. + column.index(column.index() + varIndexDelta); + updatedColumns.add(column); + } + + updatedColumns.addAll(this.sparseColumns); + + Layout layout = new Layout(this.name, this.schemaId, this.bitAllocator.numBytes(), this.fixedSize + fixedDelta, updatedColumns); + this.reset(); + return layout; + } + + public void EndObjectScope() { + checkArgument(this.scope.size() > 0); + this.scope.pop(); + } + + private LayoutColumn parent() { + if (this.scope.empty()) { + return null; + } + + return this.scope.peek(); + } + + private void reset() { + this.bitAllocator = new LayoutBit.Allocator(); + this.fixedSize = 0; + this.fixedCount = 0; + this.fixedColumns = new ArrayList(); + this.varCount = 0; + this.varColumns = new ArrayList(); + this.sparseCount = 0; + this.sparseColumns = new ArrayList(); + this.scope = new Stack(); + } +} \ 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 new file mode 100644 index 0000000..5afc92f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCode.java @@ -0,0 +1,119 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.bytes.Byte2ReferenceMap; +import it.unimi.dsi.fastutil.bytes.Byte2ReferenceOpenHashMap; + +import javax.annotation.Nullable; +import java.util.function.Supplier; + +/** + * Type coded used in the binary encoding to indicate the formatting of succeeding bytes. + */ +public enum LayoutCode { + + INVALID((byte)0), + + NULL((byte)1), + + BOOLEAN_FALSE((byte)2), + BOOLEAN((byte)3), + + INT_8((byte)5), + INT_16((byte)6), + INT_32((byte)7), + INT_64((byte)8), + UINT_8((byte)9), + UINT_16((byte)10), + UINT_32((byte)11), + UINT_64((byte)12), + VAR_INT((byte)13), + VAR_UINT((byte)14), + + FLOAT_32((byte)15), + FLOAT_64((byte)16), + DECIMAL((byte)17), + + DATE_TIME((byte)18), + GUID((byte)19), + + UTF_8((byte)20), + BINARY((byte)21), + + FLOAT_128((byte)22), + UNIX_DATE_TIME((byte)23), + MONGODB_OBJECT_ID((byte)24), + + OBJECT_SCOPE((byte)30), + IMMUTABLE_OBJECT_SCOPE((byte)31), + + ARRAY_SCOPE((byte)32), + IMMUTABLE_ARRAY_SCOPE((byte)33), + + TYPED_ARRAY_SCOPE((byte)34), + IMMUTABLE_TYPED_ARRAY_SCOPE((byte)35), + + TUPLE_SCOPE((byte)36), + IMMUTABLE_TUPLE_SCOPE((byte)37), + + TYPED_TUPLE_SCOPE((byte)38), + IMMUTABLE_TYPED_TUPLE_SCOPE((byte)39), + + MAP_SCOPE((byte)40), + IMMUTABLE_MAP_SCOPE((byte)41), + + TYPED_MAP_SCOPE((byte)42), + IMMUTABLE_TYPED_MAP_SCOPE((byte)43), + + SET_SCOPE((byte)44), + IMMUTABLE_SET_SCOPE((byte)45), + + TYPED_SET_SCOPE((byte)46), + IMMUTABLE_TYPED_SET_SCOPE((byte)47), + + NULLABLE_SCOPE((byte)48), + IMMUTABLE_NULLABLE_SCOPE((byte)49), + + TAGGED_SCOPE((byte)50), + IMMUTABLE_TAGGED_SCOPE((byte)51), + + TAGGED2_SCOPE((byte)52), + IMMUTABLE_TAGGED2_SCOPE((byte)53), + + /** + * Nested row. + */ + SCHEMA((byte)68), + IMMUTABLE_SCHEMA((byte)69), + + END_SCOPE((byte)70); + + public static final int BYTES = Byte.BYTES; + + 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); + }); + + private final byte value; + + LayoutCode(final byte value) { + this.value = value; + } + + public byte value() { + return this.value; + } + + @Nullable + 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/LayoutCodeTraits.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCodeTraits.java new file mode 100644 index 0000000..055efc2 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCodeTraits.java @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +public final class LayoutCodeTraits { + /** + * {@code true} if the specified layout code indicates that an element type always requires a type code. + *

+ * When this method returns {@code true} it indicates that the element value is in the type code. + * + * @param code The element type code. + * @return {@code true} if the specified layout code indicates that an element type always requires a type code. + */ + public static boolean alwaysRequiresTypeCode(LayoutCode code) { + return (code == LayoutCode.BOOLEAN) || (code == LayoutCode.BOOLEAN_FALSE) || (code == LayoutCode.NULL); + } + + /** + * A canonicalized version of the specified layout code. + *

+ * Some codes (e.g. {@link LayoutCode#BOOLEAN} use multiple type codes to also encode values. This function converts + * actual value based code into the canonicalized type code for schema comparisons. + * + * @param code the code to canonicalize. + * @return a canonicalized version of the specified layout code. + */ + public static LayoutCode canonicalize(LayoutCode code) { + return (code == LayoutCode.BOOLEAN_FALSE) ? LayoutCode.BOOLEAN : code; + } + + /** + * Returns the same scope code without the immutable bit set. + * + * @param code The scope type code. + * @return the same scope code without the immutable bit set. + */ + public static LayoutCode clearImmutableBit(LayoutCode code) { + return LayoutCode.from((byte) (code.value() & 0xFE)); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutColumn.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutColumn.java new file mode 100644 index 0000000..60ff3c7 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutColumn.java @@ -0,0 +1,242 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.schemas.StorageKind; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.lenientFormat; + +public final class LayoutColumn { + + private final LayoutBit booleanBit; + private final Utf8String fullPath; + private final LayoutBit nullBit; + private final LayoutColumn parent; + private final Utf8String path; + private final int size; + private final StorageKind storage; + private final LayoutType type; + private final TypeArgument typeArg; + private final TypeArgumentList typeArgs; + + private int index; + private int offset; + + /** + * Initializes a new instance of the {@link LayoutColumn} class + * + * @param path The path to the field relative to parent scope. + * @param type Type of the field. + * @param typeArgs For types with generic parameters (e.g. {@link LayoutTuple}, the type parameters. + * @param storage Storage encoding of the field. + * @param parent The layout of the parent scope, if a nested column. + * @param index zero-based column index. + * @param offset zero-based Offset from beginning of serialization. + * @param nullBit zero-based index into the bit mask for the null bit. + * @param booleanBit For bool fields, zero-based index into the bit mask for the boolean value. + * @param length For variable length types the length, otherwise {@code 0}. + */ + public LayoutColumn( + @Nonnull final String path, @Nonnull final LayoutType type, @Nonnull final TypeArgumentList typeArgs, + @Nonnull final StorageKind storage, final LayoutColumn parent, int index, int offset, + @Nonnull final LayoutBit nullBit, @Nonnull final LayoutBit booleanBit, int length) { + + checkNotNull(path); + checkNotNull(type); + checkNotNull(typeArgs); + checkNotNull(storage); + checkNotNull(nullBit); + checkNotNull(booleanBit); + + this.path = Utf8String.transcodeUtf16(path); + this.fullPath = Utf8String.transcodeUtf16(fullPath(parent, path)); + this.type = type; + this.typeArgs = typeArgs; + this.typeArg = new TypeArgument(type, typeArgs); + this.storage = storage; + this.parent = parent; + this.index = index; + this.offset = offset; + this.nullBit = nullBit; + this.booleanBit = booleanBit; + this.size = this.typeArg().type().isFixed() ? type.size() : length; + } + + /** + * For boolean fields, the zero-based index into the bit mask for the boolean value. + * + * @return for boolean fields, the zero-based index into the bit mask for the boolean value. + */ + public @Nonnull LayoutBit booleanBit() { + return this.booleanBit; + } + + /** + * Full logical path of the field within the row. + *

+ * Paths are expressed in dotted notation: e.g. a relative {@link #path()} of 'b.c' within the scope 'a' yields a + * full path of 'a.b.c'. + * + * @return Full logical path of the field within the row. + */ + public @Nonnull Utf8String fullPath() { + return this.fullPath; + } + + /** + * Zero-based index of the column within the structure. + *

+ * This value also indicates which presence bit controls this column. + * + * @return Zero-based index of the column within the structure. + */ + public int index() { + return this.index; + } + + /** + * For nullable fields, the zero-based index into the bit mask for the null bit. + * + * @return For nullable fields, the zero-based index into the bit mask for the null bit. + */ + public @Nonnull LayoutBit nullBit() { + return this.nullBit; + } + + /** + * If {@link #storage()} equals {@link StorageKind#FIXED} then the byte offset to the field location. + *

+ * If {@link #storage()} equals {@link StorageKind#VARIABLE} then the zero-based index of the field from the + * beginning of the variable length segment. + *

+ * For all other values of {@link #storage()}, {@code offset} is ignored. + * + * @return If {@link #storage()} equals {@link StorageKind#FIXED} then the byte offset to the field location. + */ + public int offset() { + return this.offset; + } + + /** + * Layout of the parent scope, if a nested column, otherwise {@code null}. + * + * @return Layout of the parent scope, if a nested column, otherwise {@code null}. + */ + public LayoutColumn parent() { + return this.parent; + } + + /** + * The relative path of the field within its parent scope. + *

+ * Paths are expressed in dotted notation: e.g. a relative {@link #path} of 'b.c' within the scope 'a' yields a + * {@link #fullPath} of 'a.b.c'. + * + * @return the relative path of the field within its parent scope. + */ + public @Nonnull Utf8String path() { + return this.path; + } + + /** + * If {@link LayoutType#isBoolean()} then the zero-based extra index within the boolean byte holding the value of + * this type, otherwise must be 0. + * + * @return If {@link LayoutType#isBoolean()} then the zero-based extra index within the boolean byte holding the + * value of this type, otherwise must be 0. + */ + public int size() { + return this.size; + } + + /** + * The storage kind of the field. + * + * @return the storage kind of the field. + */ + public @Nonnull StorageKind storage() { + return this.storage; + } + + /** + * The physical layout type of the field. + * + * @return the physical layout type of the field. + */ + public @Nonnull LayoutType type() { + return this.type; + } + + /** + * The full logical type. + * + * @return the full logical type. + */ + public @Nonnull TypeArgument typeArg() { + return this.typeArg; + } + + /** + * For types with generic parameters (e.g. {@link LayoutTuple}, the type parameters. + * + * @return for types with generic parameters (e.g. {@link LayoutTuple}, the type parameters. + */ + public @Nonnull TypeArgumentList typeArgs() { + return this.typeArgs; + } + + /** + * The physical layout type of the field cast to the specified type. + * + * @param a type that implements {@code ILayoutType}. + * + * @return The physical layout type of the field cast to the specified type. + */ + @SuppressWarnings("unchecked") + public @Nonnull T typeAs() { + return (T) this.type().typeAs(); + } + + LayoutColumn index(int value) { + this.index = value; + return this; + } + + LayoutColumn offset(int value) { + this.offset = value; + return this; + } + + /** + * Computes the full logical path to the column. + * + * @param parent The layout of the parent scope, if a nested column, otherwise null. + * @param path The path to the field relative to parent scope. + * @return The full logical path. + */ + private static @Nonnull String fullPath(final LayoutColumn parent, @Nonnull final String path) { + + if (parent != null) { + switch (LayoutCodeTraits.clearImmutableBit(parent.type().layoutCode())) { + case OBJECT_SCOPE: + case SCHEMA: + return parent.fullPath().toString() + "." + path; + case ARRAY_SCOPE: + case TYPED_ARRAY_SCOPE: + case TYPED_SET_SCOPE: + case TYPED_MAP_SCOPE: + return parent.fullPath().toString() + "[]" + path; + default: + final String message = lenientFormat("Parent scope type not supported: %s", parent.type().layoutCode()); + throw new IllegalStateException(message); + } + } + + return path; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompilationException.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompilationException.java new file mode 100644 index 0000000..af0c639 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompilationException.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import java.io.Serializable; + +public final class LayoutCompilationException extends RuntimeException implements Serializable { + + public LayoutCompilationException() { + } + + public LayoutCompilationException(String message) { + super(message); + } + + public LayoutCompilationException(String message, RuntimeException cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompiler.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompiler.java new file mode 100644 index 0000000..97034f5 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutCompiler.java @@ -0,0 +1,433 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.ArrayPropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.MapPropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace; +import com.azure.data.cosmos.serialization.hybridrow.schemas.ObjectPropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.PrimitivePropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Property; +import com.azure.data.cosmos.serialization.hybridrow.schemas.PropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Schema; +import com.azure.data.cosmos.serialization.hybridrow.schemas.ScopePropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.SetPropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.TaggedPropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.TuplePropertyType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.TypeKind; +import com.azure.data.cosmos.serialization.hybridrow.schemas.UdtPropertyType; +import com.google.common.base.Strings; +import org.checkerframework.checker.index.qual.NonNegative; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.Optional; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.lenientFormat; + +/** + * Converts a logical schema into a physical layout. + */ +public final class LayoutCompiler { + /** + * Compiles a logical schema into a physical layout that can be used to read and write rows + * + * @param namespace The namespace within which {@code schema} is defined + * @param schema The logical schema to produce a layout for + * @return The layout for the schema + */ + @Nonnull + public static Layout compile(@Nonnull final Namespace namespace, @Nonnull final Schema schema) { + + checkNotNull(namespace, "expected non-null namespace"); + checkNotNull(schema, "expected non-null schema"); + checkArgument(schema.type() == TypeKind.SCHEMA); + checkArgument(!Strings.isNullOrEmpty(schema.name())); + checkArgument(namespace.schemas().contains(schema)); + + LayoutBuilder builder = new LayoutBuilder(schema.name(), schema.schemaId()); + LayoutCompiler.addProperties(builder, namespace, LayoutCode.SCHEMA, schema.properties()); + + return builder.build(); + } + + private static void addProperties( + @Nonnull final LayoutBuilder builder, + @Nonnull final Namespace namespace, + @Nonnull LayoutCode layoutCode, + @Nonnull List properties) { + + final Out typeArgs = new Out<>(); + + for (Property p : properties) { + + LayoutType type = LayoutCompiler.logicalToPhysicalType(namespace, p.type(), typeArgs); + + switch (LayoutCodeTraits.clearImmutableBit(type.layoutCode())) { + + case OBJECT_SCOPE: { + if (!p.type().nullable()) { + throw new LayoutCompilationException("Non-nullable sparse column are not supported."); + } + ObjectPropertyType op = (ObjectPropertyType)p.type(); + builder.addObjectScope(p.path(), type); + LayoutCompiler.addProperties(builder, namespace, type.layoutCode(), op.properties()); + builder.EndObjectScope(); + break; + } + + case ARRAY_SCOPE: + case TYPED_ARRAY_SCOPE: + case SET_SCOPE: + case TYPED_SET_SCOPE: + case MAP_SCOPE: + case TYPED_MAP_SCOPE: + case TUPLE_SCOPE: + case TYPED_TUPLE_SCOPE: + case TAGGED_SCOPE: + case TAGGED2_SCOPE: + case SCHEMA: { + if (!p.type().nullable()) { + throw new LayoutCompilationException("Non-nullable sparse column are not supported."); + } + builder.addTypedScope(p.path(), type, typeArgs.get()); + break; + } + + case NULLABLE_SCOPE: { + throw new LayoutCompilationException("Nullables cannot be explicitly declared as columns."); + } + + default: { + + if (p.type() instanceof PrimitivePropertyType) { + + PrimitivePropertyType pp = (PrimitivePropertyType) p.type(); + + switch (pp.storage()) { + + case FIXED: + if (LayoutCodeTraits.clearImmutableBit(layoutCode) != LayoutCode.SCHEMA) { + throw new LayoutCompilationException( + "Cannot have fixed storage within a sparse layoutCode."); + } + if (type.isNull() && !pp.nullable()) { + throw new LayoutCompilationException( + "Non-nullable null columns are not supported."); + } + builder.addFixedColumn(p.path(), type, pp.nullable(), pp.length()); + break; + + case VARIABLE: + if (LayoutCodeTraits.clearImmutableBit(layoutCode) != LayoutCode.SCHEMA) { + throw new LayoutCompilationException( + "Cannot have variable storage within a sparse layoutCode."); + } + if (!pp.nullable()) { + throw new LayoutCompilationException( + "Non-nullable variable columns are not supported."); + } + builder.addVariableColumn(p.path(), type, pp.length()); + break; + + case SPARSE: + if (!pp.nullable()) { + throw new LayoutCompilationException( + "Non-nullable sparse columns are not supported."); + } + builder.addSparseColumn(p.path(), type); + break; + + default: + throw new LayoutCompilationException( + lenientFormat("Unknown storage specification: %s", pp.storage())); + } + } else { + throw new LayoutCompilationException( + lenientFormat("Unknown property type: %s", type.name())); + } + + break; + } + } + } + } + + private static LayoutType logicalToPhysicalType( + Namespace namespace, PropertyType logicalType, Out typeArgs) { + + typeArgs.set(TypeArgumentList.EMPTY); + boolean immutable = logicalType instanceof ScopePropertyType && ((ScopePropertyType) logicalType).immutable(); + + switch (logicalType.type()) { + + case NULL: + return LayoutTypes.NULL; + + case BOOLEAN: + return LayoutTypes.BOOLEAN; + + case INT_8: + return LayoutTypes.INT_8; + + case INT_16: + return LayoutTypes.INT_16; + + case INT_32: + return LayoutTypes.INT_32; + + case INT_64: + return LayoutTypes.INT_64; + + case UINT_8: + return LayoutTypes.UINT_8; + + case UINT_16: + return LayoutTypes.UINT_16; + + case UINT_32: + return LayoutTypes.UINT_32; + + case UINT_64: + return LayoutTypes.UINT_64; + + case FLOAT_32: + return LayoutTypes.FLOAT_32; + + case FLOAT_64: + return LayoutTypes.FLOAT_64; + + case FLOAT_128: + return LayoutTypes.FLOAT_128; + + case DECIMAL: + return LayoutTypes.DECIMAL; + + case DATE_TIME: + return LayoutTypes.DATE_TIME; + + case UNIX_DATE_TIME: + return LayoutTypes.UNIX_DATE_TIME; + + case GUID: + return LayoutTypes.GUID; + + case MONGODB_OBJECT_ID: + throw new UnsupportedOperationException(); + // return LayoutTypes.MONGO_DB_OBJECT_ID; + + case UTF_8: + return LayoutTypes.UTF_8; + + case BINARY: + return LayoutTypes.BINARY; + + case VAR_INT: + return LayoutTypes.VAR_INT; + + case VAR_UINT: + return LayoutTypes.VAR_UINT; + + case OBJECT: + return immutable ? LayoutTypes.IMMUTABLE_OBJECT : LayoutTypes.OBJECT; + + case ARRAY: { + + assert logicalType instanceof ArrayPropertyType; + ArrayPropertyType ap = (ArrayPropertyType) logicalType; + + if (ap.items() != null && (ap.items().type() != TypeKind.ANY)) { + + final Out out = new Out<>(); + + LayoutType itemType = LayoutCompiler.logicalToPhysicalType(namespace, ap.items(), out); + TypeArgumentList itemTypeArgs = out.get(); + + if (ap.items().nullable()) { + itemTypeArgs = new TypeArgumentList(new TypeArgument(itemType, itemTypeArgs)); + itemType = itemType.isImmutable() ? LayoutTypes.IMMUTABLE_NULLABLE : LayoutTypes.NULLABLE; + } + + typeArgs.set(new TypeArgumentList(new TypeArgument(itemType, itemTypeArgs))); + return immutable ? LayoutTypes.IMMUTABLE_TYPED_ARRAY : LayoutTypes.TYPED_ARRAY; + } + + return immutable ? LayoutTypes.IMMUTABLE_ARRAY : LayoutTypes.ARRAY; + } + case SET: { + + assert logicalType instanceof SetPropertyType; + SetPropertyType sp = (SetPropertyType) logicalType; + + if ((sp.items() != null) && (sp.items().type() != TypeKind.ANY)) { + + final Out out = new Out<>(); + + LayoutType itemType = LayoutCompiler.logicalToPhysicalType(namespace, sp.items(), out); + TypeArgumentList itemTypeArgs = out.get(); + + if (sp.items().nullable()) { + itemTypeArgs = new TypeArgumentList(new TypeArgument(itemType, itemTypeArgs)); + itemType = itemType.isImmutable() ? LayoutTypes.IMMUTABLE_NULLABLE : LayoutTypes.NULLABLE; + } + + typeArgs.set(new TypeArgumentList(new TypeArgument(itemType, itemTypeArgs))); + return immutable ? LayoutTypes.IMMUTABLE_TYPED_SET : LayoutTypes.TYPED_SET; + } + + // TODO(283638): implement sparse set + + throw new LayoutCompilationException(lenientFormat( + "Unknown property type: %s", + logicalType.type() + )); + } + case MAP: { + + assert logicalType instanceof MapPropertyType; + MapPropertyType mp = (MapPropertyType) logicalType; + + if (mp.keys() != null && (mp.keys().type() != TypeKind.ANY) && (mp.values() != null) && (mp.values().type() != TypeKind.ANY)) { + + final Out out = new Out<>(); + + LayoutType keyType = LayoutCompiler.logicalToPhysicalType(namespace, mp.keys(), out); + TypeArgumentList keyTypeArgs = out.get(); + + if (mp.keys().nullable()) { + keyTypeArgs = new TypeArgumentList(new TypeArgument(keyType, keyTypeArgs)); + keyType = keyType.isImmutable() ? LayoutTypes.IMMUTABLE_NULLABLE : LayoutTypes.NULLABLE; + } + + LayoutType valueType = LayoutCompiler.logicalToPhysicalType(namespace, mp.values(), out); + TypeArgumentList valueTypeArgs = out.get(); + + if (mp.values().nullable()) { + valueTypeArgs = new TypeArgumentList(new TypeArgument(valueType, valueTypeArgs)); + valueType = valueType.isImmutable() ? LayoutTypes.IMMUTABLE_NULLABLE : LayoutTypes.NULLABLE; + } + + typeArgs.set(new TypeArgumentList( + new TypeArgument(keyType, keyTypeArgs), + new TypeArgument(valueType, valueTypeArgs) + )); + + return immutable ? LayoutTypes.IMMUTABLE_TYPED_MAP : LayoutTypes.TYPED_MAP; + } + + // TODO(283638): implement sparse map + + throw new LayoutCompilationException(lenientFormat( + "Unknown property type: %s", logicalType.type()) + ); + } + case TUPLE: { + + assert logicalType instanceof TuplePropertyType; + final TuplePropertyType tp = (TuplePropertyType) logicalType; + + final TypeArgument[] args = new TypeArgument[tp.items().size()]; + final Out out = new Out<>(); + + for (int i = 0; i < tp.items().size(); i++) { + + LayoutType itemType = LayoutCompiler.logicalToPhysicalType(namespace, tp.items().get(i), out); + TypeArgumentList itemTypeArgs = out.get(); + + if (tp.items().get(i).nullable()) { + itemTypeArgs = new TypeArgumentList(new TypeArgument(itemType, itemTypeArgs)); + itemType = itemType.isImmutable() ? LayoutTypes.IMMUTABLE_NULLABLE : LayoutTypes.NULLABLE; + } + + args[i] = new TypeArgument(itemType, itemTypeArgs); + } + + typeArgs.setAndGet(new TypeArgumentList(args)); + return immutable ? LayoutTypes.IMMUTABLE_TYPED_TUPLE : LayoutTypes.TYPED_TUPLE; + } + case TAGGED: { + + assert logicalType instanceof TaggedPropertyType; + TaggedPropertyType tg = (TaggedPropertyType) logicalType; + + if (tg.items().size() < TaggedPropertyType.MIN_TAGGED_ARGUMENTS || (tg.items().size() > TaggedPropertyType.MAX_TAGGED_ARGUMENTS)) { + throw new LayoutCompilationException(lenientFormat( + "Invalid number of arguments in Tagged: %s <= %s <= %s", + TaggedPropertyType.MIN_TAGGED_ARGUMENTS, + tg.items().size(), + TaggedPropertyType.MAX_TAGGED_ARGUMENTS + )); + } + + final Out out = new Out<>(); + final TypeArgument[] tgArgs = new TypeArgument[tg.items().size() + 1]; + + tgArgs[0] = new TypeArgument(LayoutTypes.UINT_8, TypeArgumentList.EMPTY); + + for (int i = 0; i < tg.items().size(); i++) { + + LayoutType itemType = LayoutCompiler.logicalToPhysicalType(namespace, tg.items().get(i), out); + TypeArgumentList itemTypeArgs = out.get(); + + if (tg.items().get(i).nullable()) { + itemTypeArgs = new TypeArgumentList(new TypeArgument(itemType, itemTypeArgs)); + itemType = itemType.isImmutable() ? LayoutTypes.IMMUTABLE_NULLABLE : LayoutTypes.NULLABLE; + } + + tgArgs[i + 1] = new TypeArgument(itemType, itemTypeArgs); + } + + typeArgs.set(new TypeArgumentList(tgArgs)); + + switch (tg.items().size()) { + case 1: + return immutable ? LayoutTypes.IMMUTABLE_TAGGED : LayoutTypes.TAGGED; + case 2: + return immutable ? LayoutTypes.IMMUTABLE_TAGGED_2 : LayoutTypes.TAGGED_2; + default: + throw new LayoutCompilationException("Unexpected tagged arity"); + } + } + case SCHEMA: { + + assert logicalType instanceof UdtPropertyType; + UdtPropertyType up = (UdtPropertyType) logicalType; + + final Optional udtSchema; + + if (up.schemaId() == SchemaId.NONE) { + udtSchema = namespace.schemas().stream() + .filter(schema -> up.name().equals(schema.name())) + .findFirst(); + } else { + udtSchema = namespace.schemas().stream() + .filter(schema -> up.schemaId().equals(schema.schemaId())) + .findFirst(); + if (udtSchema.isPresent() && !up.name().equals(udtSchema.get().name())) { + throw new LayoutCompilationException(lenientFormat( + "ambiguous schema reference: '%s:%s'", up.name(), up.schemaId() + )); + } + } + + if (!udtSchema.isPresent()) { + throw new LayoutCompilationException(lenientFormat( + "cannot resolve schema reference '%s:%s'", up.name(), up.schemaId() + )); + } + + typeArgs.set(new TypeArgumentList(udtSchema.get().schemaId())); + return immutable ? LayoutTypes.IMMUTABLE_UDT : LayoutTypes.UDT; + } + default: + throw new LayoutCompilationException(Strings.lenientFormat( + "Unknown property type: %s", logicalType.type() + )); + } + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java new file mode 100644 index 0000000..533e1b9 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDateTime.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.codecs.DateTimeCodec; + +import javax.annotation.Nonnull; +import java.time.OffsetDateTime; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutDateTime extends LayoutTypePrimitive { + + public LayoutDateTime() { + super(LayoutCode.DATE_TIME, DateTimeCodec.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "datetime"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(OffsetDateTime.MIN); + return Result.NOT_FOUND; + } + + value.set(buffer.readDateTime(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(OffsetDateTime.MIN); + return result; + } + + value.set(buffer.readSparseDateTime(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull OffsetDateTime value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeDateTime(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull OffsetDateTime value, @Nonnull UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseDateTime(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull OffsetDateTime value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDecimal.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDecimal.java new file mode 100644 index 0000000..bb64aff --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutDecimal.java @@ -0,0 +1,92 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.codecs.DecimalCodec; + +import javax.annotation.Nonnull; +import java.math.BigDecimal; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutDecimal extends LayoutTypePrimitive { + + public LayoutDecimal() { + super(LayoutCode.DECIMAL, DecimalCodec.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "decimal"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.setAndGet(new BigDecimal(0)); + return Result.NOT_FOUND; + } + + value.setAndGet(buffer.readDecimal(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, + @Nonnull Out value) { + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + if (result != Result.SUCCESS) { + value.setAndGet(new BigDecimal(0)); + return result; + } + + value.setAndGet(buffer.readSparseDecimal(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, + @Nonnull BigDecimal value) { + checkArgument(scope.scopeType() instanceof LayoutUDT); + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeDecimal(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull BigDecimal value, @Nonnull UpdateOptions options) { + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseDecimal(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull BigDecimal value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutEndScope.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutEndScope.java new file mode 100644 index 0000000..3e89f8f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutEndScope.java @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +public final class LayoutEndScope extends LayoutTypeScope { + + public LayoutEndScope() { + super(LayoutCode.END_SCOPE, false, false, false, false, false, false); + } + + @Nonnull + public String name() { + return "end"; + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, scope, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + assert false : "cannot write an EndScope directly"; + value.set(null); + + return Result.FAILURE; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat128.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat128.java new file mode 100644 index 0000000..9f5e88d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat128.java @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Float128; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutFloat128 extends LayoutTypePrimitive { + + public LayoutFloat128() { + super(LayoutCode.FLOAT_128, Float128.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "float128"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.setAndGet(null); + return Result.NOT_FOUND; + } + + value.setAndGet(buffer.readFloat128(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.setAndGet(null); + return result; + } + + value.setAndGet(buffer.readSparseFloat128(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Float128 value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeFloat128(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Float128 value, @Nonnull UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseFloat128(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Float128 value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat32.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat32.java new file mode 100644 index 0000000..7da5f10 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat32.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutFloat32 extends LayoutTypePrimitive { + + public LayoutFloat32() { + super(LayoutCode.FLOAT_32, Float.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "float32"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0F); + return Result.NOT_FOUND; + } + + value.set(buffer.readFloat32(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0F); + return result; + } + + value.set(buffer.readSparseFloat32(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Float value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeFloat32(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Float value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseFloat32(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Float value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat64.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat64.java new file mode 100644 index 0000000..6cfb1ca --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutFloat64.java @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutFloat64 extends LayoutTypePrimitive { + + public LayoutFloat64() { + super(LayoutCode.FLOAT_64, Double.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "float64"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0D); + return Result.NOT_FOUND; + } + + value.set(buffer.readFloat64(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0D); + return result; + } + + value.set(buffer.readSparseFloat64(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn col, @Nonnull Double value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeFloat64(scope.start() + col.offset(), value); + buffer.setBit(scope.start(), col.nullBit()); + return Result.SUCCESS; + } + + //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: + //ORIGINAL LINE: public override Result WriteSparse(ref RowBuffer b, ref RowCursor edit, double value, + // UpdateOptions options = UpdateOptions.Upsert) + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Double value, @Nonnull UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseFloat64(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Double value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java new file mode 100644 index 0000000..dbbd165 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutGuid.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.codecs.GuidCodec; + +import javax.annotation.Nonnull; +import java.util.UUID; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutGuid extends LayoutTypePrimitive { + + public LayoutGuid() { + super(LayoutCode.GUID, GuidCodec.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "guid"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(null); + return Result.NOT_FOUND; + } + + value.set(buffer.readGuid(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.readSparseGuid(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull UUID value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeGuid(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull UUID value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseGuid(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull UUID value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutIndexedScope.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutIndexedScope.java new file mode 100644 index 0000000..ff14a51 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutIndexedScope.java @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class LayoutIndexedScope extends LayoutTypeScope { + + protected LayoutIndexedScope( + @Nonnull final LayoutCode code, + final boolean immutable, + final boolean isSizedScope, + final boolean isFixedArity, + final boolean isUniqueScope, + final boolean isTypedScope) { + super(code, immutable, isSizedScope, true, isFixedArity, isUniqueScope, isTypedScope); + } + + @Override + public void readSparsePath(@Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit) { + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + edit.pathToken(0); + edit.pathOffset(0); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt16.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt16.java new file mode 100644 index 0000000..9f806e4 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt16.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutInt16 extends LayoutTypePrimitive { + + public LayoutInt16() { + super(LayoutCode.INT_16, Short.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "int16"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set((short) 0); + return Result.NOT_FOUND; + } + + value.set(buffer.readInt16(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set((short) 0); + return result; + } + + value.set(buffer.readSparseInt16(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Short value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeInt16(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Short value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseInt16(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Short value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt32.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt32.java new file mode 100644 index 0000000..83c5578 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt32.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutInt32 extends LayoutTypePrimitive { + + public LayoutInt32() { + super(LayoutCode.INT_32, Integer.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "int32"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0); + return Result.NOT_FOUND; + } + + value.set(buffer.readInt32(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0); + return result; + } + + value.set(buffer.readSparseInt32(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Integer value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeInt32(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Integer value, @Nonnull UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseInt32(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Integer value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt64.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt64.java new file mode 100644 index 0000000..815a97d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt64.java @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutInt64 extends LayoutTypePrimitive { + + public LayoutInt64() { + super(LayoutCode.INT_64, Long.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "int64"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0L); + return Result.NOT_FOUND; + } + + value.set(buffer.readInt64(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0L); + return result; + } + + value.set(buffer.readSparseInt64(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Long value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeInt64(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value, @Nonnull UpdateOptions options) { + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseInt64(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt8.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt8.java new file mode 100644 index 0000000..cf49e1f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutInt8.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutInt8 extends LayoutTypePrimitive { + + public LayoutInt8() { + super(LayoutCode.INT_8, Byte.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "int8"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set((byte) 0); + return Result.NOT_FOUND; + } + + value.set(buffer.readInt8(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set((byte) 0); + return result; + } + + value.set(buffer.readSparseInt8(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Byte value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeInt8(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Byte value, @Nonnull UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseInt8(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Byte value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListReadable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListReadable.java new file mode 100644 index 0000000..be03f88 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListReadable.java @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import java.util.List; + +/** + * An optional interface that indicates a {@link LayoutType} can also read using a read-only {@link List} + * + * @param The sub-element type to be written + */ +public interface LayoutListReadable extends ILayoutType { + + Result readFixedList(RowBuffer buffer, RowCursor scope, LayoutColumn column, Out> value); + + Result readSparseList(RowBuffer buffer, RowCursor scope, Out> value); + + Result readVariableList(RowBuffer buffer, RowCursor scope, LayoutColumn column, Out> value); +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListWritable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListWritable.java new file mode 100644 index 0000000..bcacbcc --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutListWritable.java @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import java.util.List; + +/** + * An optional interface that indicates a {@link LayoutType} can also write using a {@link List} + * + * @param The sub-element type to be written + */ +public interface LayoutListWritable extends ILayoutType { + + Result writeFixedList(RowBuffer buffer, RowCursor scope, LayoutColumn column, List value); + + Result writeSparseList(RowBuffer buffer, RowCursor edit, TElement value); + + Result writeSparseList(RowBuffer buffer, RowCursor edit, List value, UpdateOptions options); + + Result writeVariableList(RowBuffer buffer, RowCursor scope, LayoutColumn column, List value); +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutMongoDbObjectId.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutMongoDbObjectId.java new file mode 100644 index 0000000..8652838 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutMongoDbObjectId.java @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import javax.annotation.Nonnull; + +public final class LayoutMongoDbObjectId extends LayoutType/**/ { + + public LayoutMongoDbObjectId() { + super(LayoutCode.MONGODB_OBJECT_ID, 0/*MongoDbObjectId.Size*/); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "mongodbobjectid"; + } + + // TODO: DANOBLE: Ressurect this class implementation +// @Override +// @Nonnull +// public Result readFixed( +// RowBuffer buffer, RowCursor scope, LayoutColumn column, Out value) { +// checkArgument(scope.get().scopeType() instanceof LayoutUDT); +// if (!buffer.get().readBit(scope.get().start(), column.getNullBit().clone())) { +// value.setAndGet(null); +// return Result.NOT_FOUND; +// } +// +// value.setAndGet(buffer.get().ReadMongoDbObjectId(scope.get().start() + column.getOffset()).clone()); +// return Result.SUCCESS; +// } +// +// @Override +// @Nonnull +// public Result readSparse(RowBuffer buffer, RowCursor edit, +// Out value) { +// Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); +// if (result != Result.SUCCESS) { +// value.setAndGet(null); +// return result; +// } +// +// value.setAndGet(buffer.get().ReadSparseMongoDbObjectId(edit).clone()); +// return Result.SUCCESS; +// } +// +// @Override +// @Nonnull +// public Result writeFixed(RowBuffer buffer, RowCursor scope, LayoutColumn column, +// MongoDbObjectId value) { +// checkArgument(scope.get().scopeType() instanceof LayoutUDT); +// if (scope.get().immutable()) { +// return Result.INSUFFICIENT_PERMISSIONS; +// } +// +// buffer.get().WriteMongoDbObjectId(scope.get().start() + column.getOffset(), value.clone()); +// buffer.get().SetBit(scope.get().start(), column.getNullBit().clone()); +// return Result.SUCCESS; +// } +// +// //C# TO JAVA CONVERTER NOTE: Java does not support optional parameters. Overloaded method(s) are created above: +// //ORIGINAL LINE: public override Result WriteSparse(ref RowBuffer b, ref RowCursor edit, MongoDbObjectId value, +// // UpdateOptions options = UpdateOptions.Upsert) +// @Override +// @Nonnull +// public Result writeSparse(RowBuffer buffer, RowCursor edit, +// MongoDbObjectId value, UpdateOptions options) { +// Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg().clone(), options); +// if (result != Result.SUCCESS) { +// return result; +// } +// +// buffer.get().WriteSparseMongoDbObjectId(edit, value.clone(), options); +// return Result.SUCCESS; +// } +// +// @Override +// @Nonnull +// public Result writeSparse(RowBuffer buffer, RowCursor edit, +// MongoDbObjectId value) { +// return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); +// } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNull.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNull.java new file mode 100644 index 0000000..3a22ff2 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNull.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.NullValue; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutNull extends LayoutTypePrimitive implements ILayoutType { + + public LayoutNull() { + super(LayoutCode.NULL, 0); + } + + public boolean isFixed() { + return true; + } + + public boolean isNull() { + return true; + } + + @Nonnull + public String name() { + return "null"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + checkArgument(scope.scopeType() instanceof LayoutUDT); + value.set(NullValue.DEFAULT); + if (!buffer.readBit(scope.start(), column.nullBit())) { + return Result.NOT_FOUND; + } + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + value.set(buffer.readSparseNull(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull NullValue value) { + checkArgument(scope.scopeType() instanceof LayoutUDT); + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull NullValue value, @Nonnull UpdateOptions options) { + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + if (result != Result.SUCCESS) { + return result; + } + buffer.writeSparseNull(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull NullValue value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java new file mode 100644 index 0000000..73f6771 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutNullable.java @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class LayoutNullable extends LayoutIndexedScope { + + public LayoutNullable(boolean immutable) { + super( + immutable ? LayoutCode.IMMUTABLE_NULLABLE_SCOPE : LayoutCode.NULLABLE_SCOPE, immutable, + true, true, false, true + ); + } + + @Override + public int countTypeArgument(@Nonnull final TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + checkArgument(value.count() == 1); + return LayoutCode.BYTES + value.get(0).type().countTypeArgument(value.get(0).typeArgs()); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_nullable" : "nullable"; + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + checkArgument(edit.index() >= 0); + checkArgument(edit.scopeTypeArgs().count() == 1); + checkArgument(edit.index() == 1); + return !LayoutCodeTraits.alwaysRequiresTypeCode(edit.scopeTypeArgs().get(0).type().layoutCode()); + } + + public static Result hasValue(@Nonnull final RowBuffer buffer, @Nonnull final RowCursor scope) { + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkArgument(scope.scopeType() instanceof LayoutNullable); + checkArgument(scope.index() == 1 || scope.index() == 2); + checkArgument(scope.scopeTypeArgs().count() == 1); + boolean hasValue = buffer.readInt8(scope.start()) != 0; + return hasValue ? Result.SUCCESS : Result.NOT_FOUND; + } + + @Nonnull + @Override + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + return new TypeArgumentList(LayoutType.readTypeArgument(buffer, offset, lengthInBytes)); + } + + @Override + public void setImplicitTypeCode(@Nonnull RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + checkState(edit.index() == 1); + edit.cellType(edit.scopeTypeArgs().get(0).type()); + edit.cellTypeArgs(edit.scopeTypeArgs().get(0).typeArgs()); + } + + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + boolean hasValue, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, hasValue, UpdateOptions.UPSERT, value); + } + + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + boolean hasValue, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + Result result = LayoutType.prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + buffer.writeNullable(edit, this, typeArgs, options, hasValue); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, true, options, value); + } + + @Override + public int writeTypeArgument(@Nonnull final RowBuffer buffer, int offset, @Nonnull final TypeArgumentList value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(value, "expected non-null value"); + checkArgument(offset >= 0); + checkArgument(value.count() == 1); + + final TypeArgument typeArg = value.get(0); + buffer.writeSparseTypeCode(offset, this.layoutCode()); + return LayoutCode.BYTES + typeArg.type().writeTypeArgument(buffer, offset + LayoutCode.BYTES, typeArg.typeArgs()); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutObject.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutObject.java new file mode 100644 index 0000000..7b265a5 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutObject.java @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutObject extends LayoutPropertyScope { + + private TypeArgument typeArg; + + public LayoutObject(boolean immutable) { + super(immutable ? LayoutCode.IMMUTABLE_OBJECT_SCOPE : LayoutCode.OBJECT_SCOPE, immutable); + this.typeArg = new TypeArgument(this); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_object" : "object"; + } + + public TypeArgument typeArg() { + return this.typeArg; + } + + + @Override + @Nonnull + public Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull TypeArgumentList typeArgs, @Nonnull Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull TypeArgumentList typeArgs, + @Nonnull UpdateOptions options, @Nonnull Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + value.setAndGet(null); + return result; + } + + value.set(buffer.writeSparseObject(edit, this, options)); + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutPropertyScope.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutPropertyScope.java new file mode 100644 index 0000000..c285886 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutPropertyScope.java @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +public abstract class LayoutPropertyScope extends LayoutTypeScope { + protected LayoutPropertyScope(LayoutCode code, boolean immutable) { + super(code, immutable, false, false, false, false, false); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolver.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolver.java new file mode 100644 index 0000000..04b846d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolver.java @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; + +import javax.annotation.Nonnull; + +public abstract class LayoutResolver { + @Nonnull + public abstract Layout resolve(@Nonnull SchemaId schemaId); +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverNamespace.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverNamespace.java new file mode 100644 index 0000000..4e8e96b --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverNamespace.java @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Schema; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.concurrent.ConcurrentHashMap; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +/** + * An implementation of {@link LayoutResolver} which dynamically compiles schema from a {@link Namespace}. + *

+ * This resolver assumes that {@link Schema} within the {@link Namespace} have their {@link Schema#schemaId()} properly + * populated. The resolver caches compiled schema. + *

+ * All members of this class are multi-thread safe. + */ +public final class LayoutResolverNamespace extends LayoutResolver { + + private final ConcurrentHashMap layoutCache; + private final LayoutResolver parent; + private final Namespace schemaNamespace; + + public LayoutResolverNamespace(@Nonnull final Namespace namespace) { + this(namespace, null); + } + + public LayoutResolverNamespace(@Nonnull final Namespace schemaNamespace, @Nullable final LayoutResolver parent) { + checkNotNull(schemaNamespace, "expected non-null schemaNamespace"); + this.schemaNamespace = schemaNamespace; + this.parent = parent; + this.layoutCache = new ConcurrentHashMap<>(); + } + + public Namespace namespace() { + return this.schemaNamespace; + } + + @Nonnull + @Override + public Layout resolve(@Nonnull SchemaId schemaId) { + + checkNotNull(schemaId, "expected non-null schemaId"); + + Layout layout = this.layoutCache.computeIfAbsent(schemaId, id -> { + for (Schema schema : this.namespace().schemas()) { + if (schema.schemaId().equals(id)) { + return schema.compile(this.schemaNamespace); + } + } + return this.parent == null ? null : this.parent.resolve(schemaId); + }); + + checkState(layout != null, "failed to resolve schema %s", schemaId); + return layout; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverSimple.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverSimple.java new file mode 100644 index 0000000..41917e4 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutResolverSimple.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; + +import javax.annotation.Nonnull; +import java.util.function.Function; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutResolverSimple extends LayoutResolver { + + private Function resolver; + + public LayoutResolverSimple(Function resolver) { + this.resolver = resolver; + } + + @Nonnull + @Override + public Layout resolve(@Nonnull SchemaId schemaId) { + checkNotNull(schemaId, "expected non-null schemaId"); + return this.resolver.apply(schemaId); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged.java new file mode 100644 index 0000000..d48c12e --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged.java @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.IMMUTABLE_TAGGED_SCOPE; +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.TAGGED_SCOPE; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutTagged extends LayoutIndexedScope { + + public LayoutTagged(boolean immutable) { + super(immutable ? IMMUTABLE_TAGGED_SCOPE : TAGGED_SCOPE, immutable, + true, true, false, true + ); + } + + @Override + public int countTypeArgument(@Nonnull final TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + checkArgument(value.count() == 2); + return LayoutCode.BYTES + value.get(1).type().countTypeArgument(value.get(1).typeArgs()); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_tagged_t" : "tagged_t"; + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + checkArgument(edit.index() >= 0); + checkArgument(edit.scopeTypeArgs().count() > edit.index()); + return !LayoutCodeTraits.alwaysRequiresTypeCode(edit.scopeTypeArgs().get(edit.index()).type().layoutCode()); + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + return new TypeArgumentList( + new TypeArgument(LayoutTypes.UINT_8, TypeArgumentList.EMPTY), + readTypeArgument(buffer, offset, lengthInBytes) + ); + } + + @Override + public void setImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + edit.cellType(edit.scopeTypeArgs().get(edit.index()).type()); + edit.cellTypeArgs(edit.scopeTypeArgs().get(edit.index()).typeArgs()); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, final @Nonnull Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + Result result = prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.writeTypedTuple(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final TypeArgumentList value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(value, "expected non-null value"); + checkArgument(value.count() == 2); + + buffer.writeSparseTypeCode(offset, this.layoutCode()); + final TypeArgument typeArg = value.get(1); + int lengthInBytes = LayoutCode.BYTES; + lengthInBytes += typeArg.type().writeTypeArgument(buffer, offset + lengthInBytes, typeArg.typeArgs()); + + return lengthInBytes; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged2.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged2.java new file mode 100644 index 0000000..fc321bc --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTagged2.java @@ -0,0 +1,131 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class LayoutTagged2 extends LayoutIndexedScope { + + public LayoutTagged2(boolean immutable) { + super( + immutable ? LayoutCode.IMMUTABLE_TAGGED2_SCOPE : LayoutCode.TAGGED2_SCOPE, immutable, + true, true, false, true + ); + } + + @Override + public int countTypeArgument(@Nonnull TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + checkState(value.count() == 3); + return value.stream() + .map(arg -> arg.type().countTypeArgument(arg.typeArgs())) + .reduce(LayoutCode.BYTES, Integer::sum); + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + checkState(edit.index() >= 0); + checkState(edit.scopeTypeArgs().count() > edit.index()); + return !LayoutCodeTraits.alwaysRequiresTypeCode(edit.scopeTypeArgs().get(edit.index()).type().layoutCode()); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_tagged2_t" : "tagged2_t"; + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + final TypeArgument[] typeArgs = new TypeArgument[] { + new TypeArgument(LayoutTypes.UINT_8, TypeArgumentList.EMPTY), + null, + null }; + + final Out len = new Out<>(); + int sum = 0; + + for (int i = 1; i < 3; i++) { + typeArgs[i] = readTypeArgument(buffer, offset + sum, len); + sum += len.get(); + } + + lengthInBytes.set(sum); + return new TypeArgumentList(typeArgs); + } + + @Override + public void setImplicitTypeCode(@Nonnull RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + edit.cellType(edit.scopeTypeArgs().get(edit.index()).type()); + edit.cellTypeArgs(edit.scopeTypeArgs().get(edit.index()).typeArgs()); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull TypeArgumentList typeArgs, @Nonnull Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull TypeArgumentList typeArgs, + @Nonnull UpdateOptions options, @Nonnull Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + Result result = prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.writeTypedTuple(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument(@Nonnull RowBuffer buffer, int offset, @Nonnull TypeArgumentList value) { + + checkState(value.count() == 3); + + buffer.writeSparseTypeCode(offset, this.layoutCode()); + int lengthInBytes = LayoutCode.BYTES; + + for (int i = 1; i < value.count(); i++) { + TypeArgument arg = value.get(i); + lengthInBytes += arg.type().writeTypeArgument(buffer, offset + lengthInBytes, arg.typeArgs()); + } + + return lengthInBytes; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTuple.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTuple.java new file mode 100644 index 0000000..a9b71ea --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTuple.java @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.IMMUTABLE_TUPLE_SCOPE; +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.TUPLE_SCOPE; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutTuple extends LayoutIndexedScope { + + public LayoutTuple(boolean immutable) { + super( + immutable ? IMMUTABLE_TUPLE_SCOPE : TUPLE_SCOPE, + immutable, false, true, false, false + ); + } + + @Override + public int countTypeArgument(@Nonnull final TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + return value.stream() + .map(arg -> arg.type().countTypeArgument(arg.typeArgs())) + .reduce(LayoutCode.BYTES + RowBuffer.count7BitEncodedUInt(value.count()), Integer::sum); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_tuple" : "tuple"; + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + final int numTypeArgs = (int) buffer.readVariableUInt(offset, lengthInBytes); + final TypeArgument[] typeArgs = new TypeArgument[numTypeArgs]; + final Out len = new Out<>(); + + int sum = lengthInBytes.get(); + + for (int i = 0; i < numTypeArgs; i++) { + typeArgs[i] = readTypeArgument(buffer, offset + sum, len); + sum += len.get(); + } + + return new TypeArgumentList(typeArgs); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + Result result = prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.writeSparseTuple(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument(@Nonnull RowBuffer buffer, int offset, @Nonnull TypeArgumentList value) { + buffer.writeSparseTypeCode(offset, this.layoutCode()); + int lengthInBytes = LayoutCode.BYTES; + lengthInBytes += buffer.writeVariableUInt(offset + lengthInBytes, value.count()); + for (TypeArgument arg : value.list()) { + lengthInBytes += arg.type().writeTypeArgument(buffer, offset + lengthInBytes, arg.typeArgs()); + } + + return lengthInBytes; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java new file mode 100644 index 0000000..c567f6e --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutType.java @@ -0,0 +1,401 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Describes the physical byte layout of a hybrid row field of a specific physical type {@code T}. + *

+ * {@link LayoutType} provides methods for manipulating hybrid row fields of a particular type, and properties that + * describe the layout of fields of that type. + */ +public abstract class LayoutType /*implements ILayoutType*/ { + + private static final LayoutType[] codeIndex = new LayoutType[LayoutCode.END_SCOPE.value() + 1]; + + @JsonProperty + private final boolean immutable; + + @JsonProperty + private final LayoutCode layoutCode; + + @JsonProperty + private final int size; + + @JsonProperty + private final TypeArgument typeArg; + + /** + * Initializes a new instance of the {@link LayoutType} class. + * + * @param code the {@linkplain LayoutCode} layout code of the instance. + * @param immutable {@code true} if edits to fields with this layout type are prohibited. + * @param size size of fields with this layout type in bytes. + */ + protected LayoutType(@Nonnull final LayoutCode code, final boolean immutable, final int size) { + + checkNotNull(code, "expected non-null code"); + + this.immutable = immutable; + this.layoutCode = code; + this.size = size; + this.typeArg = new TypeArgument(this); + + codeIndex[code.value()] = this; + } + + /** + * Initializes a new instance of the {@link LayoutType} class. + * + * @param code the {@linkplain LayoutCode} layout code of the instance. + * @param size size of fields with this layout type in bytes. + */ + protected LayoutType(LayoutCode code, int size) { + this(code, false, size); + } + + /** + * {@code true} if this type is a boolean. + * + * @return {@code true} if this type is a boolean. + */ + public boolean isBoolean() { + return false; + } + + /** + * {@code true} if this type is always fixed length. + * + * @return {@code true} if this type is always fixed length. + */ + public abstract boolean isFixed(); + + /** + * {@code true} if this {@link LayoutType}'s nested fields cannot be updated individually. + *

+ * Instances of this {@link LayoutType} can still be replaced in their entirety. + * + * @return {@code true} if this {@link LayoutType}'s nested fields cannot be updated individually. + */ + public boolean isImmutable() { + return this.immutable; + } + + /** + * {@code true} if this type is a literal null. + * + * @return {@code true} if this type is a literal null. + */ + public boolean isNull() { + return false; + } + + /** + * {@code true} if this type is a variable-length encoded integer type (either signed or unsigned). + * + * @return {@code true} if this type is a variable-length encoded integer type (either signed or unsigned). + */ + public boolean isVarint() { + return false; + } + + /** + * {@code true} if this type can be used in the variable-length segment. + * + * @return {@code true} if this type can be used in the variable-length segment. + */ + public final boolean allowVariable() { + return !this.isFixed(); + } + + public int countTypeArgument(@Nonnull TypeArgumentList value) { + return LayoutCode.BYTES; + } + + @Nonnull + public static LayoutType fromLayoutCode(LayoutCode code) { + LayoutType type = LayoutType.codeIndex[code.value()]; + checkArgument(type != null, "unimplemented code: %s", code); + return type; + } + + /** + * The physical layout code used to represent the type within the serialization. + * + * @return the physical layout code used to represent the type within the serialization. + */ + @Nonnull + public LayoutCode layoutCode() { + return this.layoutCode; + } + + /** + * Human readable name of the type. + * + * @return human readable name of the type. + */ + @Nonnull + public abstract String name(); + + /** + * Helper for preparing the delete of a sparse field. + * + * @param buffer The row to delete from. + * @param edit The parent edit containing the field to delete. + * @param code The expected type of the field. + * @return Success if the delete is permitted, the error code otherwise. + */ + @Nonnull + public static Result prepareSparseDelete(RowBuffer buffer, RowCursor edit, LayoutCode code) { + + if (edit.scopeType().isFixedArity()) { + return Result.TYPE_CONSTRAINT; + } + + if (edit.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + if (edit.exists() && LayoutCodeTraits.canonicalize(edit.cellType().layoutCode()) != code) { + return Result.TYPE_MISMATCH; + } + + return Result.SUCCESS; + } + + /** + * Helper for preparing the move of a sparse field into an existing restricted edit. + * + * @param buffer The row to read from. + * @param destinationScope The parent set edit into which the field should be moved. + * @param destinationCode The expected type of the edit moving within. + * @param elementType The expected type of the elements within the edit. + * @param srcEdit The field to be moved. + * @param options The move options. + * @param dstEdit If successful, a prepared insertion cursor for the destination. + * @return Success if the move is permitted, the error code otherwise. + * The source field is delete if the move prepare fails with a destination error. + */ + @Nonnull + public static Result prepareSparseMove( + RowBuffer buffer, + RowCursor destinationScope, + LayoutTypeScope destinationCode, + TypeArgument elementType, + RowCursor srcEdit, + UpdateOptions options, + Out dstEdit) { + + checkArgument(destinationScope.scopeType() == destinationCode); + checkArgument(destinationScope.index() == 0, "Can only insert into a edit at the root"); + + // Prepare the delete of the source + Result result = LayoutType.prepareSparseDelete(buffer, srcEdit, elementType.type().layoutCode()); + + if (result != Result.SUCCESS) { + dstEdit.set(null); + return result; + } + + if (!srcEdit.exists()) { + dstEdit.set(null); + return Result.NOT_FOUND; + } + + if (destinationScope.immutable()) { + buffer.deleteSparse(srcEdit); + dstEdit.set(null); + return Result.INSUFFICIENT_PERMISSIONS; + } + + if (!srcEdit.cellTypeArgs().equals(elementType.typeArgs())) { + buffer.deleteSparse(srcEdit); + dstEdit.set(null); + return Result.TYPE_CONSTRAINT; + } + + if (options == UpdateOptions.INSERT_AT) { + buffer.deleteSparse(srcEdit); + dstEdit.set(null); + return Result.TYPE_CONSTRAINT; + } + + // Prepare the insertion at the destination. + dstEdit.set(buffer.prepareSparseMove(destinationScope, srcEdit)); + + if ((options == UpdateOptions.UPDATE) && (!dstEdit.get().exists())) { + buffer.deleteSparse(srcEdit); + dstEdit.set(null); + return Result.NOT_FOUND; + } + + if ((options == UpdateOptions.INSERT) && dstEdit.get().exists()) { + buffer.deleteSparse(srcEdit); + dstEdit.set(null); + return Result.EXISTS; + } + + return Result.SUCCESS; + } + + /** + * Helper for preparing the read of a sparse field. + * + * @param buffer The row to read from. + * @param edit The parent edit containing the field to read. + * @param code The expected type of the field. + * @return Success if the read is permitted, the error code otherwise. + */ + @Nonnull + public static Result prepareSparseRead( + @Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit, @Nonnull LayoutCode code) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(code, "expected non-null code"); + + if (!edit.exists()) { + return Result.NOT_FOUND; + } + + if (LayoutCodeTraits.canonicalize(edit.cellType().layoutCode()) != code) { + return Result.TYPE_MISMATCH; + } + + return Result.SUCCESS; + } + + /** + * Helper for preparing the write of a sparse field. + * + * @param buffer The row to write to. + * @param edit The cursor for the field to write. + * @param typeArg The (optional) type constraints. + * @param options The write options. + * @return Success if the write is permitted, the error code otherwise. + */ + @Nonnull + public static Result prepareSparseWrite( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgument typeArg, + @Nonnull final UpdateOptions options) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArg, "expected non-null typeArg"); + checkNotNull(options, "expected non-null options"); + + if (edit.immutable() || (edit.scopeType().isUniqueScope() && !edit.deferUniqueIndex())) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + if (edit.scopeType().isFixedArity() && !(edit.scopeType() instanceof LayoutNullable)) { + if ((edit.index() < edit.scopeTypeArgs().count()) && !typeArg.equals(edit.scopeTypeArgs().get(edit.index()))) { + return Result.TYPE_CONSTRAINT; + } + } else if (edit.scopeType() instanceof LayoutTypedMap) { + if (!((typeArg.type() instanceof LayoutTypedTuple) && typeArg.typeArgs().equals(edit.scopeTypeArgs()))) { + return Result.TYPE_CONSTRAINT; + } + } else if (edit.scopeType().isTypedScope() && !typeArg.equals(edit.scopeTypeArgs().get(0))) { + return Result.TYPE_CONSTRAINT; + } + + if ((options == UpdateOptions.INSERT_AT) && edit.scopeType().isFixedArity()) { + return Result.TYPE_CONSTRAINT; + } + + if ((options == UpdateOptions.INSERT_AT) && !edit.scopeType().isFixedArity()) { + edit.exists(false); // InsertAt never overwrites an existing item. + } + + if ((options == UpdateOptions.UPDATE) && (!edit.exists())) { + return Result.NOT_FOUND; + } + + if ((options == UpdateOptions.INSERT) && edit.exists()) { + return Result.EXISTS; + } + + return Result.SUCCESS; + } + + @Nonnull + public static TypeArgument readTypeArgument( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + LayoutType type = buffer.readSparseTypeCode(offset); + TypeArgumentList typeArgs = type.readTypeArgumentList(buffer, offset + LayoutCode.BYTES, lengthInBytes); + lengthInBytes.set(LayoutCode.BYTES + lengthInBytes.get()); + + return new TypeArgument(type, typeArgs); + } + + @Nonnull + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + lengthInBytes.set(0); + return TypeArgumentList.EMPTY; + } + + /** + * If fixed, the fixed size of the type's serialization in bytes, otherwise undefined. + * + * @return If fixed, the fixed size of the type's serialization in bytes, otherwise undefined. + */ + public int size() { + return this.size; + } + + /** + * Returns a string representation of the {@linkplain LayoutType layout type}. + * + * @return a string representation of the {@linkplain LayoutType layout type}. + */ + @Override + public String toString() { + return Json.toString(this); + } + + public TypeArgument typeArg() { + return this.typeArg; + } + + /** + * The physical layout type of the field cast to the specified type. + * + * @param a type that implements {@link ILayoutType}. + * @return the physical layout type of the field cast to the specified type. + */ + @SuppressWarnings("unchecked") + public final T typeAs() { + return (T) this; + } + + public int writeTypeArgument(@Nonnull final RowBuffer buffer, int offset, @Nonnull final TypeArgumentList value) { + buffer.writeSparseTypeCode(offset, this.layoutCode()); + return LayoutCode.BYTES; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypePrimitive.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypePrimitive.java new file mode 100644 index 0000000..21fb63c --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypePrimitive.java @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class LayoutTypePrimitive extends LayoutType implements ILayoutType { + /** + * Initializes a new instance of the {@link LayoutTypePrimitive} class. + * + * @param code the {@link LayoutCode} of this layout type. + * @param immutable indicates whether edits of instances fields with this layout type are permitted. + * @param size the size of fields with this layout type in bytes. + */ + protected LayoutTypePrimitive(@Nonnull LayoutCode code, boolean immutable, int size) { + super(code, immutable, size); + } + + /** + * Initializes a new instance of the {@link LayoutTypePrimitive} class. + * + * @param code the {@link LayoutCode} of this layout type. + * @param size the size of fields with this layout type in bytes. + */ + protected LayoutTypePrimitive(LayoutCode code, int size) { + super(code, size); + } + + // TODO: DANOBLE: move methods implemented by the C# code LayoutType to this type from LayoutType + // Also: + // * Convert LayoutType to a non-generic type (LayoutType, not LayoutType) + // * Ensure that all primitive types inherit from this type + + @Nonnull + public final Result hasValue( + @Nonnull final RowBuffer buffer, @Nonnull final RowCursor scope, @Nonnull final LayoutColumn column) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + return Result.NOT_FOUND; + } + return Result.SUCCESS; + } + + @Nonnull + public final Result deleteFixed( + @Nonnull final RowBuffer buffer, @Nonnull final RowCursor scope, @Nonnull final LayoutColumn column) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + if (column.nullBit().isInvalid()) { + // Cannot delete a non-nullable fixed column. + return Result.TYPE_MISMATCH; + } + + buffer.unsetBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + /** + * Delete an existing value. + *

+ * 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. + * + * @param buffer target {@link RowBuffer}. + * @param edit a {@link RowCursor} that identifies and locates the field to be deleted. + * @return {@link Result#SUCCESS} if the value was deleted; otherwise an error {@link Result}. + */ + @Nonnull + public final Result deleteSparse(RowBuffer buffer, RowCursor edit) { + + Result result = LayoutType.prepareSparseDelete(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.deleteSparse(edit); + return Result.SUCCESS; + } + + /** + * Delete an existing value. + *

+ * 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. + * + * @param buffer the target {@link RowBuffer}. + * @param scope a {@linkplain RowCursor cursor} that identifies and locates the scope of the deletion. + * @param column identifies and locates the value within the scope to be deleted. + * @return {@link Result#SUCCESS} if the value was deleted; otherwise an error {@link Result}. + */ + @Nonnull + public final Result deleteVariable( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + boolean exists = buffer.readBit(scope.start(), column.nullBit()); + + if (exists) { + int varOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + buffer.deleteVariable(varOffset, this.isVarint()); + buffer.unsetBit(scope.start(), column.nullBit()); + } + + return Result.SUCCESS; + } + + @Nonnull + public abstract Result readFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value); + + @Nonnull + public abstract Result readSparse( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final Out value); + + @Nonnull + public Result readVariable( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + value.set(null); + return Result.FAILURE; + } + + @Nonnull + public abstract Result writeFixed( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull LayoutColumn column, + @Nonnull T value); + + @Nonnull + public abstract Result writeSparse( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull T value); + + @Nonnull + public abstract Result writeSparse( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor edit, + @Nonnull T value, + @Nonnull UpdateOptions options); + + @Nonnull + public Result writeVariable( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull LayoutColumn column, + @Nonnull T value) { + return Result.FAILURE; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypeScope.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypeScope.java new file mode 100644 index 0000000..ccaac8d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypeScope.java @@ -0,0 +1,227 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class LayoutTypeScope extends LayoutType { + + private final boolean isFixedArity; + private final boolean isIndexedScope; + private final boolean isSizedScope; + private final boolean isTypedScope; + private final boolean isUniqueScope; + + protected LayoutTypeScope( + @Nonnull final LayoutCode code, + final boolean immutable, + final boolean isSizedScope, + final boolean isIndexedScope, + final boolean isFixedArity, + final boolean isUniqueScope, + final boolean isTypedScope) { + + super(code, immutable, 0); + this.isSizedScope = isSizedScope; + this.isIndexedScope = isIndexedScope; + this.isFixedArity = isFixedArity; + this.isUniqueScope = isUniqueScope; + this.isTypedScope = isTypedScope; + } + + /** + * {@code true} if the {@link LayoutTypeScope} has a fixed-, not variable-length layout type. + * + * @return {@code true} if the {@link LayoutTypeScope} has a fixed-, not variable-length layout type. + */ + @Override + public boolean isFixed() { + return false; + } + + /** + * {@code true} if this is a fixed arity scope. + * + * @return {@code true} if this is a fixed arity scope. + */ + public boolean isFixedArity() { + return this.isFixedArity; + } + + /** + * {@code true} if this is an indexed scope. + * + * @return {@code true} if this is an indexed scope. + */ + public boolean isIndexedScope() { + return this.isIndexedScope; + } + + /** + * {@code true} if this is a sized scope. + * + * @return {@code true} if this is a sized scope. + */ + public boolean isSizedScope() { + return this.isSizedScope; + } + + /** + * {@code true} if this is a typed scope. + * + * @return {@code true} if this is a typed scope. + */ + public boolean isTypedScope() { + return this.isTypedScope; + } + + /** + * {@code true} if the scope's elements cannot be updated directly. + * + * @return {@code true} if the scope's elements cannot be updated directly. + */ + public boolean isUniqueScope() { + return this.isUniqueScope; + } + + @Nonnull + public final Result deleteScope(@Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + + Result result = LayoutType.prepareSparseDelete(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.deleteSparse(edit); + return Result.SUCCESS; + } + + /** + * {@code true} if writing an item in the specified typed scope would elide the type code because it is implied by + * the type arguments + * + * @param edit a non-null {@link RowCursor} specifying a typed scope. + * @return {@code true} if the type code is implied (not written); {@code false} otherwise. + */ + public boolean hasImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + return false; + } + + @Nonnull + public final Result readScope( + @Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit, @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(value, "expected non-null value"); + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + boolean immutable = this.isImmutable() || edit.immutable() || edit.scopeType().isUniqueScope(); + value.set(buffer.sparseIteratorReadScope(edit, immutable)); + return Result.SUCCESS; + } + + public void readSparsePath(@Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit) { + Out pathLengthInBytes = new Out<>(); + Out pathOffset = new Out<>(); + edit.pathToken(buffer.readSparsePathLen(edit.layout(), edit.valueOffset(), pathOffset, pathLengthInBytes)); + edit.pathOffset(pathOffset.get()); + edit.valueOffset(edit.valueOffset() + pathLengthInBytes.get()); + } + + public void setImplicitTypeCode(@Nonnull final RowCursor edit) { + throw new UnsupportedOperationException(); + } + + @Nonnull + public abstract Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull TypeArgumentList typeArgs, @Nonnull Out value); + + @Nonnull + public abstract Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull TypeArgumentList typeArgs, + @Nonnull UpdateOptions options, @Nonnull Out value); + + @Nonnull + public Result writeScope( + @Nonnull RowBuffer buffer, + @Nonnull RowCursor scope, + @Nonnull TypeArgumentList typeArgs, + @Nonnull TContext context, @Nullable WriterFunc func) { + return this.writeScope(buffer, scope, typeArgs, context, func, UpdateOptions.UPSERT); + } + + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final TypeArgumentList typeArgs, + @Nullable TContext context, + @Nullable WriterFunc func, + @Nonnull UpdateOptions options) { + + final Out out = new Out<>(); + Result result = this.writeScope(buffer, scope, typeArgs, options, out); + + if (result != Result.SUCCESS) { + return result; + } + + final RowCursor childScope = out.get(); + + if (func != null) { + result = func.invoke(buffer, childScope, context); + if (result != Result.SUCCESS) { + this.deleteScope(buffer, scope); + return result; + } + } + + RowCursors.skip(scope, buffer, childScope); + return Result.SUCCESS; + } + + /** + * A functional interfaced that can be used to write content to a {@link RowBuffer} + * + * @param The type of the context value passed by the caller + */ + @FunctionalInterface + public interface WriterFunc { + /** + * Writes content to a {@link RowBuffer} + * + * @param buffer The row to write to + * @param scope The type of the scope to write into + * @param context A context value provided by the caller + * @return The result + */ + @Nonnull + Result invoke(@Nonnull final RowBuffer buffer, @Nonnull final RowCursor scope, @Nullable TContext context); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedArray.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedArray.java new file mode 100644 index 0000000..fb9a398 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedArray.java @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class LayoutTypedArray extends LayoutIndexedScope { + + public LayoutTypedArray(boolean immutable) { + super( + immutable ? LayoutCode.IMMUTABLE_TYPED_ARRAY_SCOPE : LayoutCode.TYPED_ARRAY_SCOPE, immutable, + true, false, false, true + ); + } + + @Override + public int countTypeArgument(@Nonnull TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + checkState(value.count() == 1); + return LayoutCode.BYTES + value.get(0).type().countTypeArgument(value.get(0).typeArgs()); + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull RowCursor edit) { + checkState(edit.index() >= 0); + checkState(edit.scopeTypeArgs().count() == 1); + return !LayoutCodeTraits.alwaysRequiresTypeCode(edit.scopeTypeArgs().get(0).type().layoutCode()); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_array_t" : "array_t"; + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList(@Nonnull RowBuffer buffer, int offset, @Nonnull Out lenInBytes) { + return new TypeArgumentList(LayoutType.readTypeArgument(buffer, offset, lenInBytes)); + } + + @Override + public void setImplicitTypeCode(@Nonnull final RowCursor edit) { + edit.cellType(edit.scopeTypeArgs().get(0).type()); + edit.cellTypeArgs(edit.scopeTypeArgs().get(0).typeArgs()); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + final TypeArgument typeArg = new TypeArgument(this, typeArgs); + final Result result = LayoutType.prepareSparseWrite(buffer, edit, typeArg, options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.writeTypedArray(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final TypeArgumentList value) { + + checkState(value.count() == 1); + + TypeArgument typeArg = value.get(0); + buffer.writeSparseTypeCode(offset, this.layoutCode()); + + return LayoutCode.BYTES + typeArg.type().writeTypeArgument( + buffer, offset + LayoutCode.BYTES, typeArg.typeArgs() + ); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedMap.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedMap.java new file mode 100644 index 0000000..dadc860 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedMap.java @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class LayoutTypedMap extends LayoutUniqueScope { + + public LayoutTypedMap(boolean immutable) { + super( + immutable ? LayoutCode.IMMUTABLE_TYPED_MAP_SCOPE : LayoutCode.TYPED_MAP_SCOPE, immutable, + true, true); + } + + @Override + public int countTypeArgument(@Nonnull final TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + checkState(value.count() == 2); + return value.stream() + .map(arg -> arg.type().countTypeArgument(arg.typeArgs())) + .reduce(LayoutCode.BYTES, Integer::sum); + } + + @Nonnull + @Override + public TypeArgument fieldType(@Nonnull final RowCursor scope) { + checkNotNull(scope, "expected non-null scope"); + return new TypeArgument( + scope.scopeType().isImmutable() ? LayoutTypes.IMMUTABLE_TYPED_TUPLE : LayoutTypes.TYPED_TUPLE, + scope.scopeTypeArgs()); + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + return true; + } + + @Nonnull + public String name() { + return this.isImmutable() ? "im_map_t" : "map_t"; + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + + TypeArgument[] typeArguments = new TypeArgument[2]; + Out length = new Out<>(); + int index = 0; + + for (int i = 0; i < 2; i++) { + typeArguments[i] = readTypeArgument(buffer, offset + index, length); + index += length.get(); + } + + lengthInBytes.set(index); + return new TypeArgumentList(typeArguments); + } + + @Override + public void setImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + edit.cellType(edit.scopeType().isImmutable() ? LayoutTypes.IMMUTABLE_TYPED_TUPLE : LayoutTypes.TYPED_TUPLE); + edit.cellTypeArgs(edit.scopeTypeArgs()); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + final Result result = prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.setAndGet(null); + return result; + } + + value.set(buffer.writeTypedMap(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final TypeArgumentList value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(value, "expected non-null value"); + checkArgument(value.count() == 2, "expected value count of 2, not %s", value.count()); + + buffer.writeSparseTypeCode(offset, this.layoutCode()); + int lengthInBytes = LayoutCode.BYTES; + + for (TypeArgument arg : value.list()) { + lengthInBytes += arg.type().writeTypeArgument(buffer, offset + lengthInBytes, arg.typeArgs()); + } + + return lengthInBytes; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedSet.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedSet.java new file mode 100644 index 0000000..3379894 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedSet.java @@ -0,0 +1,121 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.IMMUTABLE_TYPED_SET_SCOPE; +import static com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCode.TYPED_SET_SCOPE; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +public final class LayoutTypedSet extends LayoutUniqueScope { + + public LayoutTypedSet(boolean immutable) { + super(immutable ? IMMUTABLE_TYPED_SET_SCOPE : TYPED_SET_SCOPE, immutable, true, true); + } + + @Override + public int countTypeArgument(@Nonnull final TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + checkState(value.count() == 1); + return LayoutCode.BYTES + value.get(0).type().countTypeArgument(value.get(0).typeArgs()); + } + + @Nonnull + @Override + public TypeArgument fieldType(@Nonnull final RowCursor scope) { + checkNotNull(scope, "expected non-null scope"); + return scope.scopeTypeArgs().get(0); + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + checkState(edit.index() >= 0); + checkState(edit.scopeTypeArgs().count() == 1); + return !LayoutCodeTraits.alwaysRequiresTypeCode(edit.scopeTypeArgs().get(0).type().layoutCode()); + } + + @Nonnull + public String name() { + return this.isImmutable() ? "im_set_t" : "set_t"; + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, + final int offset, + @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + return new TypeArgumentList(readTypeArgument(buffer, offset, lengthInBytes)); + } + + @Override + public void setImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + edit.cellType(edit.scopeTypeArgs().get(0).type()); + edit.cellTypeArgs(edit.scopeTypeArgs().get(0).typeArgs()); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + Result result = prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.setAndGet(null); + return result; + } + + value.set(buffer.writeTypedSet(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument( + @Nonnull final RowBuffer buffer, + final int offset, + @Nonnull final TypeArgumentList value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(value, "expected non-null value"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + checkArgument(value.count() == 1, "expected a single value count, not %s", value.count()); + + buffer.writeSparseTypeCode(offset, this.layoutCode()); + final TypeArgument typeArg = value.get(0); + int lengthInBytes = LayoutCode.BYTES; + lengthInBytes += typeArg.type().writeTypeArgument(buffer, offset + lengthInBytes, typeArg.typeArgs()); + + return lengthInBytes; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedTuple.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedTuple.java new file mode 100644 index 0000000..ea61ba0 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypedTuple.java @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutTypedTuple extends LayoutIndexedScope { + + public LayoutTypedTuple(boolean immutable) { + super( + immutable ? LayoutCode.IMMUTABLE_TYPED_TUPLE_SCOPE : LayoutCode.TYPED_TUPLE_SCOPE, immutable, + true, true, false, true + ); + } + + @Override + public int countTypeArgument(@Nonnull TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + return value.stream() + .map(arg -> arg.type().countTypeArgument(arg.typeArgs())) + .reduce(LayoutCode.BYTES + RowBuffer.count7BitEncodedUInt(value.count()), Integer::sum); + } + + @Override + public boolean hasImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + checkArgument(edit.index() >= 0); + checkArgument(edit.scopeTypeArgs().count() > edit.index()); + return !LayoutCodeTraits.alwaysRequiresTypeCode(edit.scopeTypeArgs().get(edit.index()).type().layoutCode()); + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_tuple_t" : "tuple_t"; + } + + @Nonnull + @Override + public TypeArgumentList readTypeArgumentList( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out lengthInBytes) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(lengthInBytes, "expected non-null lengthInBytes"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + final int numTypeArgs = (int) buffer.readVariableUInt(offset, lengthInBytes); + final TypeArgument[] typeArgs = new TypeArgument[numTypeArgs]; + final Out len = new Out<>(); + + int sum = lengthInBytes.get(); + + for (int i = 0; i < numTypeArgs; i++) { + typeArgs[i] = LayoutType.readTypeArgument(buffer, offset + sum, len); + sum += len.get(); + } + + lengthInBytes.set(sum); + return new TypeArgumentList(typeArgs); + } + + @Override + public void setImplicitTypeCode(@Nonnull final RowCursor edit) { + checkNotNull(edit, "expected non-null edit"); + edit.cellType(edit.scopeTypeArgs().get(edit.index()).type()); + edit.cellTypeArgs(edit.scopeTypeArgs().get(edit.index()).typeArgs()); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final TypeArgumentList typeArgs, + @Nonnull final UpdateOptions options, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(edit, "expected non-null edit"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + checkNotNull(value, "expected non-null value"); + + Result result = LayoutType.prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.setAndGet(null); + return result; + } + + value.set(buffer.writeTypedTuple(edit, this, typeArgs, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument( + @Nonnull final RowBuffer buffer, final int offset, @Nonnull final TypeArgumentList value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(value, "expected non-null value"); + checkArgument(offset >= 0, "expected non-negative offset, not %s", offset); + + buffer.writeSparseTypeCode(offset, this.layoutCode()); + int lengthInBytes = LayoutCode.BYTES; + lengthInBytes += buffer.writeVariableUInt(offset + lengthInBytes, value.count()); + + for (TypeArgument arg : value.list()) { + lengthInBytes += arg.type().writeTypeArgument(buffer, offset + lengthInBytes, arg.typeArgs()); + } + + return lengthInBytes; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypes.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypes.java new file mode 100644 index 0000000..2a9dd32 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutTypes.java @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +/** + * Layout type definitions + */ +public abstract class LayoutTypes { + public static final LayoutArray ARRAY = new LayoutArray(false); + public static final LayoutBinary BINARY = new LayoutBinary(); + public static final LayoutBoolean BOOLEAN = new LayoutBoolean(true); + public static final LayoutBoolean BOOLEAN_FALSE = new LayoutBoolean(false); + public static final LayoutDateTime DATE_TIME = new LayoutDateTime(); + public static final LayoutDecimal DECIMAL = new LayoutDecimal(); + public static final LayoutEndScope END_SCOPE = new LayoutEndScope(); + public static final LayoutFloat128 FLOAT_128 = new LayoutFloat128(); + public static final LayoutFloat32 FLOAT_32 = new LayoutFloat32(); + public static final LayoutFloat64 FLOAT_64 = new LayoutFloat64(); + public static final LayoutGuid GUID = new LayoutGuid(); + public static final LayoutArray IMMUTABLE_ARRAY = new LayoutArray(true); + public static final LayoutNullable IMMUTABLE_NULLABLE = new LayoutNullable(true); + public static final LayoutObject IMMUTABLE_OBJECT = new LayoutObject(true); + public static final LayoutTagged IMMUTABLE_TAGGED = new LayoutTagged(true); + public static final LayoutTagged2 IMMUTABLE_TAGGED_2 = new LayoutTagged2(true); + public static final LayoutTuple ImmutableTuple = new LayoutTuple(true); + public static final LayoutTypedArray IMMUTABLE_TYPED_ARRAY = new LayoutTypedArray(true); + public static final LayoutTypedMap IMMUTABLE_TYPED_MAP = new LayoutTypedMap(true); + public static final LayoutTypedSet IMMUTABLE_TYPED_SET = new LayoutTypedSet(true); + public static final LayoutTypedTuple IMMUTABLE_TYPED_TUPLE = new LayoutTypedTuple(true); + public static final LayoutUDT IMMUTABLE_UDT = new LayoutUDT(true); + public static final LayoutInt16 INT_16 = new LayoutInt16(); + public static final LayoutInt32 INT_32 = new LayoutInt32(); + public static final LayoutInt64 INT_64 = new LayoutInt64(); + public static final LayoutInt8 INT_8 = new LayoutInt8(); + public static final LayoutMongoDbObjectId MONGODB_OBJECT_ID = new LayoutMongoDbObjectId(); + public static final LayoutNull NULL = new LayoutNull(); + public static final LayoutNullable NULLABLE = new LayoutNullable(false); + public static final LayoutObject OBJECT = new LayoutObject(false); + public static final LayoutTagged TAGGED = new LayoutTagged(false); + public static final LayoutTagged2 TAGGED_2 = new LayoutTagged2(false); + public static final LayoutTuple TUPLE = new LayoutTuple(false); + public static final LayoutTypedArray TYPED_ARRAY = new LayoutTypedArray(false); + public static final LayoutTypedMap TYPED_MAP = new LayoutTypedMap(false); + public static final LayoutTypedSet TYPED_SET = new LayoutTypedSet(false); + public static final LayoutTypedTuple TYPED_TUPLE = new LayoutTypedTuple(false); + public static final LayoutUDT UDT = new LayoutUDT(false); + public static final LayoutUInt16 UINT_16 = new LayoutUInt16(); + public static final LayoutUInt32 UINT_32 = new LayoutUInt32(); + public static final LayoutUInt64 UINT_64 = new LayoutUInt64(); + public static final LayoutUInt8 UINT_8 = new LayoutUInt8(); + public static final LayoutUnixDateTime UNIX_DATE_TIME = new LayoutUnixDateTime(); + public static final LayoutUtf8 UTF_8 = new LayoutUtf8(); + public static final LayoutVarInt VAR_INT = new LayoutVarInt(); + public static final LayoutVarUInt VAR_UINT = new LayoutVarUInt(); +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUDT.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUDT.java new file mode 100644 index 0000000..bb5da7d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUDT.java @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutUDT extends LayoutPropertyScope { + + public LayoutUDT(boolean immutable) { + super(immutable ? LayoutCode.IMMUTABLE_SCHEMA : LayoutCode.SCHEMA, immutable); + } + + @Override + public int countTypeArgument(@Nonnull TypeArgumentList value) { + checkNotNull(value, "expected non-null value"); + return LayoutCode.BYTES + SchemaId.BYTES; + } + + @Override + @Nonnull + public String name() { + return this.isImmutable() ? "im_udt" : "udt"; + } + + @Override + @Nonnull + public TypeArgumentList readTypeArgumentList(@Nonnull RowBuffer row, int offset, @Nonnull Out lengthInBytes) { + SchemaId schemaId = row.readSchemaId(offset); + lengthInBytes.set(SchemaId.BYTES); + return new TypeArgumentList(schemaId); + } + + @Override + @Nonnull + public Result writeScope(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull TypeArgumentList typeArgs, @Nonnull Out value) { + return this.writeScope(buffer, edit, typeArgs, UpdateOptions.UPSERT, value); + } + + @Override + @Nonnull + public Result writeScope(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull TypeArgumentList typeArgs, @Nonnull UpdateOptions options, + @Nonnull Out value) { + + Layout udt = buffer.resolver().resolve(typeArgs.schemaId()); + Result result = prepareSparseWrite(buffer, edit, new TypeArgument(this, typeArgs), options); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.writeSparseUDT(edit, this, udt, options)); + return Result.SUCCESS; + } + + @Override + public int writeTypeArgument(@Nonnull RowBuffer buffer, int offset, @Nonnull TypeArgumentList value) { + buffer.writeSparseTypeCode(offset, this.layoutCode()); + buffer.writeSchemaId(offset + LayoutCode.BYTES, value.schemaId()); + return LayoutCode.BYTES + SchemaId.BYTES; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt16.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt16.java new file mode 100644 index 0000000..b38cb19 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt16.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutUInt16 extends LayoutTypePrimitive { + + public LayoutUInt16() { + super(LayoutCode.UINT_16, Short.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "uint16"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0); + return Result.NOT_FOUND; + } + + value.set(buffer.readUInt16(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0); + return result; + } + + value.set(buffer.readSparseUInt16(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Integer value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeUInt16(scope.start() + column.offset(), value.shortValue()); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Integer value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseUInt16(edit, value.shortValue(), options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Integer value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt32.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt32.java new file mode 100644 index 0000000..af9787a --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt32.java @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutUInt32 extends LayoutTypePrimitive { + + public LayoutUInt32() { + super(LayoutCode.UINT_32, Integer.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "uint32"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0L); + return Result.NOT_FOUND; + } + + value.set(buffer.readUInt32(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0L); + return result; + } + + value.set(buffer.readSparseUInt32(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Long value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeUInt32(scope.start() + column.offset(), value.intValue()); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value, @Nonnull UpdateOptions options) { + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + if (result != Result.SUCCESS) { + return result; + } + buffer.writeSparseUInt32(edit, value.intValue(), options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt64.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt64.java new file mode 100644 index 0000000..1de6ce0 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt64.java @@ -0,0 +1,95 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutUInt64 extends LayoutTypePrimitive { + + public LayoutUInt64() { + super(LayoutCode.UINT_64, Long.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "uint64"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0L); + return Result.NOT_FOUND; + } + + value.set(buffer.readUInt64(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0L); + return result; + } + + value.set(buffer.readSparseUInt64(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Long value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeUInt64(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseUInt64(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt8.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt8.java new file mode 100644 index 0000000..1d678a5 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUInt8.java @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutUInt8 extends LayoutTypePrimitive { + + public LayoutUInt8() { + super(LayoutCode.UINT_8, 1); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "uint8"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set((short) 0); + return Result.NOT_FOUND; + } + + value.set(buffer.readUInt8(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set((short) 0); + return result; + } + + value.set(buffer.readSparseUInt8(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Short value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeUInt8(scope.start() + column.offset(), value.byteValue()); + buffer.setBit(scope.start(), column.nullBit()); + + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Short value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseUInt8(edit, value.byteValue(), options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Short value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUniqueScope.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUniqueScope.java new file mode 100644 index 0000000..fa34ff4 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUniqueScope.java @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.RowCursors; +import com.azure.data.cosmos.serialization.hybridrow.RowOptions; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class LayoutUniqueScope extends LayoutIndexedScope implements ILayoutType { + + protected LayoutUniqueScope(LayoutCode code, boolean immutable, boolean isSizedScope, boolean isTypedScope) { + super(code, immutable, isSizedScope, false, true, isTypedScope); + } + + @Nonnull + public abstract TypeArgument fieldType(@Nonnull RowCursor scope); + + /** + * Search for a matching field within a unique index. + *

+ * The pattern field is deleted whether the find succeeds or fails. + * + * @param buffer The row to search. + * @param scope The parent unique index edit to search. + * @param patternScope The parent edit from which the match pattern is read. + * @param value If successful, the updated edit. + * @return Success a matching field exists in the unique index, NotFound if no match is found, the error code + * otherwise. + */ + @Nonnull + public final Result find(RowBuffer buffer, RowCursor scope, RowCursor patternScope, Out value) { + + Result result = LayoutType.prepareSparseMove(buffer, scope, this, this.fieldType(scope), patternScope, + UpdateOptions.UPDATE, value); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.deleteSparse(patternScope); + return Result.SUCCESS; + } + + /** + * Moves an existing sparse field into the unique index. + *

+ * The source field MUST be a field whose type arguments match the element type of the destination unique index. + * The source field is deleted whether the move succeeds or fails. + * + * @param buffer The row to move within. + * @param destinationScope The parent unique indexed edit into which the field should be moved. + * @param sourceEdit The field to be moved. + * @param options The move options. + * @return Success if the field is permitted within the unique index, the error code otherwise. + */ + @Nonnull + public final Result moveField( + RowBuffer buffer, RowCursor destinationScope, RowCursor sourceEdit, UpdateOptions options) { + + Out dstEdit = new Out<>(); + + Result result = LayoutType.prepareSparseMove( + buffer, destinationScope, this, this.fieldType(destinationScope), sourceEdit, options, dstEdit); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.typedCollectionMoveField(dstEdit.get(), sourceEdit, RowOptions.from(options.value())); + + // TODO: it would be "better" if the destinationScope were updated to point to the highest item seen. Then we + // would avoid the maximum reparse + + destinationScope.count(dstEdit.get().count()); + return Result.SUCCESS; + } + + /** + * Moves an existing sparse field into the unique index. + * + * @param buffer The row to move within. + * @param destinationScope The parent unique indexed edit into which the field should be moved. + * @param sourceEdit The field to be moved. + * @return {@link Result#SUCCESS} if the field is moved; an error {@link Result} otherwise. + *

+ * The source field MUST be a field whose type arguments match the element type of the + * destination unique index. + *

+ * The source field is deleted whether the move succeeds or fails. + */ + @Nonnull + public final Result moveField( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor destinationScope, + @Nonnull final RowCursor sourceEdit) { + return this.moveField(buffer, destinationScope, sourceEdit, UpdateOptions.UPSERT); + } + + @Override + @Nonnull + public Result writeScope( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final TypeArgumentList typeArgs, + @Nullable final TContext context, + @Nullable final WriterFunc func, + @Nonnull final UpdateOptions options) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(typeArgs, "expected non-null typeArgs"); + checkNotNull(options, "expected non-null options"); + + final Out uniqueScope = new Out<>(); + Result result; + + result = this.writeScope(buffer, scope, typeArgs, options, uniqueScope); + + if (result != Result.SUCCESS) { + return result; + } + + RowCursor childScope = uniqueScope.get().deferUniqueIndex(true); + result = func == null ? null : func.invoke(buffer, childScope, context); + + if (result != null && result != Result.SUCCESS) { + this.deleteScope(buffer, scope); + return result; + } + + uniqueScope.get().count(childScope.count()); + result = buffer.typedCollectionUniqueIndexRebuild(uniqueScope.get()); + + if (result != Result.SUCCESS) { + this.deleteScope(buffer, scope); + return result; + } + + RowCursors.skip(scope, buffer, childScope); + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUnixDateTime.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUnixDateTime.java new file mode 100644 index 0000000..7e827eb --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUnixDateTime.java @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; +import com.azure.data.cosmos.serialization.hybridrow.UnixDateTime; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutUnixDateTime extends LayoutTypePrimitive { + + public LayoutUnixDateTime() { + super(LayoutCode.UNIX_DATE_TIME, UnixDateTime.BYTES); + } + + public boolean isFixed() { + return true; + } + + @Nonnull + public String name() { + return "unixdatetime"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(null); + return Result.NOT_FOUND; + } + + value.set(buffer.readUnixDateTime(scope.start() + column.offset())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.readSparseUnixDateTime(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull UnixDateTime value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeUnixDateTime(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull UnixDateTime value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseUnixDateTime(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull UnixDateTime value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java new file mode 100644 index 0000000..aaca359 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8.java @@ -0,0 +1,246 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +public final class LayoutUtf8 extends LayoutTypePrimitive + implements LayoutUtf8Readable, LayoutUtf8Writable { + + public LayoutUtf8() { + super(LayoutCode.UTF_8, 0); + } + + public boolean isFixed() { + return false; + } + + @Nonnull + public String name() { + return "utf8"; + } + + @Override + @Nonnull + public Result readFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(column, "expected non-null column"); + checkNotNull(value, "expected non-null value"); + + Out span = new Out<>(); + Result result = this.readFixedSpan(buffer, scope, column, span); + value.set(result == Result.SUCCESS ? span.get().toUtf16() : null); + + return result; + } + + @Override + @Nonnull + public Result readFixedSpan( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + checkArgument(column.size() >= 0); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(null); + return Result.NOT_FOUND; + } + + value.set(buffer.readFixedString(scope.start() + column.offset(), column.size())); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readSparse( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final Out value) { + + Out span = new Out<>(); + Result result = this.readSparseSpan(buffer, edit, span); + value.set((result == Result.SUCCESS) ? span.get().toUtf16() : null); + return result; + } + + @Override + @Nonnull + public Result readSparseSpan( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor edit, + @Nonnull final Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(null); + return result; + } + + value.set(buffer.readSparseString(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readVariable( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + Out span = new Out<>(); + Result result = this.readVariableSpan(buffer, scope, column, span); + value.set(result == Result.SUCCESS ? span.get().toUtf16() : null); + return result; + } + + @Override + @Nonnull + public Result readVariableSpan( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(null); + return Result.NOT_FOUND; + } + + int varOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + value.set(buffer.readVariableString(varOffset)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final String value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(column, "expected non-null column"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(value, "expected non-null value"); + + return this.writeFixed(buffer, scope, column, Utf8String.transcodeUtf16(value)); + } + + @Override + @Nonnull + public Result writeFixed( + @Nonnull final RowBuffer buffer, + @Nonnull final RowCursor scope, + @Nonnull final LayoutColumn column, + @Nonnull final Utf8String value) { + + checkNotNull(buffer, "expected non-null buffer"); + checkNotNull(column, "expected non-null column"); + checkNotNull(scope, "expected non-null scope"); + checkNotNull(value, "expected non-null value"); + + checkArgument(scope.scopeType() instanceof LayoutUDT); + checkArgument(column.size() >= 0); + checkArgument(value.encodedLength() == column.size()); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + buffer.writeFixedString(scope.start() + column.offset(), value); + buffer.setBit(scope.start(), column.nullBit()); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull String value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull String value, @Nonnull UpdateOptions options) { + checkArgument(value != null); + return this.writeSparse(buffer, edit, Utf8String.transcodeUtf16(value), options); + } + + @Override + @Nonnull + public Result writeSparse(RowBuffer buffer, RowCursor edit, Utf8String value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } + + @Override + @Nonnull + public Result writeSparse(RowBuffer buffer, RowCursor edit, Utf8String value, UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseString(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeVariable(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull String value) { + checkArgument(value != null); + return this.writeVariable(buffer, scope, column, Utf8String.transcodeUtf16(value)); + } + + @Override + @Nonnull + public Result writeVariable(RowBuffer buffer, RowCursor scope, LayoutColumn column, Utf8String value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + int length = value.encodedLength(); + + if ((column.size() > 0) && (length > column.size())) { + return Result.TOO_BIG; + } + + int offset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + boolean exists = buffer.readBit(scope.start(), column.nullBit()); + int shift = buffer.writeVariableString(offset, value, exists); + + buffer.setBit(scope.start(), column.nullBit()); + scope.metaOffset(scope.metaOffset() + shift); + scope.valueOffset(scope.valueOffset() + shift); + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Readable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Readable.java new file mode 100644 index 0000000..5586d6d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Readable.java @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +/** + * An optional interface that indicates a {@link LayoutType} can also be read as a {@link Utf8String}. + */ +public interface LayoutUtf8Readable extends ILayoutType { + + @Nonnull + Result readFixedSpan(RowBuffer buffer, RowCursor scope, LayoutColumn column, Out value); + + @Nonnull + Result readSparseSpan(RowBuffer buffer, RowCursor scope, Out value); + + @Nonnull + Result readVariableSpan(RowBuffer buffer, RowCursor scope, LayoutColumn column, Out value); +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Writable.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Writable.java new file mode 100644 index 0000000..08cc202 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutUtf8Writable.java @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +/** + * An optional interface that indicates a {@link LayoutType} can also write using a {@link Utf8String} + */ +public interface LayoutUtf8Writable extends ILayoutType { + + @Nonnull + Result writeFixed(RowBuffer buffer, RowCursor scope, LayoutColumn column, Utf8String value); + + @Nonnull + Result writeSparse(RowBuffer buffer, RowCursor edit, Utf8String value); + + @Nonnull + Result writeSparse(RowBuffer buffer, RowCursor edit, Utf8String value, UpdateOptions options); + + @Nonnull + Result writeVariable(RowBuffer buffer, RowCursor scope, LayoutColumn column, Utf8String value); +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java new file mode 100644 index 0000000..2552dea --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarInt.java @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutVarInt extends LayoutTypePrimitive { + + public LayoutVarInt() { + super(LayoutCode.VAR_INT, 0); + } + + public boolean isFixed() { + return false; + } + + public boolean isVarint() { + return true; + } + + @Nonnull + public String name() { + return "varint"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + assert false : "not implemented"; + value.set(0L); + return Result.FAILURE; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = LayoutType.prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0L); + return result; + } + + value.set(buffer.readSparseVarInt(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readVariable(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0L); + return Result.NOT_FOUND; + } + + int varOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + value.set(buffer.readVariableInt(varOffset)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Long value) { + assert false : "not implemented"; + return Result.FAILURE; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value, @Nonnull UpdateOptions options) { + + Result result = LayoutType.prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseVarInt(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } + + @Override + @Nonnull + public Result writeVariable(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Long value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + boolean exists = buffer.readBit(scope.start(), column.nullBit()); + int varOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + int shift = buffer.writeVariableInt(varOffset, value, exists); + + buffer.setBit(scope.start(), column.nullBit()); + scope.metaOffset(scope.metaOffset() + shift); + scope.valueOffset(scope.valueOffset() + shift); + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java new file mode 100644 index 0000000..9ee81df --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/LayoutVarUInt.java @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.RowCursor; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkArgument; + +public final class LayoutVarUInt extends LayoutTypePrimitive { + + public LayoutVarUInt() { + super(LayoutCode.VAR_UINT, 0); + } + + public boolean isFixed() { + return false; + } + + public boolean isVarint() { + return true; + } + + @Nonnull + public String name() { + return "varuint"; + } + + @Override + @Nonnull + public Result readFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + assert false : "not implemented"; + value.set(0L); + return Result.FAILURE; + } + + @Override + @Nonnull + public Result readSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Out value) { + + Result result = prepareSparseRead(buffer, edit, this.layoutCode()); + + if (result != Result.SUCCESS) { + value.set(0L); + return result; + } + + value.set(buffer.readSparseVarUInt(edit)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result readVariable(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Out value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (!buffer.readBit(scope.start(), column.nullBit())) { + value.set(0L); + return Result.NOT_FOUND; + } + + int varOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset()); + value.set(buffer.readVariableUInt(varOffset)); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeFixed(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn column, @Nonnull Long value) { + assert false : "not implemented"; + return Result.FAILURE; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value, @Nonnull UpdateOptions options) { + + Result result = prepareSparseWrite(buffer, edit, this.typeArg(), options); + + if (result != Result.SUCCESS) { + return result; + } + + buffer.writeSparseVarUInt(edit, value, options); + return Result.SUCCESS; + } + + @Override + @Nonnull + public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull Long value) { + return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT); + } + + @Override + @Nonnull + public Result writeVariable(@Nonnull RowBuffer buffer, @Nonnull RowCursor scope, @Nonnull LayoutColumn col, @Nonnull Long value) { + + checkArgument(scope.scopeType() instanceof LayoutUDT); + + if (scope.immutable()) { + return Result.INSUFFICIENT_PERMISSIONS; + } + + final boolean exists = buffer.readBit(scope.start(), col.nullBit()); + final int varOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), col.offset()); + final int shift = buffer.writeVariableUInt(varOffset, value, exists); + + buffer.setBit(scope.start(), col.nullBit()); + scope.metaOffset(scope.metaOffset() + shift); + scope.valueOffset(scope.valueOffset() + shift); + + return Result.SUCCESS; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringToken.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringToken.java new file mode 100644 index 0000000..0aaf8d0 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringToken.java @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Utf8String; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class StringToken implements Cloneable { + + public static final StringToken NONE = new StringToken(); + + private final long id; + private final Utf8String path; + private final ByteBuf varint; + + public StringToken(long id, @Nonnull Utf8String path) { + + checkNotNull(path); + + byte[] buffer = new byte[count7BitEncodedUInt(id)]; + StringToken.write7BitEncodedUInt(buffer, id); + + this.varint = Unpooled.wrappedBuffer(buffer).asReadOnly(); + this.path = path; + this.id = id; + } + + private StringToken() { + this.id = 0L; + this.path = Utf8String.EMPTY; + this.varint = Unpooled.wrappedBuffer(new byte[1]).asReadOnly(); + } + + public boolean isNull() { + return this.varint() == null; + } + + public long id() { + return this.id; + } + + public Utf8String path() { + return this.path; + } + + public ByteBuf varint() { + return this.varint; + } + + @Override + protected StringToken clone() { + + try { + return (StringToken) super.clone(); + } catch (CloneNotSupportedException error) { + assert false : error; + throw new IllegalStateException(error); + } + } + + private static int count7BitEncodedUInt(long value) { + + // Count the number of bytes needed to write out an int 7 bits at a time. + int i = 0; + + while (value >= 0x80L) { + i++; + value >>>= 7; + } + + return ++i; + } + + private static int write7BitEncodedUInt(byte[] buffer, long value) { + + // Write an unsigned long 7 bits at a time. The high bit of the byte, when set, indicates there are more bytes. + int i = 0; + + while (value >= 0x80L) { + buffer[i++] = (byte) (value | 0x80); + value >>>= 7; + } + + buffer[i++] = (byte) value; + return i; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java new file mode 100644 index 0000000..61c10c9 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/StringTokenizer.java @@ -0,0 +1,110 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.core.UtfAnyString; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Optional; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +public final class StringTokenizer { + + private final HashMap stringTokens; + private final ArrayList strings; + private final HashMap tokens; + + private int count; + + /** + * Initializes a new instance of the {@link StringTokenizer} class. + */ + public StringTokenizer() { + + this.tokens = new HashMap<>(); + this.tokens.put(Utf8String.EMPTY, StringToken.NONE); + + this.stringTokens = new HashMap<>(); + this.stringTokens.put("", StringToken.NONE); + + this.strings = new ArrayList<>(); + this.strings.add(Utf8String.EMPTY); + + this.count = 1; + } + + /** + * Looks up a token's corresponding string. + * + * @param token The token to look up. + * @return True if successful, false otherwise. + */ + public Optional tryFindString(long token) { + return token >= (long)this.strings.size() ? Optional.empty() : Optional.of(this.strings.get((int) token)); + } + + /** + * Looks up a string's corresponding token. + * + * @param path The string to look up. + * @return {@code true} if successful, {@code false} otherwise. + */ + public Optional tryFindToken(UtfAnyString path) { + + if (path.isNull()) { + return Optional.empty(); + } + + if (path.isUtf8()) { + return Optional.ofNullable(this.tokens.get(path.toUtf8())); + } + + return Optional.ofNullable(this.stringTokens.get(path.toUtf16())); + } + + /** + * Assign a token to a string + *

+ * If the string already has a token, that token is returned instead. + * + * @param path The string to assign a new token. + * @return The token assigned to the string. + */ + public StringToken add(Utf8String path) { + checkArgument(path != null); + final StringToken token = this.tokens.get(path); + return token == null ? this.allocateToken(path) : token; + } + + /** + * The number of unique tokens described by the encoding. + * + * @return the number of unique tokens described by the encoding. + */ + public int count() { + return this.count; + } + + /** + * Allocates a new token and assigns the string to it. + * + * @param path The string that needs a new token. + * @return The new allocated token. + */ + private StringToken allocateToken(Utf8String path) { + + final StringToken token = new StringToken(this.count++, path); + + this.stringTokens.put(path.toUtf16(), token); + this.tokens.put(path, token); + this.strings.add(path); + + checkState((long)this.strings.size() - 1 == token.id()); + return token; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchema.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchema.java new file mode 100644 index 0000000..5cb455f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchema.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace; +import com.google.common.base.Suppliers; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.CodeSource; +import java.util.Enumeration; +import java.util.Optional; +import java.util.function.Supplier; + +import static com.google.common.base.Strings.lenientFormat; + +public final class SystemSchema { + + public static final String specificationTitle = "HybridRow serialization library"; + + /** + * SchemaId of the empty schema. This schema has no defined cells but can accomodate + * unschematized sparse content. + */ + public static final SchemaId EMPTY_SCHEMA_ID = SchemaId.from(2147473650); + + /** + * SchemaId of HybridRow RecordIO Record Headers. + */ + public static final SchemaId RECORD_SCHEMA_ID = SchemaId.from(2147473649); + + /** + * SchemaId of HybridRow RecordIO Segments. + */ + public static final SchemaId SEGMENT_SCHEMA_ID = SchemaId.from(2147473648); + + private static final Supplier layoutResolver = Suppliers.memoize(() -> { + + final Optional namespace; + + try (final InputStream stream = getResourceAsStream("SystemSchema.json")) { + namespace = Namespace.parse(stream); + } catch (IOException cause) { + String message = lenientFormat("failed to initialize %s due to %s", SystemSchema.class, cause); + throw new IllegalStateException(message, cause); + } + + return new LayoutResolverNamespace(namespace.orElseThrow(() -> { + String message = lenientFormat( + "failed to initialize %s due to system schema parse error", + SystemSchema.class); + return new IllegalStateException(message); + })); + }); + + private SystemSchema() { + } + + public static LayoutResolver layoutResolver() { + return layoutResolver.get(); + } + + private static InputStream getResourceAsStream(final String name) throws IOException { + + final CodeSource codeSource = SystemSchema.class.getProtectionDomain().getCodeSource(); + final ClassLoader classLoader = SystemSchema.class.getClassLoader(); + final String location = codeSource.getLocation().toString(); + final Enumeration urls; + + urls = classLoader.getResources(name); + + while (urls.hasMoreElements()) { + final URL url = urls.nextElement(); + if (url.getFile().endsWith(name)) { + return url.openStream(); + } + } + + throw new FileNotFoundException(lenientFormat("cannot find %s at %s", name, location)); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgument.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgument.java new file mode 100644 index 0000000..da4c560 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgument.java @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Json; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.Nonnull; + +import static com.google.common.base.Preconditions.checkNotNull; + +public final class TypeArgument { + + public static final TypeArgument NONE = new TypeArgument(); + + private final LayoutType type; + + @JsonProperty + private final TypeArgumentList typeArgs; + + /** + * Initializes a new instance of the {@link TypeArgument} struct. + * + * @param type the type of the constraint. + */ + public TypeArgument(@Nonnull LayoutType type) { + checkNotNull(type, "expected non-null type"); + this.type = type; + this.typeArgs = TypeArgumentList.EMPTY; + } + + /** + * Initializes a new instance of the {@link TypeArgument} struct. + * + * @param type The type of the constraint. + * @param typeArgs For generic types the type parameters. + */ + public TypeArgument(@Nonnull LayoutType type, @Nonnull TypeArgumentList typeArgs) { + checkNotNull(type, "expected non-null type"); + checkNotNull(type, "expected non-null typeArgs"); + this.type = type; + this.typeArgs = typeArgs; + } + + private TypeArgument() { + this.type = null; + this.typeArgs = null; + } + + @Override + public boolean equals(Object other) { + if (null == other) { + return false; + } + return other.getClass() == TypeArgument.class && this.equals((TypeArgument) other); + } + + public boolean equals(TypeArgument other) { + return this.type.equals(other.type) && this.typeArgs.equals(other.typeArgs); + } + + @Override + public int hashCode() { + return (this.type.hashCode() * 397) ^ this.typeArgs.hashCode(); + } + + @Override + public String toString() { + return Json.toString(this); + } + + /** + * The physical layout type. + * + * @return the physical layout type. + */ + public LayoutType type() { + return this.type; + } + + /** + * If the type argument is itself generic, then its type arguments. + * + * @return it the type argument is itself generic, then its type arguments. + */ + public TypeArgumentList typeArgs() { + return this.typeArgs; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgumentList.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgumentList.java new file mode 100644 index 0000000..be164fe --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/TypeArgumentList.java @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import static com.google.common.base.Preconditions.checkNotNull; + +@JsonSerialize(using = TypeArgumentList.JsonSerializer.class) +public final class TypeArgumentList { + + public static final TypeArgumentList EMPTY = new TypeArgumentList(); + + private final TypeArgument[] args; + private final SchemaId schemaId; + + /** + * Initializes a new instance of the {@link TypeArgumentList} class. + * + * @param args arguments in the list. + */ + public TypeArgumentList(@Nonnull final TypeArgument... args) { + checkNotNull(args); + this.args = args; + this.schemaId = SchemaId.INVALID; + } + + /** + * Initializes a new instance of the {@link TypeArgumentList} class + * + * @param schemaId for UDT fields, the schema id of the nested layout + */ + public TypeArgumentList(@Nonnull final SchemaId schemaId) { + checkNotNull(schemaId); + this.args = EMPTY.args; + this.schemaId = schemaId; + } + + private TypeArgumentList() { + this.args = new TypeArgument[] {}; + this.schemaId = SchemaId.INVALID; + } + + /** + * Number of elements in this {@link TypeArgumentList} + *

+ * @return number of arguments in the list + */ + public int count() { + return this.args.length; + } + + public boolean equals(TypeArgumentList other) { + if (null == other) { + return false; + } + if (this == other) { + return true; + } + return this.schemaId().equals(other.schemaId()) && Arrays.equals(this.args, other.args); + } + + @Override + public boolean equals(Object other) { + return other instanceof TypeArgumentList && this.equals((TypeArgumentList) other); + } + + /** + * Element at the specified position in this {@link TypeArgumentList} + *

+ * @param index index of the element to return + * @return element at the specified position in this {@link TypeArgumentList} + */ + public TypeArgument get(int index) { + return this.args[index]; + } + + @Override + public int hashCode() { + + int hash = 19; + hash = (hash * 397) ^ this.schemaId().hashCode(); + + for (TypeArgument a : this.args) { + hash = (hash * 397) ^ a.hashCode(); + } + + return hash; + } + + public List list() { + return Collections.unmodifiableList(Arrays.asList(this.args)); + } + + /** + * For UDT fields, the schema id of the nested layout. + * + * @return for UDT fields, the Schema ID of the nested layout. + */ + public SchemaId schemaId() { + return this.schemaId; + } + + /** + * Stream for iterating over elements in this {@link TypeArgumentList} + *

+ * @return a stream for iterating over elements in this {@link TypeArgumentList} + */ + public Stream stream() { + if (this.args.length == 0) { + return Stream.empty(); + } + return StreamSupport.stream(Arrays.spliterator(this.args), false); + } + + @Override + public String toString() { + return Json.toString(this); + } + + static class JsonSerializer extends StdSerializer { + + private JsonSerializer() { + super(TypeArgumentList.class); + } + + @Override + public void serialize(TypeArgumentList value, JsonGenerator generator, SerializerProvider provider) throws IOException { + + generator.writeStartObject(); + generator.writeObjectField("schemaId", value.schemaId); + generator.writeArrayFieldStart("args"); + + for (TypeArgument element : value.args) { + generator.writeString(element.toString()); + } + + generator.writeEndArray(); + } + } +} \ 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 new file mode 100644 index 0000000..7d66759 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/layouts/UpdateOptions.java @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +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}. + */ +public enum UpdateOptions { + + NONE(0), + + /** + * Overwrite an existing value. + *

+ * An existing value is assumed to exist at the offset provided. The existing value is + * replaced inline. The remainder of the row is resized to accomodate either an increase or decrease + * in required space. + */ + UPDATE(1), + + /** + * Insert a new value + *

+ * An existing value is assumed NOT to exist at the offset provided. The new value is inserted immediately at the + * offset. The remainder of the row is resized to accommodate either an increase or decrease in required space. + */ + INSERT(2), + + /** + * Update an existing value or insert a new value, if no value exists + *

+ * If a value exists, then this operation becomes {@link #UPDATE}, otherwise it becomes {@link #INSERT}. + */ + UPSERT(3), + + /** + * Insert a new value moving existing values to the right. + *

+ * Within an array scope, inserts a new value immediately at the index moving all subsequent + * items to the right. In any other scope behaves the same as {@link #UPSERT}. + */ + INSERT_AT(4); + + public static final int BYTES = Integer.BYTES; + + 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; + } + + public static UpdateOptions from(int value) { + return mappings.get().get(value); + } + + public int value() { + return this.value; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ArrayPropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ArrayPropertyType.java new file mode 100644 index 0000000..ae1cff7 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ArrayPropertyType.java @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Array properties represent an unbounded set of zero or more items. + *

+ * Arrays may be typed or untyped. Within typed arrays, all items MUST be the same type. The type of items is specified + * via {@link #items()}. Typed arrays may be stored more efficiently than untyped arrays. When {@link #items()} is + * unspecified, the array is untyped and its items may be heterogeneous. + */ +public class ArrayPropertyType extends ScopePropertyType { + + @JsonProperty + private PropertyType items; + + /** + * (Optional) type of the elements of the array, if a typed array, otherwise null. + * + * @return type of the elements of the array or {@code null}, if the array is untyped. + */ + public final PropertyType items() { + return this.items; + } + + /** + * Set the type of the elements of the array + * + * @param value type of the elements of the array or {@code null}, if the array is untyped. + * @return a reference to this {@link ArrayPropertyType}. + */ + public final ArrayPropertyType items(PropertyType value) { + this.items = value; + return this; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/MapPropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/MapPropertyType.java new file mode 100644 index 0000000..02e3c33 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/MapPropertyType.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +/** + * Map properties represent an unbounded set of zero or more key-value pairs with unique keys. + *

+ * Maps are typed or untyped. Within typed maps, all key MUST be the same type, and all values MUST be the same type. + * The type of both key and values is specified via {@link #keys()} and {@link #values()} respectively. Typed maps may + * be stored more efficiently than untyped maps. When {@link #keys()} or {@link #values()} is unspecified or marked + * {@link TypeKind#ANY}, the map is untyped and its key and/or values may be heterogeneous. + */ +public class MapPropertyType extends ScopePropertyType { + + private PropertyType keys; + private PropertyType values; + + /** + * (Optional) type of the keys of the map, if a typed map, otherwise {@code null}. + * + * @return type of the keys of the map, if a type map, otherwise {@code null}. + */ + public final PropertyType keys() { + return this.keys; + } + + public final MapPropertyType keys(PropertyType value) { + this.keys = value; + return this; + } + + /** + * (Optional) type of the values of the map, if a typed map, otherwise {@code null}. + * + * @return type of the values of the map, if a typed map, otherwise {@code null}. + */ + public final PropertyType values() { + return this.values; + } + + public final MapPropertyType values(PropertyType value) { + this.values = value; + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Namespace.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Namespace.java new file mode 100644 index 0000000..f2c27d1 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Namespace.java @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.azure.data.cosmos.core.Json; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class Namespace { + + private static final Logger logger = LoggerFactory.getLogger(Json.class); + + @JsonProperty(required = true) + private String name; + + @JsonProperty(required = true) + private ArrayList schemas; + + @JsonProperty(required = true) + private SchemaLanguageVersion version; + + /** + * The fully qualified name of the namespace. + * + * @return fully qualified name of the {@linkplain Namespace namespace}. + */ + public final String name() { + return this.name; + } + + /** + * Sets the fully qualified name of the namespace. + * + * @param value fully qualified name of the {@linkplain Namespace namespace}. + * @return a reference to this {@linkplain Namespace namespace}. + */ + public final Namespace name(String value) { + this.name = value; + return this; + } + + /** + * Parse a JSON document and return a full namespace. + * + * @param file The JSON file to parse. + * @return A namespace containing a set of logical schemas. + */ + public static Optional parse(File file) { + Optional namespace = Json.parse(file, Namespace.class); + namespace.ifPresent(SchemaValidator::validate); + return namespace; + } + + /** + * Parse a JSON document and return a full namespace. + * + * @param stream The JSON input stream to parse. + * @return A namespace containing a set of logical schemas. + */ + public static Optional parse(InputStream stream) { + Optional namespace = Json.parse(stream, Namespace.class); + try { + namespace.ifPresent(SchemaValidator::validate); + } catch (SchemaException error) { + logger.error("failed to parse {} due to ", Namespace.class, error); + } + return namespace; + } + + /** + * Parse a JSON document and return a full namespace. + * + * @param value The JSON text to parse. + * @return A namespace containing a set of logical schemas. + */ + public static Optional parse(String value) { + Optional namespace = Json.parse(value, Namespace.class); + namespace.ifPresent(SchemaValidator::validate); + return namespace; + } + + /** + * The set of schemas that make up the {@link Namespace}. + *

+ * Namespaces may consist of zero or more table schemas along with zero or more UDT schemas. Table schemas can only + * reference UDT schemas defined in the same namespace. UDT schemas can contain nested UDTs whose schemas are + * defined within the same namespace. + * + * @return list of schemas in the current {@link Namespace}. + */ + public final List schemas() { + return this.schemas; + } + + public final Namespace schemas(ArrayList value) { + this.schemas = value != null ? value : new ArrayList(); + return this; + } + + /** + * The version of the HybridRow Schema Definition Language used to encode this namespace. + * + * @return {linkplain SchemaLanguageVersion version} of the HybridRow Schema Definition Language used to encode this + * {@linkplain Namespace namespace}. + */ + public final SchemaLanguageVersion version() { + return this.version; + } + + /** + * Sets the version of the HybridRow Schema Definition Language used to encode this namespace. + * + * @param value {linkplain SchemaLanguageVersion version} of the HybridRow Schema Definition Language that will be + * used to encode this {@linkplain Namespace namespace}. + * @return a reference to this {@linkplain Namespace namespace}. + */ + public final Namespace version(@Nonnull SchemaLanguageVersion value) { + Preconditions.checkNotNull(value, "expected non-null value"); + this.version = value; + return this; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ObjectPropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ObjectPropertyType.java new file mode 100644 index 0000000..fed6462 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ObjectPropertyType.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import java.util.Collections; +import java.util.List; + +/** + * Object properties represent nested structures. + *

+ * Object properties map to multiple columns depending on the number of internal properties within the defined object + * structure. Object properties are provided as a convince in schema design. They are effectively equivalent to + * defining the same properties explicitly via {@link PrimitivePropertyType} with nested property paths. + */ +public class ObjectPropertyType extends ScopePropertyType { + + private List properties; + + /** + * Initializes a new instance of the {@link ObjectPropertyType} class. + */ + public ObjectPropertyType() { + this.properties = Collections.emptyList(); + } + + /** + * A list of zero or more property definitions that define the columns within the schema. + * + * @return a list of zero or more property definitions that define the columns within the schema. + */ + public final List properties() { + return this.properties; + } + + public final ObjectPropertyType properties(List value) { + this.properties = value != null ? value : Collections.emptyList(); + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PartitionKey.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PartitionKey.java new file mode 100644 index 0000000..d500479 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PartitionKey.java @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +/** + * Describes a property or set of properties used to partition the data set across machines. + */ +public class PartitionKey { + /** + * The logical path of the referenced property. + * Partition keys MUST refer to properties defined within the same {@link Schema}. + */ + private String path; + + public final String path() { + return this.path; + } + + public final PartitionKey path(String value) { + this.path = value; + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimarySortKey.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimarySortKey.java new file mode 100644 index 0000000..aa18a48 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimarySortKey.java @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +/** + * Describes a property or set of properties used to order the data set within a single. + * partition. + */ +public class PrimarySortKey { + + private SortDirection direction = SortDirection.values()[0]; + private String path; + + /** + * The logical path of the referenced property. + *

+ * Primary keys MUST refer to properties defined within the same {@link Schema}. + * + * @return the logical path of the referenced property. + */ + public final SortDirection direction() { + return this.direction; + } + + public final PrimarySortKey direction(SortDirection value) { + this.direction = value; + return this; + } + + /** + * The logical path of the referenced property. + *

+ * Primary keys MUST refer to properties defined within the same {@link Schema}. + * + * @return the logical path of the referenced property. + */ + public final String path() { + return this.path; + } + + public final PrimarySortKey path(String value) { + this.path = value; + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimitivePropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimitivePropertyType.java new file mode 100644 index 0000000..d9aed1c --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PrimitivePropertyType.java @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A primitive property. + *

+ * Primitive properties map to columns one-to-one. Primitive properties indicate how the column should be represented + * within the row. + */ +public class PrimitivePropertyType extends PropertyType { + + @JsonProperty + private int length; + + @JsonProperty + private StorageKind storage; + + /** + * The maximum allowable length in bytes. + *

+ * This annotation is only valid for non-fixed length types. A value of 0 means the maximum allowable length. + * + * @return the maximum allowable length in bytes. + */ + public final int length() { + return this.length; + } + + public final PrimitivePropertyType length(int value) { + this.length = value; + return this; + } + + /** + * Storage requirements of the property. + * + * @return storage requirements of the property. + */ + public final StorageKind storage() { + return this.storage; + } + + public final PrimitivePropertyType storage(StorageKind value) { + this.storage = value; + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Property.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Property.java new file mode 100644 index 0000000..1c83c3f --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Property.java @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.Nonnull; + +/** + * Describes a single property definition. + */ +public class Property { + + @JsonProperty(required = false) + private String comment; + + @JsonProperty(required = true) + private String path; + + @JsonProperty(required = true) + private PropertyType type; + + /** + * An (optional) comment describing the purpose of this {@linkplain Property property}. + *

+ * Comments are for documentary purpose only and do not affect the property at runtime. + * + * @return the comment on this {@linkplain Schema property} or {@code null}, if there is no comment. + */ + public final String comment() { + return this.comment; + } + + /** + * Sets the (optional) comment describing the purpose of this {@linkplain Property property}. + *

+ * Comments are for documentary purpose only and do not affect the property at runtime. + * + * @param value a comment on this {@linkplain Property property} or {@code null} to remove the comment, if any, on + * this {@linkplain Property property}. + * @return a reference to this {@linkplain Property property}. + */ + public final Property comment(String value) { + this.comment = value; + return this; + } + + /** + * The logical path of this {@linkplain Property property}. + *

. + * For complex properties (e.g. objects) the logical path forms a prefix to relative paths of properties defined + * within nested structures. + *

+ * See the logical path specification for full details on both relative and absolute paths. + * + * @return the logical path of this {@linkplain Property property}. + */ + public final String path() { + return this.path; + } + + /** + * Sets the logical path of this {@linkplain Property property}. + *

. + * For complex properties (e.g. objects) the logical path forms a prefix to relative paths of properties defined + * within nested structures. + *

+ * See the logical path specification for full details on both relative and absolute paths. + * + * @param value the logical path of this {@linkplain Property property}. + * @return a reference to this {@linkplain Property property}. + */ + public final Property path(@Nonnull String value) { + this.path = value; + return this; + } + + /** + * The type of this {@linkplain Property property}. + *

+ * Types may be simple (e.g. int8) or complex (e.g. object). Simple types always define a single column. Complex + * types may define one or more columns depending on their structure. + * + * @return the type of this {@linkplain Property property}. + */ + public final PropertyType type() { + return this.type; + } + + /** + * Sets the type of this {@linkplain Property property}. + *

+ * Types may be simple (e.g. int8) or complex (e.g. object). Simple types always define a single column. Complex + * types may define one or more columns depending on their structure. + * + * @param value the type of this {@linkplain Property property}. + * @return a reference to this {@linkplain Property property}. + */ + public final Property type(PropertyType value) { + this.type = value; + return this; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertyType.java new file mode 100644 index 0000000..088363c --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/PropertyType.java @@ -0,0 +1,125 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonSubTypes.Type; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; + +/** + * The base class for property types both primitive and complex. + */ +@JsonTypeInfo(use = Id.NAME, property = "type", visible = true) +@JsonSubTypes({ + // Composite types + @Type(value = ArrayPropertyType.class, name = "array"), + @Type(value = MapPropertyType.class, name = "map"), + @Type(value = ObjectPropertyType.class, name = "object"), + @Type(value = SetPropertyType.class, name = "set"), + @Type(value = TaggedPropertyType.class, name = "tagged"), + @Type(value = TuplePropertyType.class, name = "tuple"), + @Type(value = UdtPropertyType.class, name = "schema"), + // Primitive types + @Type(value = PrimitivePropertyType.class, name = "null"), + @Type(value = PrimitivePropertyType.class, name = "bool"), + @Type(value = PrimitivePropertyType.class, name = "int8"), + @Type(value = PrimitivePropertyType.class, name = "int16"), + @Type(value = PrimitivePropertyType.class, name = "int32"), + @Type(value = PrimitivePropertyType.class, name = "int64"), + @Type(value = PrimitivePropertyType.class, name = "varint"), + @Type(value = PrimitivePropertyType.class, name = "uint8"), + @Type(value = PrimitivePropertyType.class, name = "uint16"), + @Type(value = PrimitivePropertyType.class, name = "uint32"), + @Type(value = PrimitivePropertyType.class, name = "uint64"), + @Type(value = PrimitivePropertyType.class, name = "varuint"), + @Type(value = PrimitivePropertyType.class, name = "float32"), + @Type(value = PrimitivePropertyType.class, name = "float64"), + @Type(value = PrimitivePropertyType.class, name = "float128"), + @Type(value = PrimitivePropertyType.class, name = "decimal"), + @Type(value = PrimitivePropertyType.class, name = "datetime"), + @Type(value = PrimitivePropertyType.class, name = "unixdatetime"), + @Type(value = PrimitivePropertyType.class, name = "binary"), + @Type(value = PrimitivePropertyType.class, name = "guid"), + @Type(value = PrimitivePropertyType.class, name = "utf8"), + @Type(value = PrimitivePropertyType.class, name = "any") +}) +public abstract class PropertyType { + + @JsonProperty + private String apiType; + + @JsonProperty(defaultValue = "true") + private boolean nullable; + + @JsonProperty(required = true) + private TypeKind type; + + protected PropertyType() { + this.nullable(true); + } + + /** + * API-specific type annotations for this {@linkplain Property property}. + * + * @return API-specific type annotations for this {@linkplain Property property}. + */ + public final String apiType() { + return this.apiType; + } + + /** + * Sets API-specific type annotations for this {@linkplain Property property}. + * + * @param value API-specific type annotations for this {@linkplain Property property}. + * @return a reference to this {@linkplain Property property}. + */ + public final PropertyType apiType(String value) { + this.apiType = value; + return this; + } + + /** + * {@code true} if the {@linkplain Property property} can be {@code null}. + *

+ * Default: {@code true} + * + * @return {@code true} if the {@linkplain Property property} can be {@code null, otherwise {@code false}}. + */ + public final boolean nullable() { + return this.nullable; + } + + /** + * Sets a flag indicating whether the {@linkplain Property property} can be {@code null}. + * + * @param value {@code true} indicates that this {@linkplain Property property} can be {@code null}. + * @return a reference to this {@linkplain Property property}. + */ + public final PropertyType nullable(boolean value) { + this.nullable = value; + return this; + } + + /** + * The logical type of this {@linkplain Property property}. + * + * @return the logical type of this {@linkplain Property property}. + */ + public final TypeKind type() { + return this.type; + } + + /** + * Sets the logical type of this {@linkplain Property property}. + * + * @param value the logical type of this {@linkplain Property property}. + * @return a reference to this {@linkplain Property property}. + */ + public final PropertyType type(TypeKind value) { + this.type = value; + return this; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Schema.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Schema.java new file mode 100644 index 0000000..eb855b3 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/Schema.java @@ -0,0 +1,290 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.layouts.Layout; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutCompiler; +import com.fasterxml.jackson.annotation.JsonProperty; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * A schema describes either table or UDT metadata. + *

+ * The schema of a table or UDT describes the structure of row (i.e. which columns and the types of those columns). A + * table schema represents the description of the contents of a collection level row directly. UDTs described nested + * structured objects that may appear either within a table column or within another UDT (i.e. nested UDTs). + */ +public class Schema { + + // Required fields + + @JsonProperty(required = true) + private String name; + + @JsonProperty(defaultValue = "schema", required = true) + private TypeKind type; + + // Optional fields + + @JsonProperty + private String comment; + + @JsonProperty() + private SchemaId id; + + @JsonProperty + private SchemaOptions options; + + @JsonProperty + private List properties; + + @JsonProperty + private SchemaLanguageVersion version; + + // TODO: DANOBLE: how do these properties serialize? + + private List partitionKeys; + private List primaryKeys; + private List staticKeys; + + /** + * Initializes a new instance of the {@link Schema} class. + */ + private Schema() { + this.id = SchemaId.NONE; + this.type = TypeKind.SCHEMA; + this.partitionKeys = Collections.emptyList(); + this.primaryKeys = Collections.emptyList(); + this.staticKeys = Collections.emptyList(); + } + + /** + * An (optional) comment describing the purpose of this schema. + *

+ * Comments are for documentary purpose only and do not affect the schema at runtime. + * + * @return the comment on this {@linkplain Schema schema} or {@code null}, if there is no comment. + */ + public final String comment() { + return this.comment; + } + + /** + * Sets the (optional) comment describing the purpose of this schema. + *

+ * Comments are for documentary purpose only and do not affect the schema at runtime. + * + * @param value a comment on this {@linkplain Schema schema} or {@code null} to remove the comment, if any, on this + * {@linkplain Schema schema}. + * @return a reference to this {@linkplain Schema schema}. + */ + public final Schema comment(String value) { + this.comment = value; + return this; + } + + /** + * Compiles this logical schema into a physical layout that can be used to read and write rows. + * + * @param namespace The namespace within which this schema is defined. + * @return The layout for the schema. + */ + public final Layout compile(Namespace namespace) { + + checkNotNull(namespace, "expected non-null ns"); + checkArgument(namespace.schemas().contains(this)); + + return LayoutCompiler.compile(namespace, this); + } + + /** + * The name of this {@linkplain Schema schema}. + *

+ * The name of a schema MUST be unique within its namespace. Names must begin with an alpha-numeric character and + * can only contain alpha-numeric characters and underscores. + * + * @return the name of this {@linkplain Schema schema} or {@code null}, if the name has not yet been set. + */ + public final String name() { + return this.name; + } + + /** + * Sets the name of this {@linkplain Schema schema}. + *

+ * The name of a schema MUST be unique within its namespace. Names must begin with an alpha-numeric character and + * can only contain alpha-numeric characters and underscores. + * + * @param value a name for this {@linkplain Schema schema}. + * @return a reference to this {@linkplain Schema schema}. + */ + @Nonnull + public final Schema name(@Nonnull String value) { + checkNotNull(value); + this.name = value; + return this; + } + + /** + * Schema-wide options. + * + * @return schema-wide options. + */ + public final SchemaOptions options() { + return this.options; + } + + public final Schema options(SchemaOptions value) { + this.options = value; + return this; + } + + /** + * Parse a JSON fragment and return a schema. + * + * @param value The JSON string value to parse + * @return A logical schema, if the value parses. + */ + public static Optional parse(String value) { + return Json.parse(value, Schema.class); + // TODO: DANOBLE: perform structural validation on the Schema after JSON parsing + } + + /** + * An (optional) list of zero or more logical paths that form the partition key. + *

+ * All paths referenced MUST map to a property within the schema. This field is never null. + * + * @return list of zero or more logical paths that form the partition key + */ + @Nullable + public final List partitionKeys() { + return this.partitionKeys; + } + + public final Schema partitionKeys(@Nullable List value) { + this.partitionKeys = value != null ? value : Collections.emptyList(); + return this; + } + + /** + * An (optional) list of zero or more logical paths that form the primary sort key. + *

+ * All paths referenced MUST map to a property within the schema. This field is never null. + * + * @return list of zero or more logical paths that form the partition key + */ + @Nullable + public final List primarySortKeys() { + return this.primaryKeys; + } + + public final Schema primarySortKeys(ArrayList value) { + this.primaryKeys = value != null ? value : Collections.emptyList(); + return this; + } + + /** + * A list of zero or more property definitions that define the columns within the schema. + *

+ * This field is never null. + * + * @return list of zero or more property definitions that define the columns within the schema + */ + @Nonnull + public final List properties() { + return this.properties; + } + + public final Schema properties(List value) { + this.properties = value != null ? value : Collections.emptyList(); + return this; + } + + /** + * The unique identifier for a schema. + *

+ * Identifiers must be unique within the scope of the database in which they are used. + * + * @return the unique identifier for a schema. + */ + public final SchemaId schemaId() { + return this.id; + } + + public final Schema schemaId(SchemaId value) { + this.id = value; + return this; + } + + /** + * A list of zero or more logical paths that hold data shared by all documents with same partition key. + *

+ * All paths referenced MUST map to a property within the schema. + *

+ * This field is never null. + * + * @return A list of zero or more logical paths that hold data shared by all documents with same partition key. + */ + @Nonnull + public final List staticKeys() { + return this.staticKeys; + } + + public final Schema staticKeys(List value) { + this.staticKeys = value != null ? value : Collections.emptyList(); + return this; + } + + /** + * Returns a JSON string representation of the current {@link Schema}. + * + * @return a JSON string representation of the current {@link Schema} + */ + @Override + public String toString() { + return Json.toString(this); + } + + /** + * The type of this schema. + *

+ * This value MUST be {@link TypeKind#SCHEMA}. + * + * @return the type of this schema. + */ + public final TypeKind type() { + return this.type; + } + + public final Schema type(TypeKind value) { + this.type = value; + return this; + } + + /** + * The version of the HybridRow Schema Definition Language used to encode this schema. + * + * @return the version of the HybridRow Schema Definition Language used to encode this schema. + */ + public final SchemaLanguageVersion version() { + return this.version; + } + + public final Schema version(SchemaLanguageVersion value) { + this.version = value; + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaException.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaException.java new file mode 100644 index 0000000..6d53066 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaException.java @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import java.io.Serializable; + +public final class SchemaException extends RuntimeException implements Serializable { + + public SchemaException() { + } + + public SchemaException(String message) { + super(message); + } + + public SchemaException(String message, RuntimeException innerException) { + super(message, innerException); + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaHash.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaHash.java new file mode 100644 index 0000000..1eb42e4 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaHash.java @@ -0,0 +1,213 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.azure.data.cosmos.serialization.hybridrow.HashCode128; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.azure.data.cosmos.serialization.hybridrow.internal.Murmur3Hash; + +import java.util.Optional; +import java.util.stream.Stream; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.lenientFormat; + +public final class SchemaHash { + + /** + * Computes the logical hash for a logical schema. + * + * @param namespace The namespace within which {@code schema} is defined. + * @param schema The logical schema to compute the hash of. + * @param seed The seed to initialized the hash function. + * @return The logical 128-bit hash as a two-tuple (low, high). + */ + public static HashCode128 computeHash(Namespace namespace, Schema schema, HashCode128 seed) { + HashCode128 hash = seed; + + hash = Murmur3Hash.Hash128(schema.schemaId().value(), hash); + hash = Murmur3Hash.Hash128(schema.type().value(), hash); + hash = SchemaHash.computeHash(namespace, schema.options(), hash); + + if (schema.partitionKeys() != null) { + for (PartitionKey partitionKey : schema.partitionKeys()) { + hash = SchemaHash.computeHash(namespace, partitionKey, hash); + } + } + + if (schema.primarySortKeys() != null) { + for (PrimarySortKey p : schema.primarySortKeys()) { + hash = SchemaHash.computeHash(namespace, p, hash); + } + } + + if (schema.staticKeys() != null) { + for (StaticKey p : schema.staticKeys()) { + hash = SchemaHash.computeHash(namespace, p, hash); + } + } + + if (schema.properties() != null) { + for (Property p : schema.properties()) { + hash = SchemaHash.computeHash(namespace, p, hash); + } + } + + return hash; + } + + private static HashCode128 computeHash(Namespace namespace, SchemaOptions options, HashCode128 seed) { + + HashCode128 hash = seed; + + hash = Murmur3Hash.Hash128(options != null && options.disallowUnschematized(), hash); + hash = Murmur3Hash.Hash128(options != null && options.enablePropertyLevelTimestamp(), hash); + hash = Murmur3Hash.Hash128(options != null && options.disableSystemPrefix(), hash); + + return hash; + } + + private static HashCode128 computeHash(Namespace ns, Property p, HashCode128 seed) { + + HashCode128 hash = seed; + + hash = Murmur3Hash.Hash128(p.path(), hash); + hash = SchemaHash.computeHash(ns, p.type(), hash); + + return hash; + } + + private static HashCode128 computeHash(Namespace namespace, PropertyType p, HashCode128 seed) { + + HashCode128 hash = seed; + + hash = Murmur3Hash.Hash128(p.type().value(), hash); + hash = Murmur3Hash.Hash128(p.nullable(), hash); + + if (p.apiType() != null) { + hash = Murmur3Hash.Hash128(p.apiType(), hash); + } + + if (p instanceof PrimitivePropertyType) { + + PrimitivePropertyType pp = (PrimitivePropertyType) p; + + hash = Murmur3Hash.Hash128(pp.storage().value(), hash); + hash = Murmur3Hash.Hash128(pp.length(), hash); + + return hash; + } + + checkState(p instanceof ScopePropertyType); + ScopePropertyType pp = (ScopePropertyType) p; + hash = Murmur3Hash.Hash128(pp.immutable(), hash); + + if (p instanceof ArrayPropertyType) { + ArrayPropertyType spp = (ArrayPropertyType) p; + if (spp.items() != null) { + hash = SchemaHash.computeHash(namespace, spp.items(), hash); + } + return hash; + } + + if (p instanceof ObjectPropertyType) { + ObjectPropertyType spp = (ObjectPropertyType) p; + if (spp.properties() != null) { + for (Property opp : spp.properties()) { + hash = SchemaHash.computeHash(namespace, opp, hash); + } + } + return hash; + } + + if (p instanceof MapPropertyType) { + + MapPropertyType spp = (MapPropertyType) p; + + if (spp.keys() != null) { + hash = SchemaHash.computeHash(namespace, spp.keys(), hash); + } + + if (spp.values() != null) { + hash = SchemaHash.computeHash(namespace, spp.values(), hash); + } + + return hash; + } + + if (p instanceof SetPropertyType) { + + SetPropertyType spp = (SetPropertyType) p; + + if (spp.items() != null) { + hash = SchemaHash.computeHash(namespace, spp.items(), hash); + } + + return hash; + } + + if (p instanceof TaggedPropertyType) { + + TaggedPropertyType spp = (TaggedPropertyType) p; + + if (spp.items() != null) { + for (PropertyType pt : spp.items()) { + hash = SchemaHash.computeHash(namespace, pt, hash); + } + } + + return hash; + } + + if (p instanceof TuplePropertyType) { + + TuplePropertyType spp = (TuplePropertyType) p; + + if (spp.items() != null) { + for (PropertyType pt : spp.items()) { + hash = SchemaHash.computeHash(namespace, pt, hash); + } + } + + return hash; + } + + if (p instanceof UdtPropertyType) { + + Stream schemaStream = namespace.schemas().stream(); + UdtPropertyType spp = (UdtPropertyType) p; + Optional udtSchema; + + if (spp.schemaId() == SchemaId.INVALID) { + udtSchema = schemaStream.filter(schema -> schema.name().equals(spp.name())).findFirst(); + } else { + udtSchema = schemaStream.filter(schema -> schema.schemaId().equals(spp.schemaId())).findFirst(); + udtSchema.ifPresent(schema -> checkState(schema.name().equals(spp.name()), + "Ambiguous schema reference: '%s:%s'", spp.name(), spp.schemaId())); + } + + checkState(udtSchema.isPresent(), "Cannot resolve schema reference '{0}:{1}'", spp.name(), spp.schemaId()); + return SchemaHash.computeHash(namespace, udtSchema.get(), hash); + } + + throw new IllegalStateException(lenientFormat("unrecognized property type: %s", p.getClass())); + } + + private static HashCode128 computeHash(Namespace namespace, PartitionKey key, HashCode128 seed) { + return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed); + } + + private static HashCode128 computeHash(Namespace namespace, PrimarySortKey key, HashCode128 seed) { + HashCode128 hash = seed; + if (key != null) { + hash = Murmur3Hash.Hash128(key.path(), hash); + hash = Murmur3Hash.Hash128(key.direction().value(), hash); + } + return hash; + } + + private static HashCode128 computeHash(Namespace ns, StaticKey key, HashCode128 seed) { + return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed); + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaLanguageVersion.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaLanguageVersion.java new file mode 100644 index 0000000..4fb4663 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaLanguageVersion.java @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import java.util.HashMap; + +/** + * Versions of the HybridRow Schema Description Language. + */ +public enum SchemaLanguageVersion { + /** + * Initial version of the HybridRow Schema Description Lanauge. + */ + V1((byte) 0, "v1"); + + public static final int BYTES = Byte.BYTES; + + private static HashMap mappings; + private String friendlyName; + private byte value; + + SchemaLanguageVersion(byte value, String text) { + this.value = value; + this.friendlyName = text; + mappings().put(value, this); + } + + /** + * Returns the friendly name of this enum constant. + * + * @return the friendly name of this enum constant. + * @see #toString() + */ + public String friendlyName() { + return this.friendlyName; + } + + public static SchemaLanguageVersion from(byte value) { + return mappings().get(value); + } + + /** + * Returns the friendly name of this enum constant. + * + * @return the friendly name of this enum constant. + * @see #friendlyName() + */ + @Override + public String toString() { + return this.friendlyName; + } + + public byte value() { + return this.value; + } + + private static HashMap mappings() { + if (mappings == null) { + synchronized (SchemaLanguageVersion.class) { + if (mappings == null) { + mappings = new HashMap<>(); + } + } + } + return mappings; + } + + +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaOptions.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaOptions.java new file mode 100644 index 0000000..4db307e --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaOptions.java @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +/** + * Describes the set of options that apply to the entire schema and the way it is validated. + */ +public class SchemaOptions { + + private boolean disableSystemPrefix; + private boolean disallowUnschematized; + private boolean enablePropertyLevelTimestamp; + + /** + * {@code true} if prefixing system properties with a prefix of {@code "__sys_"} is disabled. + *

+ * The system property prefix is required to distinguish properties owned by the store layer. + * + * @return {@code true} if prefixing system properties with a prefix of {@code "__sys_"} is disabled. + */ + public final boolean disableSystemPrefix() { + return this.disableSystemPrefix; + } + + public final void disableSystemPrefix(boolean value) { + this.disableSystemPrefix = value; + } + + /** + * {@code true} if structural schema validation is enabled. + *

+ * When structural schema validation is enabled then attempting to store an unschematized + * path in the row, or a value whose type does not conform to the type constraints defined for that + * path within the schema will lead to a schema validation error. When structural schema validation is + * NOT enabled, then storing an unschematized path or non-confirming value will lead to a sparse + * column override of the path. The value will be stored (and any existing value at that path will be + * overwritten). No error will be given. + * + * @return {@code true} if structural schema validation is enabled. + */ + public final boolean disallowUnschematized() { + return this.disallowUnschematized; + } + + public final void disallowUnschematized(boolean value) { + this.disallowUnschematized = value; + } + + /** + * {@code true} if behavior in the Schema that acts based on property level timestamps is triggered. + *

+ * In Cassandra, this means that new columns are added for each top level property that has values of the client + * side timestamp. This is then used in conflict resolution to independently resolve each property based on the + * timestamp value of that property. + * + * @return {@code true} if behavior in the Schema that acts based on property level timestamps is triggered. + */ + public final boolean enablePropertyLevelTimestamp() { + return this.enablePropertyLevelTimestamp; + } + + public final void enablePropertyLevelTimestamp(boolean value) { + this.enablePropertyLevelTimestamp = value; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaValidator.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaValidator.java new file mode 100644 index 0000000..af6af00 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SchemaValidator.java @@ -0,0 +1,326 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.azure.data.cosmos.core.Json; +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.google.common.base.Strings; +import org.checkerframework.checker.nullness.qual.NonNull; + +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.lenientFormat; + +public final class SchemaValidator { + + public static void validate(@NonNull final Namespace namespace) { + + checkNotNull(namespace, "expected non-null namespace"); + + final int initialCapacity = namespace.schemas().size(); + + final Map nameDupCheck = new HashMap<>(initialCapacity); + final Map nameVersioningCheck = new HashMap<>(initialCapacity); + final Map idDupCheck = new HashMap<>(initialCapacity); + + for (Schema schema : namespace.schemas()) { + + SchemaIdentification identification = SchemaIdentification.of(schema.name(), schema.schemaId()); + + Assert.isValidIdentifier(identification.name(), "Schema name"); + Assert.isValidSchemaId(identification.id(), "Schema id"); + Assert.duplicateCheck(identification.id(), schema, idDupCheck, "Schema id", "Namespace"); + Assert.duplicateCheck(identification, schema, nameDupCheck, "Schema reference", "Namespace"); + + nameVersioningCheck.compute(schema.name(), (name, count) -> count == null ? 1 : count + 1); + } + + // Enable id-less Schema references for all types with a unique version in the namespace + + for (Schema schema : namespace.schemas()) { + if (nameVersioningCheck.get(schema.name()) == 1) { + Assert.duplicateCheck( + SchemaIdentification.of(schema.name(), SchemaId.NONE), schema, nameDupCheck, + "Schema reference", "Namespace" + ); + } + } + + SchemaValidator.visit(namespace, nameDupCheck, idDupCheck); + } + + /** + * Visit an entire namespace and validate its constraints. + * + * @param namespace The {@link Namespace} to validate. + * @param schemas A map from schema names within the namespace to their schemas. + * @param ids A map from schema ids within the namespace to their schemas. + */ + private static void visit( + Namespace namespace, Map schemas, Map ids) { + for (Schema schema : namespace.schemas()) { + SchemaValidator.visit(schema, schemas, ids); + } + } + + /** + * Visit a single schema and validate its constraints. + * + * @param schema The {@link Schema} to validate. + * @param schemas A map from schema names within the namespace to their schemas. + * @param ids A map from schema ids within the namespace to their schemas. + */ + private static void visit(Schema schema, Map schemas, Map ids) { + + Assert.areEqual( + schema.type(), TypeKind.SCHEMA, lenientFormat("The type of a schema MUST be %s: %s", TypeKind.SCHEMA, + schema.type()) + ); + + HashMap pathDupCheck = new HashMap<>(schema.properties().size()); + + for (Property p : schema.properties()) { + Assert.duplicateCheck(p.path(), p, pathDupCheck, "Property path", "Schema"); + } + + for (PartitionKey pk : schema.partitionKeys()) { + Assert.exists(pk.path(), pathDupCheck, "Partition key column", "Schema"); + } + + for (PrimarySortKey ps : schema.primarySortKeys()) { + Assert.exists(ps.path(), pathDupCheck, "Primary sort key column", "Schema"); + } + + for (StaticKey sk : schema.staticKeys()) { + Assert.exists(sk.path(), pathDupCheck, "Static key column", "Schema"); + } + + for (Property p : schema.properties()) { + SchemaValidator.visit(p, schema, schemas, ids); + } + } + + private static void visit( + Property p, Schema s, Map schemas, Map ids) { + + Assert.isValidIdentifier(p.path(), "Property path"); + SchemaValidator.visit(p.type(), null, schemas, ids); + } + + private static void visit( + PropertyType p, + PropertyType parent, + Map schemas, + Map ids) { + + if (p instanceof PrimitivePropertyType) { + PrimitivePropertyType pp = (PrimitivePropertyType) p; + Assert.isTrue(pp.length() >= 0, "Length MUST be positive"); + if (parent != null) { + Assert.areEqual(pp.storage(), StorageKind.SPARSE, "Nested fields MUST have storage kind SPARSE"); + } + return; + } + if (p instanceof ArrayPropertyType) { + ArrayPropertyType ap = (ArrayPropertyType) p; + if (ap.items() != null) { + SchemaValidator.visit(ap.items(), p, schemas, ids); + } + return; + } + if (p instanceof MapPropertyType) { + MapPropertyType mp = (MapPropertyType) p; + SchemaValidator.visit(mp.keys(), p, schemas, ids); + SchemaValidator.visit(mp.values(), p, schemas, ids); + return; + } + if (p instanceof SetPropertyType) { + SetPropertyType sp = (SetPropertyType) p; + SchemaValidator.visit(sp.items(), p, schemas, ids); + return; + } + if (p instanceof TaggedPropertyType) { + TaggedPropertyType gp = (TaggedPropertyType) p; + for (PropertyType item : gp.items()) { + SchemaValidator.visit(item, p, schemas, ids); + } + return; + } + if (p instanceof TuplePropertyType) { + TuplePropertyType tp = (TuplePropertyType) p; + for (PropertyType item : tp.items()) { + SchemaValidator.visit(item, p, schemas, ids); + } + return; + } + if (p instanceof ObjectPropertyType) { + ObjectPropertyType op = (ObjectPropertyType) p; + Map pathDupCheck = new HashMap<>(op.properties().size()); + for (Property nested : op.properties()) { + Assert.duplicateCheck(nested.path(), nested, pathDupCheck, "Property path", "Object"); + SchemaValidator.visit(nested.type(), p, schemas, ids); + } + return; + } + if (p instanceof UdtPropertyType) { + UdtPropertyType up = (UdtPropertyType) p; + Assert.exists(SchemaIdentification.of(up.name(), up.schemaId()), schemas, "Schema reference", "Namespace"); + if (up.schemaId() != SchemaId.INVALID) { + Schema s = Assert.exists(up.schemaId(), ids, "Schema id", "Namespace"); + Assert.areEqual(up.name(), s.name(), lenientFormat("Schema name '%s' does not match the name of " + + "schema with id '%s': %s", up.name(), up.schemaId(), s.name())); + } + return; + } + throw new IllegalStateException(lenientFormat("Unknown property type: %s", p.getClass())); + } + + private static class Assert { + + /** + * Validate two values are equal. + * + * @param Type of the values to compare. + * @param left The left value to compare. + * @param right The right value to compare. + * @param message Diagnostic message if the comparison fails. + */ + static void areEqual(T left, T right, String message) { + if (!left.equals(right)) { + throw new SchemaException(message); + } + } + + /** + * Validate {@code key} does not already appear within the given scope. + * + * @param The type of the keys within the scope. + * @param The type of the values within the scope. + * @param key The key to check. + * @param value The value to add to the scope if there is no duplicate. + * @param scope The set of existing values within the scope. + * @param label Diagnostic label describing {@code key}. + * @param scopeLabel Diagnostic label describing {@code scope}. + */ + static void duplicateCheck( + TKey key, TValue value, Map scope, String label, String scopeLabel) { + if (scope.containsKey(key)) { + throw new SchemaException(lenientFormat("%s must be unique within a %s: %s", label, scopeLabel, key)); + } + scope.put(key, value); + } + + /** + * Validate {@code key} does appear within the given scope. + * + * @param The type of the keys within the scope. + * @param The type of the values within the scope. + * @param key The key to check. + * @param scope The set of existing values within the scope. + * @param label Diagnostic label describing {@code key}. + * @param scopeLabel Diagnostic label describing {@code scope}. + */ + static TValue exists(TKey key, Map scope, String label, String scopeLabel) { + TValue value = scope.get(key); + if (value == null) { + throw new SchemaException(lenientFormat("%s must exist within a %s: %s", label, scopeLabel, key)); + } + return value; + } + + /** + * Validate a predicate is true. + * + * @param predicate The predicate to check. + * @param message Diagnostic message if the comparison fails. + */ + static void isTrue(boolean predicate, String message) { + if (!predicate) { + throw new SchemaException(message); + } + } + + /** + * Validate {@code identifier} contains only characters valid in a schema identifier. + * + * @param identifier The identifier to check. + * @param label Diagnostic label describing {@code identifier}. + */ + static void isValidIdentifier(String identifier, String label) { + if (Strings.isNullOrEmpty(identifier)) { + throw new SchemaException(lenientFormat("%s must be a valid identifier: %s", label, identifier)); + } + } + + /** + * Validate a {@link SchemaId}. + * + * @param id The id to check. + * @param label Diagnostic label describing {@code id}. + */ + static void isValidSchemaId(SchemaId id, String label) { + if (id == SchemaId.INVALID) { + throw new SchemaException(lenientFormat("%s cannot be 0", label)); + } + } + } + + private static class SchemaIdentification implements Comparable { + + private final SchemaId id; + private final String name; + + private SchemaIdentification(@Nonnull final String name, @Nonnull final SchemaId id) { + checkNotNull(name, "expected non-null name"); + checkNotNull(id, "expected non-null id"); + this.name = name; + this.id = id; + } + + @Override + public int compareTo(@Nonnull SchemaIdentification other) { + checkNotNull(other, "expected non-null other"); + int result = Integer.compare(this.id.value(), other.id.value()); + return result == 0 ? this.name().compareTo(other.name()) : result; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (null == other || this.getClass() != other.getClass()) { + return false; + } + SchemaIdentification that = (SchemaIdentification) other; + return this.id.equals(that.id) && this.name.equals(that.name); + } + + @Override + public int hashCode() { + return Objects.hash(this.id, this.name); + } + + public SchemaId id() { + return this.id; + } + + public String name() { + return this.name; + } + + public static SchemaIdentification of(@NonNull String name, @NonNull SchemaId id) { + return new SchemaIdentification(name, id); + } + + @Override + public String toString() { + return Json.toString(this); + } + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ScopePropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ScopePropertyType.java new file mode 100644 index 0000000..d8c68e6 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/ScopePropertyType.java @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +public abstract class ScopePropertyType extends PropertyType { + + private boolean immutable; + + /** + * {@code true} if the property's child elements cannot be mutated in place. + *

+ * Immutable properties can still be replaced in their entirety. + * + * @return {@code true} if the property's child elements cannot be mutated in place. + */ + public final boolean immutable() { + return this.immutable; + } + + public final void immutable(boolean value) { + this.immutable = value; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SetPropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SetPropertyType.java new file mode 100644 index 0000000..6dcdff3 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SetPropertyType.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +/** + * Set properties represent an unbounded set of zero or more unique items. + *

+ * Sets may be typed or untyped. Within typed sets, all items MUST be the same type. The + * type of items is specified via {@link #items}. Typed sets may be stored more efficiently + * than untyped sets. When {@link #items} is unspecified, the set is untyped and its items + * may be heterogeneous. + *

+ * Each item within a set must be unique. Uniqueness is defined by the HybridRow encoded sequence + * of bytes for the item. + */ +public class SetPropertyType extends ScopePropertyType { + /** + * (Optional) type of the elements of the set, if a typed set, otherwise null. + */ + private PropertyType items; + + public final PropertyType items() { + return this.items; + } + + public final SetPropertyType items(PropertyType value) { + this.items = value; + return this; + } +} \ 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 new file mode 100644 index 0000000..31e54e4 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/SortDirection.java @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +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. + */ +public enum SortDirection { + /** + * Sorts from the lowest to the highest value. + */ + ASCENDING(0), + + /** + * Sorts from the highests to the lowest value. + */ + DESCENDING(1); + + public static final int BYTEST = Integer.BYTES; + + 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; + } + + public int value() { + return this.value; + } + + public static SortDirection from(int 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/schemas/StaticKey.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StaticKey.java new file mode 100644 index 0000000..ede2e4a --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StaticKey.java @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +/** + * Describes a property or property set whose values MUST be the same for all rows that share the same partition key. + */ +public class StaticKey { + + private String path; + + /** + * The logical path of the referenced property. + *

+ * Static path MUST refer to properties defined within the same {@link Schema}. + * + * @return the logical path of the referenced property. + */ + public final String path() { + return this.path; + } + + public final StaticKey path(String value) { + this.path = value; + return this; + } +} \ 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 new file mode 100644 index 0000000..4382539 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/StorageKind.java @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +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 storage placement for primitive properties. + */ +public enum StorageKind { + /** + * The property does not define a column + *

+ * This is indicative of an error in the the column specification. + */ + NONE(-1, "none"), + + /** + * The property defines a sparse column + *

+ * Columns marked as sparse consume no space in the row when not present. When present they appear in an unordered + * linked list at the end of the row. Access time for sparse columns is proportional to the number of sparse columns + * in the row. + */ + SPARSE(0, "sparse"), + + /** + * The property is a fixed-length, space-reserved column + *

+ * The column will consume 1 null-bit, and its byte-width regardless of whether the value is present in the row. + */ + FIXED(1, "fixed"), + + /** + * The property is a variable-length column. + *

+ * The column will consume 1 null-bit regardless of whether the value is present. When the value is present it will + * also consume a variable number of bytes to encode the length preceding the actual value. + *

+ * When a long value is marked variable then a null-bit is reserved and the value is optionally encoded as + * variable if small enough to fit, otherwise the null-bit is set and the value is encoded as sparse. + */ + VARIABLE(2, "variable"); + + public static final int BYTES = Integer.BYTES; + + 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 Int2ReferenceArrayMap<>(values, storageKinds); + }); + + private final String friendlyName; + private final int value; + + StorageKind(int value, String friendlyName) { + this.friendlyName = friendlyName; + this.value = value; + } + + public String friendlyName() { + return this.friendlyName; + } + + public static StorageKind from(int value) { + return mappings.get().get(value); + } + + @Override + public String toString() { + return this.friendlyName; + } + + public int value() { + return this.value; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TaggedPropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TaggedPropertyType.java new file mode 100644 index 0000000..cd19630 --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TaggedPropertyType.java @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tagged properties pair one or more typed values with an API-specific uint8 type code. + *

+ * The {@code UInt8} type code is implicitly in position 0 within the resulting tagged and should not be specified in + * {@link #items()}. + */ +public class TaggedPropertyType extends ScopePropertyType { + + public static final int MAX_TAGGED_ARGUMENTS = 2; + public static final int MIN_TAGGED_ARGUMENTS = 1; + + private List items; + + /** + * Initializes a new instance of the {@link TaggedPropertyType} class. + */ + public TaggedPropertyType() { + this.items = new ArrayList<>(); + } + + /** + * Types of the elements of the tagged in element order. + * + * @return a list of property types. + */ + public final List items() { + return this.items; + } + + public final TaggedPropertyType items(List value) { + this.items = value != null ? value : new ArrayList<>(); + return this; + } +} \ No newline at end of file diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TuplePropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TuplePropertyType.java new file mode 100644 index 0000000..e7571ae --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TuplePropertyType.java @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tuple properties represent a typed, finite, ordered set of two or more items. + */ +public class TuplePropertyType extends ScopePropertyType { + /** + * Types of the elements of the tuple in element order. + */ + private List items; + + /** + * Initializes a new instance of the {@link TuplePropertyType} class. + */ + public TuplePropertyType() { + this.items = new ArrayList(); + } + + /** + * Types of the elements of the tuple in element order. + * + * @return types of the elements of the tuple in element order. + */ + public final List items() { + return this.items; + } + + public final void items(List value) { + this.items = value != null ? value : new ArrayList(); + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..a3b357d --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/TypeKind.java @@ -0,0 +1,236 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.fasterxml.jackson.annotation.JsonEnumDefaultValue; +import com.google.common.base.Suppliers; +import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; +import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; + +import java.util.Arrays; +import java.util.function.Supplier; + +/** + * Describes the logical type of a property. + */ +public enum TypeKind { + /** + * Reserved. + */ + @JsonEnumDefaultValue + INVALID(0, "invalid"), + + /** + * The literal null. + *

+ * When used as a fixed column, only a presence bit is allocated. When used as a sparse column, a sparse value with + * 0-length payload is written. + */ + NULL(1, "null"), + + /** + * A boolean property. + *

+ * Boolean properties are allocated a single bit when schematized within a row. + */ + BOOLEAN(2, "bool"), + + /** + * 8-bit signed integer. + */ + INT_8(3, "int8"), + + /** + * 16-bit signed integer. + */ + INT_16(4, "int16"), + + /** + * 32-bit signed integer. + */ + INT_32(5, "int32"), + + /** + * 64-bit signed integer. + */ + INT_64(6, "int64"), + + /** + * 8-bit unsigned integer. + */ + UINT_8(7, "uint8"), + + /** + * 16-bit unsigned integer. + */ + UINT_16(8, "uint16"), + + /** + * 32-bit unsigned integer. + */ + UINT_32(9, "uint32"), + + /** + * 64-bit unsigned integer. + */ + UINT_64(10, "uint64"), + + /** + * Variable length encoded signed integer. + */ + VAR_INT(11, "varint"), + + /** + * Variable length encoded unsigned integer. + */ + VAR_UINT(12, "varuint"), + + /** + * 32-bit IEEE 754 floating point value. + */ + FLOAT_32(13, "float32"), + + /** + * 64-bit IEEE 754 floating point value. + */ + FLOAT_64(14, "float64"), + + /** + * 128-bit IEEE 754-2008 floating point value. + */ + FLOAT_128(15, "float128"), + + /** + * 128-bit floating point value. + * + * @see java.math.BigDecimal + */ + DECIMAL(16, "decimal"), + + /** + * 64-bit date/time value in 100ns increments from C# epoch. + * + * @see java.time.OffsetDateTime + */ + DATE_TIME(17, "datetime"), + + /** + * 64-bit date/time value in milliseconds increments from Unix epoch. + * + * @see com.azure.data.cosmos.serialization.hybridrow.UnixDateTime + */ + UNIX_DATE_TIME(18, "unixdatetime"), + + /** + * 128-bit globally unique identifier (in little-endian byte order). + */ + GUID(19, "guid"), + + /** + * 12-byte MongoDB Object Identifier (in little-endian byte order). + */ + MONGODB_OBJECT_ID(20, "mongodb.objectid"), + + /** + * Zero to MAX_ROW_SIZE bytes encoded as UTF-8 code points. + */ + UTF_8(21, "utf8"), + + /** + * Zero to MAX_ROW_SIZE untyped bytes. + */ + BINARY(22, "binary"), + + /** + * An object property. + */ + OBJECT(23, "object"), + + /** + * An array property, either typed or untyped. + */ + ARRAY(24, "array"), + + /** + * A set property, either typed or untyped. + */ + SET(25, "set"), + + /** + * A map property, either typed or untyped. + */ + MAP(26, "map"), + + /** + * A tuple property. Tuples are typed, finite, ordered, sets. + */ + TUPLE(27, "tuple"), + + /** + * A tagged property. + *

+ * Tagged properties pair one or more typed values with an API-specific uint8 type code. + */ + TAGGED(28, "tagged"), + + /** + * A row with schema. + *

+ * May define either a top-level table schema or a UDT (nested row). + */ + SCHEMA(29, "schema"), + + /** + * An untyped sparse field. + *

+ * May only be used to define the type of a field within a nested scope. + */ + ANY(30, "any"); + + public static final int BYTES = Integer.BYTES; + + 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; + private final int value; + + TypeKind(final int value, final String friendlyName) { + this.friendlyName = friendlyName; + this.value = value; + } + + /** + * Returns the friendly name of this enum constant. + * + * @return the friendly name of this enum constant. + * @see #toString() + */ + public String friendlyName() { + return this.friendlyName; + } + + public static TypeKind from(int value) { + return mappings.get().get(value); + } + + /** + * Returns the friendly name of this enum constant. + * + * @return the friendly name of this enum constant. + * @see #friendlyName() + */ + @Override + public String toString() { + return this.friendlyName; + } + + public int value() { + return this.value; + } +} diff --git a/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/UdtPropertyType.java b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/UdtPropertyType.java new file mode 100644 index 0000000..34e9bfc --- /dev/null +++ b/java/src/main/java/com/azure/data/cosmos/serialization/hybridrow/schemas/UdtPropertyType.java @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import com.azure.data.cosmos.serialization.hybridrow.SchemaId; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * UDT properties represent nested structures with an independent schema. + *

+ * UDT properties include a nested row within an existing row as a column. The schema of the nested row may be evolved + * independently of the outer row. Changes to the independent schema affect all outer schemas where the UDT is used. + */ +public class UdtPropertyType extends ScopePropertyType { + + @JsonProperty(required = true) + private String name; + + @JsonProperty(required = true) + private SchemaId id; + + /** + * The name of the UDT schema defining the structure of a nested row. + *

+ * The UDT schema MUST be defined within the same {@link Namespace} as the schema that references it. + * + * @return the identifier of the UDT schema defining the structure of a nested row. + */ + public final String name() { + return this.name; + } + + /** + * Sets the name of the UDT schema defining the structure of a nested row. + *

+ * The UDT schema MUST be defined within the same {@link Namespace} as the schema that references it. + * + * @param value the name of the UDT schema defining the structure of a nested row. + * @return a reference to this {@link UdtPropertyType}. + */ + public final UdtPropertyType name(String value) { + this.name = value; + return this; + } + + /** + * The unique identifier of the UDT schema defining the structure of a nested row. + *

+ * Optional uniqueifier if multiple versions of {@link #name} appears within the {@link Namespace}. + *

+ * If multiple versions of a UDT are defined within a {@link Namespace} the globally unique identifier of the + * specific version referenced MUST be provided. + * + * @return the unique identifier of the UDT schema defining the structure of a nested row or {@code null}. + */ + public final SchemaId schemaId() { + return this.id; + } + + /** + * Sets the unique identifier of the UDT schema defining the structure of a nested row. + *

+ * Optional uniqueifier if multiple versions of {@link #name} appears within the {@link Namespace}. + *

+ * If multiple versions of a UDT are defined within a {@link Namespace} the globally unique identifier of the + * specific version referenced MUST be provided. + * + * @param value the unique identifier of the UDT schema defining the structure of a nested row or {@code null}. + * @return a reference to this {@link UdtPropertyType}. + */ + public final UdtPropertyType schemaId(SchemaId value) { + this.id = value; + return this; + } +} diff --git a/java/src/test/java/com/azure/data/cosmos/core/Utf8StringTest.java b/java/src/test/java/com/azure/data/cosmos/core/Utf8StringTest.java new file mode 100644 index 0000000..2f66089 --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/core/Utf8StringTest.java @@ -0,0 +1,505 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import com.google.common.collect.ImmutableList; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Optional; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; + +@Test(groups = "unit") +public class Utf8StringTest { + + @Test + public void testIsEmpty() { + + Utf8String value; + + value = Utf8String.transcodeUtf16(""); + assertTrue(value.isEmpty()); + assertSame(value, Utf8String.EMPTY); + + value = Utf8String.fromUnsafe(Unpooled.EMPTY_BUFFER); + assertTrue(value.isEmpty()); + assertSame(value, Utf8String.EMPTY); + + Optional optional = Utf8String.from(Unpooled.EMPTY_BUFFER); + assertTrue(optional.isPresent()); + assertTrue(optional.get().isEmpty()); + assertSame(optional.get(), Utf8String.EMPTY); + } + + @Test + public void testIsNull() { + Utf8String value = Utf8String.transcodeUtf16(null); + assertTrue(value.isNull()); + assertSame(value, Utf8String.NULL); + } + + @Test + public void testChars() { + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testCodePoints(UnicodeText item) { + Utf8String value = Utf8String.transcodeUtf16(item.value()); + assertEquals(value.codePoints().iterator(), item.value().codePoints().iterator()); + } + + @Test(dataProvider = "unicodeAlphabetDataProvider") + public void testCompareTo(UnicodeAlphabet item) { + for (int i = 0, j = item.letters.length - 2; i < j; i += 2, j -= 2) { + try { + item.testCompareTo(i, j); // upper case letter + item.testCompareTo(i + 1, j + 1); // lower case letter + } catch (Throwable throwable) { + throw throwable; + } + } + } + + @SuppressWarnings("EqualsWithItself") + @Test(dataProvider = "unicodeTextDataProvider") + public void testCompareTo(UnicodeText item) { + + Utf8String value = Utf8String.transcodeUtf16(item.value()); + assertEquals(value.compareTo(value), 0); + assertEquals(value.compareTo(item.value()), 0); + + Utf8String unsafe = Utf8String.fromUnsafe(item.byteBuf()); + assertEquals(unsafe.compareTo(value), 0); + assertEquals(unsafe.compareTo(item.value()), 0); + + Optional optional = Utf8String.from(item.byteBuf()); + assertTrue(optional.isPresent()); + assertEquals(optional.get().compareTo(value), 0); + assertEquals(optional.get().compareTo(item.value()), 0); + + // TODO: DANOBLE: create new test from the following assertions because they don't relate to the item under test + + assertThrows(NullPointerException.class, () -> { + //noinspection ConstantConditions,ResultOfMethodCallIgnored + value.compareTo((Utf8String) null); + }); + + assertEquals(Utf8String.NULL.compareTo(item.value()), -1); + assertEquals(Utf8String.NULL.compareTo((String) null), 0); + assertEquals(Utf8String.EMPTY.compareTo((String) null), 1); + assertEquals(Utf8String.EMPTY.compareTo(Utf8String.NULL), 1); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testEncodedLength(UnicodeText item) { + final int encodedLength = item.buffer.length; + assertEquals(Utf8String.from(item.byteBuf()).orElseThrow(AssertionError::new).encodedLength(), encodedLength); + assertEquals(Utf8String.fromUnsafe(item.byteBuf()).encodedLength(), encodedLength); + assertEquals(Utf8String.transcodeUtf16(item.value()).encodedLength(), encodedLength); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testTestEquals(UnicodeText item) { + + TestEquals testEquals = new TestEquals(item); + + testEquals.invoke(item.byteBuf()); + testEquals.invoke(item.value()); + testEquals.invoke(Utf8String.fromUnsafe(item.byteBuf())); + testEquals.invoke((Object)Utf8String.fromUnsafe(item.byteBuf())); + + TestNotEquals testNotEquals = new TestNotEquals(item); + + testNotEquals.invoke(Utf8String.EMPTY); + testNotEquals.invoke(Unpooled.EMPTY_BUFFER); + testNotEquals.invoke((Object) Utf8String.EMPTY); + testNotEquals.invoke(""); + + testNotEquals.invoke(Utf8String.NULL); + testNotEquals.invoke((ByteBuf) null); + testNotEquals.invoke((Object) null); + testNotEquals.invoke((String) null); + + testNotEquals.invoke((Object) item.byteBuf()); + testNotEquals.invoke((Object) item.value()); + + testNotEquals.invoke((Utf8String) null); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testFrom(UnicodeText item) { + Optional value = Utf8String.from(item.byteBuf()); + assertTrue(value.isPresent()); + assertTrue(value.get().equals(value.get())); + assertTrue(value.get().equals(item.value())); + assertTrue(value.get().equals(item.byteBuf())); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testFromUnsafe(UnicodeText item) { + Utf8String value = Utf8String.fromUnsafe(item.byteBuf()); + assertTrue(value.equals(value)); + assertTrue(value.equals(item.value())); + assertTrue(value.equals(item.byteBuf())); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testHashCode(UnicodeText item) { + Utf8String value = Utf8String.fromUnsafe(item.byteBuf()); + assertEquals(value.hashCode(), item.byteBuf().hashCode()); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testLength(UnicodeText item) { + assertEquals(Utf8String.fromUnsafe(item.byteBuf()).length(), item.value().length()); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testSubSequence(UnicodeText item) { + + Utf8String value = Utf8String.fromUnsafe(item.byteBuf()); + + for (int start : new int[] {0, 1, 2 }) { + + for (int end = start + 1; end <= value.length(); end++) { + try { + final Utf8String actual = (Utf8String) value.subSequence(start, end); + assertNotNull(actual); + assertFalse(actual.isNull()); + assertEquals(actual.toUtf16(), item.value.subSequence(start, end)); + } catch (IllegalArgumentException error) { + final String actual = value.toUtf16(); + assertNotNull(actual); + assertTrue(Character.isSurrogate(actual.charAt(start)) || Character.isSurrogate(actual.charAt(end))); + } + } + } + + for (int start = 0, end = value.length(); start <= end; start++, end--) { + try { + final Utf8String actual = (Utf8String) value.subSequence(start, end); + assertNotNull(actual); + assertFalse(actual.isNull()); + assertEquals(actual.toUtf16(), item.value.subSequence(start, end)); + } catch (IllegalArgumentException error) { + final String actual = value.toUtf16(); + assertNotNull(actual); + assertTrue(Character.isSurrogate(actual.charAt(start)) || Character.isSurrogate(actual.charAt(end))); + } + } + + assertThrows(IndexOutOfBoundsException.class, () -> Utf8String.NULL.subSequence(0, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> value.subSequence(-1, 0)); + assertThrows(IndexOutOfBoundsException.class, () -> value.subSequence(0, -1)); + assertThrows(IndexOutOfBoundsException.class, () -> value.subSequence(value.length() + 1, 1)); + assertThrows(IndexOutOfBoundsException.class, () -> value.subSequence(1, value.length() + 1)); + assertThrows(IndexOutOfBoundsException.class, () -> value.subSequence(value.length() / 2, value.length() / 2 - 1)); + } + + @Test + public void testToString() { + + assertEquals(Utf8String.NULL.toString(), "null"); + + assertEquals(Utf8String.EMPTY.toString(), "\"\""); + assertEquals(Utf8String.EMPTY.toString(), "\"\""); + assertEquals(Utf8String.fromUnsafe(Unpooled.EMPTY_BUFFER).toString(), "\"\""); + assertEquals(Utf8String.transcodeUtf16(new String("")).toString(), "\"\""); + + assertEquals(Utf8String.transcodeUtf16("Hello World!").toString(), "\"Hello World!\""); + assertEquals(Utf8String.transcodeUtf16("\"Hello World!\"").toString(), "\"\\\"Hello World!\\\"\""); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testToUtf16(UnicodeText item) { + assertEquals(Utf8String.fromUnsafe(item.byteBuf()).toUtf16(), item.value()); + } + + @Test(dataProvider = "unicodeTextDataProvider") + public void testTranscodeUtf16(UnicodeText item) { + assertEquals(Utf8String.transcodeUtf16(item.value()).toUtf16(), item.value()); + } + + @DataProvider(name = "unicodeAlphabetDataProvider") + private static Iterator unicodeAlphabet() { + ImmutableList items = ImmutableList.of( + new UnicodeAlphabet("English", new String[] { + "A", "a", "B", "b", "C", "c", "D", "d", "E", "e", "F", "f", "G", "g", "H", "h", "I", "i", "J", "j", + "K", "k", "L", "l", "M", "m", "N", "n", "O", "o", "P", "p", "Q", "q", "R", "r", "S", "s", "T", "t", + "U", "u", "V", "v", "W", "w", "X", "x", "Y", "y", "Z", "z" + }), + new UnicodeAlphabet("Turkish", new String[] { + "A", "a", "B", "b", "C", "c", "Ç", "ç", "D", "d", "E", "e", "F", "f", "G", "g", "Ğ", "ğ", "H", "h", + "I", "ı", "İ", "i", "J", "j", "K", "k", "L", "l", "M", "m", "N", "n", "O", "o", "Ö", "ö", "P", "p", + "R", "r", "S", "s", "Ş", "ş", "T", "t", "U", "u", "Ü", "ü", "V", "v", "Y", "y", "Z", "z" }), + new UnicodeAlphabet("Deseret", new String[] { + "𐐀", "𐐁", "𐐂", "𐐃", "𐐄", "𐐅", "𐐆", "𐐇", "𐐈", "𐐉", "𐐊", "𐐋", "𐐌", "𐐍", "𐐎", "𐐏", + "𐐐", "𐐑", "𐐒", "𐐓", "𐐔", "𐐕", "𐐖", "𐐗", "𐐘", "𐐙", "𐐚", "𐐛", "𐐜", "𐐝", "𐐞", "𐐟", + "𐐠", "𐐡", "𐐢", "𐐣", "𐐤", "𐐥", "𐐦", "𐐧", "𐐨", "𐐩", "𐐪", "𐐫", "𐐬", "𐐭", "𐐮", "𐐯", + "𐐰", "𐐱", "𐐲", "𐐳", "𐐴", "𐐵", "𐐶", "𐐷", "𐐸", "𐐹", "𐐺", "𐐻", "𐐼", "𐐽", "𐐾", "𐐿", + "𐑀", "𐑁", "𐑂", "𐑃", "𐑄", "𐑅", "𐑆", "𐑇", "𐑈", "𐑉", "𐑊", "𐑋", "𐑌", "𐑍", "𐑎", "𐑏", + }) + ); + return items.stream().map(item -> new Object[] { item }).iterator(); + } + + @DataProvider(name = "unicodeTextDataProvider") + private static Iterator unicodeTextData() { + + ImmutableList items = ImmutableList.of( + + // US ASCII (7-bit encoding) + // ..English + new UnicodeText("The quick brown fox jumps over the lazy dog."), + + // ISO-8859-1 (8-bit encoding) + // ..German + new UnicodeText("Der schnelle braune Fuchs springt über den faulen Hund."), + // ..Icelandic + new UnicodeText("Skjótur brúni refurinn hoppar yfir lata hundinn."), + // ..Spanish + new UnicodeText("El rápido zorro marrón salta sobre el perro perezoso."), + + // ISO 8859-7 (11-bit encoding) + // ..Greek + new UnicodeText("Η γρήγορη καφέ αλεπού πηδάει πάνω από το τεμπέλικο σκυλί."), + + // Katakana code block (16-bit encoding) + // ..Japanese + new UnicodeText("速い茶色のキツネは怠laな犬を飛び越えます。"), + + // Deseret code block (21-bit encoding containing an English alphabet invented by the LDS Church) + // ..Deseret + new UnicodeText("\uD801\uDC10\uD801\uDC2F\uD801\uDC4A\uD801\uDC2C, \uD801\uDC38\uD801\uDC35 \uD801\uDC2A\uD801\uDC49 \uD801\uDC4F?") + ); + + return items.stream().map(item -> new Object[] { item }).iterator(); + } + + private static class TestEquals { + + private final UnicodeText item; + private final Utf8String[] variants; + + public TestEquals(UnicodeText item) { + + this.item = item; + + this.variants = new Utf8String[] { + Utf8String.from(this.item.byteBuf()).orElseThrow(AssertionError::new), + Utf8String.fromUnsafe(this.item.byteBuf()), + Utf8String.transcodeUtf16(this.item.value()) + }; + } + + public void invoke(ByteBuf other) { + for (Utf8String variant : this.variants) { + assertTrue(variant.equals(other)); + } + } + + public void invoke(Object other) { + for (Utf8String variant : this.variants) { + assertTrue(variant.equals(other)); + } + } + + public void invoke(String other) { + for (Utf8String variant : this.variants) { + assertTrue(variant.equals(other)); + } + } + + public void invoke(Utf8String other) { + for (Utf8String variant : this.variants) { + assertTrue(variant.equals(other)); + } + } + } + + private static class TestNotEquals { + + private final UnicodeText item; + private final Utf8String[] variants; + + public TestNotEquals(UnicodeText item) { + + this.item = item; + + this.variants = new Utf8String[] { + Utf8String.from(this.item.byteBuf()).orElseThrow(AssertionError::new), + Utf8String.fromUnsafe(this.item.byteBuf()), + Utf8String.transcodeUtf16(this.item.value()) + }; + } + + public void invoke(ByteBuf other) { + for (Utf8String variant : this.variants) { + assertFalse(variant.equals(other)); + } + } + + public void invoke(Object other) { + for (Utf8String variant : this.variants) { + assertFalse(variant.equals(other)); + } + } + + public void invoke(String other) { + for (Utf8String variant : this.variants) { + assertFalse(variant.equals(other)); + } + } + + public void invoke(Utf8String other) { + for (Utf8String variant : this.variants) { + assertFalse(variant.equals(other)); + } + } + } + + private static class UnicodeAlphabet { + + private final ByteBuf[] encodedLetters; + private final String name; + private final String[] letters; + + UnicodeAlphabet(String name, String[] letters) { + + this.name = name; + this.letters = letters; + this.encodedLetters = new ByteBuf[letters.length]; + + int i = 0; + + for (String letter : letters) { + this.encodedLetters[i] = Unpooled.wrappedBuffer(letter.getBytes(StandardCharsets.UTF_8)).asReadOnly(); + i++; + } + } + + ByteBuf[] encodedLetters() { + return this.encodedLetters; + } + + String[] letters() { + return this.letters; + } + + String name() { + return this.name; + } + + void testCompareTo(final int i, final int j) { + + final Utf8String ei = Utf8String.fromUnsafe(this.encodedLetters[i]); + final String li = this.letters[i]; + + final Utf8String ej = Utf8String.fromUnsafe(this.encodedLetters[j]); + final String lj = this.letters[j]; + + // Compare String form of letters to the Utf8String forms + + assertEquals( + normalize(ei.compareTo(li)), + normalize(li.compareTo(li))); + assertEquals( + normalize(ei.compareTo(lj)), + normalize(li.compareTo(lj))); + assertEquals( + normalize(ej.compareTo(li)), + normalize(lj.compareTo(li))); + assertEquals( + normalize(ej.compareTo(lj)), + normalize(lj.compareTo(lj))); + + // Compare Utf8String form of letters to the Utf8String forms + + assertEquals( + normalize(ei.compareTo(Utf8String.transcodeUtf16(li))), + normalize(li.compareTo(li))); + assertEquals( + normalize(ei.compareTo(Utf8String.transcodeUtf16(lj))), + normalize(li.compareTo(lj))); + assertEquals( + normalize(ej.compareTo(Utf8String.transcodeUtf16(li))), + normalize(lj.compareTo(li))); + assertEquals( + normalize(ej.compareTo(Utf8String.transcodeUtf16(lj))), + normalize(lj.compareTo(lj))); + + // Compare multi-character strings + + String word1 = Arrays.stream(this.letters).skip(i).limit(j - i).reduce("", (w, c) -> w + c); + String word2 = Arrays.stream(this.letters).skip(j).limit(this.letters.length - j).reduce("", (w, c) -> w + c); + + assertEquals( + normalize(Utf8String.transcodeUtf16(word1).compareTo(word1)), + normalize(word1.compareTo(word1))); + assertEquals( + normalize(Utf8String.transcodeUtf16(word1).compareTo(word2)), + normalize(word1.compareTo(word2))); + assertEquals( + normalize(Utf8String.transcodeUtf16(word2).compareTo(word1)), + normalize(word2.compareTo(word1))); + assertEquals( + normalize(Utf8String.transcodeUtf16(word1).compareTo(Utf8String.transcodeUtf16(word1))), + normalize(word1.compareTo(word1))); + assertEquals( + normalize(Utf8String.transcodeUtf16(word1).compareTo(Utf8String.transcodeUtf16(word2))), + normalize(word1.compareTo(word2))); + assertEquals( + normalize(Utf8String.transcodeUtf16(word2).compareTo(Utf8String.transcodeUtf16(word1))), + normalize(word2.compareTo(word1))); + } + + @Override + public String toString() { + return this.name + " alphabet"; + } + + private static int normalize(int comparison) { + return Integer.signum(comparison); + } + } + + private static class UnicodeText { + + private final byte[] buffer; + private final String value; + + UnicodeText(String value) { + this.buffer = value.getBytes(StandardCharsets.UTF_8); + this.value = value; + } + + public byte[] buffer() { + return this.buffer; + } + + public ByteBuf byteBuf() { + return Unpooled.wrappedBuffer(this.buffer); + } + + @Override + public String toString() { + return this.value; + } + + public String value() { + return this.value; + } + } +} \ No newline at end of file diff --git a/java/src/test/java/com/azure/data/cosmos/core/UtfAnyStringTest.java b/java/src/test/java/com/azure/data/cosmos/core/UtfAnyStringTest.java new file mode 100644 index 0000000..e4aacf0 --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/core/UtfAnyStringTest.java @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.core; + +import org.testng.annotations.Test; + +@Test(groups = "unit") +public class UtfAnyStringTest { + + @Test + public void testIsEmpty() { + } + + @Test + public void testIsNull() { + } + + @Test + public void testIsUtf16() { + } + + @Test + public void testIsUtf8() { + } + + @Test + public void testCompareTo() { + } + + @Test + public void testTestCompareTo() { + } + + @Test + public void testTestCompareTo1() { + } + + @Test + public void testTestEquals() { + } + + @Test + public void testTestEquals1() { + } + + @Test + public void testTestEquals2() { + } + + @Test + public void testTestEquals3() { + } + + @Test + public void testTestHashCode() { + } + + @Test + public void testLength() { + } + + @Test + public void testTestToString() { + } + + @Test + public void testToUtf16() { + } + + @Test + public void testToUtf8() { + } +} \ No newline at end of file diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodecTest.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodecTest.java new file mode 100644 index 0000000..fed1b7d --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DateTimeCodecTest.java @@ -0,0 +1,90 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import com.google.common.collect.ImmutableList; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.time.OffsetDateTime; +import java.util.Iterator; + +import static org.testng.Assert.assertEquals; + +/** + * Tests the DateTimeCodec using data generated from C# code + *

+ * Test data was generated from code that looks like this: + * {@code + * var buffer = new byte[8]; + * var value = DateTime.Now; + * MemoryMarshal.Write(buffer, ref value); + * Console.WriteLine($"new DateTimeItem(new byte[] {{ (byte) {string.Join(", (byte) ", buffer )} }}, OffsetDateTime.parse(\"{value.ToString("o")}\"))"); + * } + */ +@Test(groups = "unit") +public class DateTimeCodecTest { + + @Test(dataProvider = "dateTimeDataProvider") + public void testDecodeByteArray(byte[] buffer, OffsetDateTime value) { + OffsetDateTime actual = DateTimeCodec.decode(buffer); + assertEquals(actual, value); + } + + @Test(dataProvider = "dateTimeDataProvider") + public void testDecodeByteBuf(byte[] buffer, OffsetDateTime value) { + ByteBuf byteBuf = Unpooled.wrappedBuffer(buffer); + OffsetDateTime actual = DateTimeCodec.decode(byteBuf); + assertEquals(actual, value); + } + + @Test(dataProvider = "dateTimeDataProvider") + public void testEncodeByteArray(byte[] buffer, OffsetDateTime value) { + byte[] actual = DateTimeCodec.encode(value); + assertEquals(actual, buffer); + } + + @Test(dataProvider = "dateTimeDataProvider") + public void testEncodeByteBuf(byte[] buffer, OffsetDateTime value) { + ByteBuf actual = Unpooled.wrappedBuffer(new byte[DateTimeCodec.BYTES]).clear(); + DateTimeCodec.encode(value, actual); + assertEquals(actual.array(), buffer); + } + + @DataProvider(name = "dateTimeDataProvider") + private static Iterator dateTimeData() { + + ImmutableList items = ImmutableList.of( + new DateTimeItem(new byte[] { + (byte) 120, (byte) 212, (byte) 106, (byte) 251, (byte) 105, (byte) 48, (byte) 215, (byte) 136 }, + OffsetDateTime.parse("2019-09-03T12:26:44.3996280-07:00")), + new DateTimeItem(new byte[] { + (byte) 226, (byte) 108, (byte) 87, (byte) 194, (byte) 164, (byte) 48, (byte) 215, (byte) 72 }, + OffsetDateTime.parse("2019-09-03T19:27:28.9493730Z")) + ); + + return items.stream().map(item -> new Object[] { item.buffer, item.value }).iterator(); + } + + private static class DateTimeItem { + + private final byte[] buffer; + private final OffsetDateTime value; + + DateTimeItem(byte[] buffer, OffsetDateTime value) { + this.buffer = buffer; + this.value = value; + } + + public byte[] buffer() { + return this.buffer; + } + + public OffsetDateTime value() { + return this.value; + } + } +} \ No newline at end of file diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodecTest.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodecTest.java new file mode 100644 index 0000000..85e32dd --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/DecimalCodecTest.java @@ -0,0 +1,133 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import com.google.common.collect.ImmutableList; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.math.BigDecimal; +import java.util.Iterator; + +import static org.testng.Assert.assertEquals; + +/** + * Tests the DecimalCodec using data generated from C# code + *

+ * Test data was generated from code that looks like this: + * {@code + * using System.Runtime.InteropServices; + * var buffer = new byte[16]; + * var value = decimal.MaxValue; + * MemoryMarshal.Write(buffer, ref value); + * Console.WriteLine($"new DecimalItem(new byte[] {{ (byte) {string.Join(", (byte) ", buffer )} }}, new BigDecimal(\" + * {value.ToString()}\"))"); + * } + */ +@Test(groups = "unit") +public class DecimalCodecTest { + + @Test(dataProvider = "decimalDataProvider") + public void testDecodeByteArray(byte[] buffer, BigDecimal value) { + BigDecimal actual = DecimalCodec.decode(buffer); + assertEquals(actual, value); + } + + @Test(dataProvider = "decimalDataProvider") + public void testDecodeByteBuf(byte[] buffer, BigDecimal value) { + ByteBuf byteBuf = Unpooled.wrappedBuffer(buffer); + BigDecimal actual = DecimalCodec.decode(byteBuf); + assertEquals(actual, value); + } + + @Test(dataProvider = "decimalDataProvider") + public void testEncodeByteArray(byte[] buffer, BigDecimal value) { + byte[] actual = DecimalCodec.encode(value); + assertEquals(actual, buffer); + } + + @Test(dataProvider = "decimalDataProvider") + public void testEncodeByteBuf(byte[] buffer, BigDecimal value) { + ByteBuf actual = Unpooled.wrappedBuffer(new byte[DecimalCodec.BYTES]).clear(); + DecimalCodec.encode(value, actual); + assertEquals(actual.array(), buffer); + } + + @DataProvider(name = "decimalDataProvider") + private static Iterator decimalData() { + + ImmutableList items = ImmutableList.of( + new DecimalItem( // decimal.MinusOne + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 128, // flags + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // high + (byte) 1, (byte) 0, (byte) 0, (byte) 0, // low + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // mid + }, + new BigDecimal("-1")), + new DecimalItem( // decimal.Zero + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // flags + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // high + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // low + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // mid + }, + new BigDecimal("0")), + new DecimalItem( // decimal.One + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // flags + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // high + (byte) 1, (byte) 0, (byte) 0, (byte) 0, // low + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // mid + }, + new BigDecimal("1")), + new DecimalItem( // decimal.MinValue + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 128, // flags + (byte) 255, (byte) 255, (byte) 255, (byte) 255, // high + (byte) 255, (byte) 255, (byte) 255, (byte) 255, // low + (byte) 255, (byte) 255, (byte) 255, (byte) 255, // mid + }, + new BigDecimal("-79228162514264337593543950335")), + new DecimalItem( // decimal.MaxValue + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // flags + (byte) 255, (byte) 255, (byte) 255, (byte) 255, // high + (byte) 255, (byte) 255, (byte) 255, (byte) 255, // low + (byte) 255, (byte) 255, (byte) 255, (byte) 255, // mid + }, + new BigDecimal("79228162514264337593543950335")), + new DecimalItem( // new decimal(Math.PI) + new byte[] { + (byte) 0, (byte) 0, (byte) 14, (byte) 0, // flags + (byte) 0, (byte) 0, (byte) 0, (byte) 0, // high + (byte) 131, (byte) 36, (byte) 106, (byte) 231, // low + (byte) 185, (byte) 29, (byte) 1, (byte) 0 }, // mid + new BigDecimal("3.14159265358979")) + ); + + return items.stream().map(item -> new Object[] { item.buffer, item.value }).iterator(); + } + + private static class DecimalItem { + + private final byte[] buffer; + private final BigDecimal value; + + DecimalItem(byte[] buffer, BigDecimal value) { + this.buffer = buffer; + this.value = value; + } + + public byte[] buffer() { + return this.buffer; + } + + public BigDecimal value() { + return this.value; + } + } +} diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodecTest.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodecTest.java new file mode 100644 index 0000000..73f35a6 --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/codecs/GuidCodecTest.java @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.codecs; + +import com.google.common.collect.ImmutableList; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Iterator; +import java.util.UUID; + +import static org.testng.Assert.assertEquals; + +/** + * Tests the GuidCodec using data generated from C# code + *

+ * Test data was generated from code that looks like this: + * {@code + * var buffer = new byte[16]; + * var value = Guid.NewGuid(); + * MemoryMarshal.Write(buffer, ref value); + * Console.WriteLine($"new GuidItem(new byte[] {{ (byte) {string.Join(", (byte) ", buffer )} }}, UUID.fromString(\"{value.ToString()}\"))"); + * } + */ +@Test(groups = "unit") +public class GuidCodecTest { + + @Test(dataProvider = "guidDataProvider") + public void testDecodeByteArray(byte[] buffer, UUID value) { + UUID actual = GuidCodec.decode(buffer); + assertEquals(actual, value); + } + + @Test(dataProvider = "guidDataProvider") + public void testDecodeByteBuf(byte[] buffer, UUID value) { + ByteBuf byteBuf = Unpooled.wrappedBuffer(buffer); + UUID actual = GuidCodec.decode(byteBuf); + assertEquals(actual, value); + } + + @Test(dataProvider = "guidDataProvider") + public void testEncodeByteArray(byte[] buffer, UUID value) { + byte[] actual = GuidCodec.encode(value); + assertEquals(actual, buffer); + } + + @Test(dataProvider = "guidDataProvider") + public void testEncodeByteBuf(byte[] buffer, UUID value) { + ByteBuf actual = Unpooled.wrappedBuffer(new byte[GuidCodec.BYTES]).clear(); + GuidCodec.encode(value, actual); + assertEquals(actual.array(), buffer); + } + + @DataProvider(name = "guidDataProvider") + private static Iterator guidData() { + + ImmutableList items = ImmutableList.of( + new GuidItem( + new byte[] { + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, + (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 + }, + UUID.fromString("00000000-0000-0000-0000-000000000000")), + new GuidItem( + new byte[] { + (byte) 191, (byte) 17, (byte) 214, (byte) 27, (byte) 22, (byte) 170, (byte) 84, (byte) 69, + (byte) 147, (byte) 105, (byte) 195, (byte) 216, (byte) 1, (byte) 81, (byte) 34, (byte) 107 + }, + UUID.fromString("1bd611bf-aa16-4554-9369-c3d80151226b")) + ); + + return items.stream().map(item -> new Object[] { item.buffer, item.value }).iterator(); + } + + private static class GuidItem { + + private final byte[] buffer; + private final UUID value; + + GuidItem(byte[] buffer, UUID value) { + this.buffer = buffer; + this.value = value; + } + + public byte[] buffer() { + return this.buffer; + } + + public UUID value() { + return this.value; + } + } +} diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderTest.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderTest.java new file mode 100644 index 0000000..f9efb37 --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/io/RowReaderTest.java @@ -0,0 +1,290 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.io; + +import com.azure.data.cosmos.core.Out; +import com.azure.data.cosmos.core.Utf8String; +import com.azure.data.cosmos.serialization.hybridrow.HybridRowVersion; +import com.azure.data.cosmos.serialization.hybridrow.Result; +import com.azure.data.cosmos.serialization.hybridrow.RowBuffer; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolver; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutResolverNamespace; +import com.azure.data.cosmos.serialization.hybridrow.layouts.LayoutType; +import com.azure.data.cosmos.serialization.hybridrow.schemas.Namespace; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufUtil; +import io.netty.buffer.Unpooled; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; +import org.testng.util.Strings; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Strings.lenientFormat; +import static java.lang.System.out; +import static java.util.Objects.requireNonNull; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; +import static org.testng.AssertJUnit.assertNotNull; + +public class RowReaderTest { + + // region Fields + + private static final String basedir = System.getProperty("project.basedir", System.getProperty("user.dir")); + + private final Path dataFile; + private final File schemaFile; + + private Namespace namespace; + + // endregion + + // region Construction and Setup + + private RowReaderTest(File schemaFile, Path dataFile) { + this.schemaFile = schemaFile; + this.dataFile = dataFile; + } + + @BeforeClass(groups = "unit") + public void setUp() { + assertNull(this.namespace); + this.namespace = Namespace.parse(this.schemaFile).orElseThrow(() -> + new AssertionError(lenientFormat("failed to load %s", this.schemaFile)) + ); + } + + // endregion + + @Test(groups = "unit") + public void testIterable() throws IOException { + try (final RowScanner scanner = RowScanner.open(this.namespace, this.dataFile)) { + for (DataItem item : scanner) { + assertNotNull(item); + out.println(item); + } + } + } + + @Test(groups = "unit") + public void testReader() { + + final long length = this.dataFile.toFile().length(); + assertTrue(0 < length && length < Integer.MAX_VALUE); + + final ByteBuf data = Unpooled.buffer((int) length); + + try (InputStream stream = Files.newInputStream(this.dataFile)) { + data.writeBytes(stream, (int) length); + } catch (IOException error) { + fail(lenientFormat("failed to open %s due to %s", this.dataFile, error)); + } + + final LayoutResolver resolver = new LayoutResolverNamespace(this.namespace); + final RowBuffer buffer = new RowBuffer(data, HybridRowVersion.V1, resolver); + final RowReader reader = new RowReader(buffer); + + final Result result; + + try { + result = visitFields(reader, 0); + } catch (IllegalStateException error) { + throw new AssertionError(lenientFormat("row reader on %s failed due to %s", this.dataFile, error)); + } + + assertEquals(result, Result.SUCCESS); + } + + @Test(groups = "unit") + public void testScanner() throws Exception { + try (final RowScanner scanner = RowScanner.open(this.namespace, this.dataFile)) { + scanner.visit((DataItem item, Object context) -> { + assertNull(context); + assertNotNull(item); + out.println(item); + return Result.SUCCESS; + }, null); + } + } + + // region Privates + + @SuppressWarnings("unchecked") + private static Result visitFields(RowReader reader, int level) { + + Out out = new Out(); + + while (reader.read()) { + + Utf8String path = reader.path(); + LayoutType type = reader.type(); + + if (path.isNull() || type == null) { + fail(lenientFormat("path: %s, type: %s", path, type)); + } + + Result result = Result.SUCCESS; + out.set(null); + + switch (type.layoutCode()) { + + case BOOLEAN: { + result = reader.readBoolean(out); + break; + } + case INT_16: { + result = reader.readInt16(out); + break; + } + case INT_32: { + result = reader.readInt32(out); + break; + } + case INT_64: { + result = reader.readInt64(out); + break; + } + case UINT_8: { + result = reader.readUInt8(out); + break; + } + case UINT_32: { + result = reader.readUInt32(out); + break; + } + case UINT_64: { + result = reader.readUInt64(out); + break; + } + case BINARY: { + result = reader.readBinary(out); + break; + } + case GUID: { + result = reader.readGuid(out); + break; + } + case NULL: + case BOOLEAN_FALSE: + case INT_8: + case UINT_16: + case VAR_INT: + case VAR_UINT: + case FLOAT_32: + case FLOAT_64: + case FLOAT_128: + case DECIMAL: + case DATE_TIME: + case UNIX_DATE_TIME: + case UTF_8: { + break; + } + case NULLABLE_SCOPE: + case IMMUTABLE_NULLABLE_SCOPE: { + if (!reader.hasValue()) { + break; + } + } + case ARRAY_SCOPE: + case IMMUTABLE_ARRAY_SCOPE: + + case MAP_SCOPE: + case IMMUTABLE_MAP_SCOPE: + + case OBJECT_SCOPE: + case IMMUTABLE_OBJECT_SCOPE: + + case SCHEMA: + case IMMUTABLE_SCHEMA: + + case SET_SCOPE: + case IMMUTABLE_SET_SCOPE: + + case TAGGED2_SCOPE: + case IMMUTABLE_TAGGED2_SCOPE: + + case TAGGED_SCOPE: + case IMMUTABLE_TAGGED_SCOPE: + + case TUPLE_SCOPE: + case IMMUTABLE_TUPLE_SCOPE: + + case TYPED_ARRAY_SCOPE: + case IMMUTABLE_TYPED_ARRAY_SCOPE: + + case TYPED_MAP_SCOPE: + case IMMUTABLE_TYPED_MAP_SCOPE: + + case TYPED_SET_SCOPE: + case IMMUTABLE_TYPED_SET_SCOPE: + + case TYPED_TUPLE_SCOPE: + case IMMUTABLE_TYPED_TUPLE_SCOPE: { + + System.out.print(Strings.repeat(" ", level)); + System.out.println(lenientFormat("%s: %s", path, type.name())); + + result = reader.readScope(null, (RowReader child, Object ignored) -> visitFields(child, level + 1)); + + System.out.print(Strings.repeat(" ", level)); + System.out.println("end"); + break; + } + case END_SCOPE: { + fail(lenientFormat("unexpected layout type: %s", type)); + break; + } + case INVALID: + case MONGODB_OBJECT_ID: { + fail(lenientFormat("unsupported layout type: %s", type)); + break; + } + default: { + fail(lenientFormat("unknown layout type: %s", type)); + break; + } + } + + if (result != Result.SUCCESS) { + return result; + } + + if (out.isPresent()) { + Object value = out.get(); + System.out.print(Strings.repeat(" ", level)); + System.out.println(lenientFormat("%s: %s = %s", + path, type.name(), value instanceof ByteBuf ? ByteBufUtil.hexDump((ByteBuf)value) : value) + ); + } + } + + return Result.SUCCESS; + } + + public static class Builder { + @Factory + public static Object[] create() { + return new Object[] { + new RowReaderTest( + Paths.get(basedir, "test-data", "RootSegment.json").toFile(), + Paths.get(basedir, "test-data", "RootSegment.hybridrow") + ) + }; + } + } + + // endregion +} \ No newline at end of file diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchemaTest.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchemaTest.java new file mode 100644 index 0000000..e6a9565 --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/layouts/SystemSchemaTest.java @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.layouts; + +import org.testng.annotations.Test; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.testng.Assert.*; + +@Test(groups = "unit") +public class SystemSchemaTest { + + private static final Path SCHEMA_FILE = Paths.get("test-data", "RootSegment.json"); + + @Test + public void testLayoutResolver() { + + final LayoutResolver layoutResolver = SystemSchema.layoutResolver(); + + final Layout recordLayout = layoutResolver.resolve(SystemSchema.RECORD_SCHEMA_ID); + assertEquals(recordLayout.name(), "Record"); + assertEquals(recordLayout.schemaId(), SystemSchema.RECORD_SCHEMA_ID); + + final Layout segmentLayout = layoutResolver.resolve(SystemSchema.SEGMENT_SCHEMA_ID); + assertEquals(segmentLayout.name(), "Segment"); + assertEquals(segmentLayout.schemaId(), SystemSchema.SEGMENT_SCHEMA_ID); + } +} \ No newline at end of file diff --git a/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/schemas/NamespaceTest.java b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/schemas/NamespaceTest.java new file mode 100644 index 0000000..7def457 --- /dev/null +++ b/java/src/test/java/com/azure/data/cosmos/serialization/hybridrow/schemas/NamespaceTest.java @@ -0,0 +1,143 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.cosmos.serialization.hybridrow.schemas; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Factory; +import org.testng.annotations.Test; + +import java.io.File; +import java.nio.file.Paths; +import java.util.UUID; + +import static com.google.common.base.Strings.lenientFormat; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.fail; + +public class NamespaceTest { + + private static final String basedir = System.getProperty("project.basedir", System.getProperty("user.dir")); + private final File schemaFile; + private Namespace namespace; + + private NamespaceTest(File schemaFile) { + this.schemaFile = schemaFile; + } + + @BeforeClass(groups = "unit") + public void setUp() { + assertNull(this.namespace); + this.namespace = Namespace.parse(this.schemaFile).orElseThrow(() -> + new AssertionError(lenientFormat("failed to load %s", this.schemaFile)) + ); + } + + @Test(groups = "unit") + public void testName() { + String name = UUID.randomUUID().toString(); + this.namespace.name(name); + assertEquals(this.namespace.name(), name); + } + + @Test(groups = "unit") + public void testSchemas() { + + assertNotNull(this.namespace.schemas()); + + for (Schema schema : this.namespace.schemas()) { + + assertNotNull(schema.name()); + assertNotNull(schema.schemaId()); + assertNotNull(schema.properties()); + + for (Property property : schema.properties()) { + + assertNotNull(property.path()); + assertNotNull(property.type()); + + assertValidPropertyType(property.type()); + } + } + } + + @Test(groups = "unit") + public void testVersion() { + + assertNotNull(this.namespace.version()); + assertThrows(NullPointerException.class, () -> this.namespace.version(null)); + + for (SchemaLanguageVersion version : SchemaLanguageVersion.values()) { + this.namespace.version(version); + assertEquals(this.namespace.version(), version); + } + } + + private static void assertValidPropertyType(PropertyType propertyType) { + + if (propertyType instanceof UdtPropertyType) { + UdtPropertyType value = (UdtPropertyType) propertyType; + assertNotNull(value.name()); + assertNotNull(value.schemaId()); + assertEquals(value.type(), TypeKind.SCHEMA); + return; + } + if (propertyType instanceof ArrayPropertyType) { + ArrayPropertyType value = (ArrayPropertyType) propertyType; + assertEquals(value.type(), TypeKind.ARRAY); + if (value.items() != null) { + assertValidPropertyType(value.items()); + } + return; + } + if (propertyType instanceof PrimitivePropertyType) { + + PrimitivePropertyType value = (PrimitivePropertyType) propertyType; + + switch (value.type()) { + case BOOLEAN: + case NULL: + case INT_8: + case INT_16: + case INT_32: + case INT_64: + case VAR_INT: + case UINT_8: + case UINT_16: + case UINT_32: + case UINT_64: + case VAR_UINT: + case DECIMAL: + case FLOAT_32: + case FLOAT_64: + case FLOAT_128: + case GUID: + case DATE_TIME: + case UNIX_DATE_TIME: + case BINARY: + case UTF_8: + assertNotNull(value.storage()); + assertNotEquals(value.storage(), StorageKind.NONE); + break; + default: + fail(lenientFormat("not a primitive TypeKind: %s", value.type())); + } + + return; + } + fail(lenientFormat("untested property type: %s", propertyType)); + } + + public static class Builder { + @Factory + public static Object[] create() { + return new Object[] { + new NamespaceTest(Paths.get(basedir, "test-data", "RootSegment.json").toFile()) + }; + } + } +} diff --git a/java/src/test/resources/log4j.properties b/java/src/test/resources/log4j.properties new file mode 100644 index 0000000..5e59e08 --- /dev/null +++ b/java/src/test/resources/log4j.properties @@ -0,0 +1,6 @@ +# log4j configuration for tests + +log4j.rootLogger=INFO, A1 +log4j.appender.A1=org.apache.log4j.ConsoleAppender +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%d %5X{pid} [%t] %-5p %c - %m%n diff --git a/layout.xlsx b/layout.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..b340aad7a24860819c505ff69370f6d70222295c GIT binary patch literal 27664 zcmeFXWl&z-vMve)3l6~v?(Xic!QI{69Rk7K-QC?SxI?hu5ZoPt!+l@AwRWv@_P$m3 z@2zwAK{02K?$Q19)7@jviM;eDa8wXT5NHq(5JC`<+X(g_pdcWrkRTvmK%l|2gzapd zO>CX@ls)WCoOI~iZLA6M!NDkULBIg(|L@QL!3YefjNA4xAa$x8^NVz=hJ6=SQ2|G2 z~^6z{(3a#hNB*G=}sV<5-$Q-PQbXAxgOX%BU z^tAx>KCs8!#g2o%Lw~Nqyk7l+tuN@cii92;zYelcLdF`5>sOcT_uwj3lKcgv9yQ1D zX^yf93np5JQ@bnub(R5-3|QVOU51;0*FdX-!3Gn3f1?DyQd{ zf=dyrvbqr5{3evpBMR0uVKik`e#(6Y_gg#lfP0M&V!0Fj1M33!CMllVCXAP}*h18o zNx2qMCA4{W5tDn6Ds4}(8CdXTrOp3h$;=r%RSC)+PA5hWyvx7mr0yBE2ZWT26n7yy zc=a4jtexoTfWQB5(f%J?ss9mrW&Ag}eg?SU3yGJI zk^6=9SR^57H$jOGLS^*Lk9jM+pCJvs6Z) zpmGy8yHy3JJUO^PQIR<&i#b$o4IsNN+%5b~6PNO!aP5krs%S0ElOEk97Mr^gsY9Bk zQ^WrJrRZxgI&a!{&7p4^8-@?npbJ7uXH~(qE$q3+3DX&Vi^;`D@cf~iGN-d?Xd_OB zX3N#yBi4j>kJu_o=A0I_hS`o>L>_v^)<17VGJ3wedeh2gjwlkbpgb^5iw~3L-uY=Z zvRsX4c?__B?ynfR91V!TFWmslvHxBqZx+XDFaXKKClC;95NJ?$Yx;lc#Ldpp%Fxcv z3OM8bT{ED7K?hj-fA&vjf}HdK1Jd9{z$W3udT~{IsC7G(=u$;BK0)DJv2{k`#6!vE zhJ2liL0QVS!$$1AFAvk|y4hm58{E8m34ydC(qSY$jvBQ)FOSapcY@#5^Hpx8`T_wu z4jy$rL#j^RBF#sVA{gQ@G){i>q*xJI#RK<;+r`&;b6)f^I$aJQWPa?91kK2YU~BYp_(o`;2nuGKjVu~JTy9CA z$C*V-5^>sIlct{L7@%h?SAI5fw!*8lU0a(Vp=EXKAOqLHt@YkQqW3qA{o?U?-&6$? zZ^hkyE~LoeEi8qcUETYCWYRUyWJxf9MG1hT6C!{j04Dt>hbmQc7s4wvBXBn z%c{CD_H3lYY~bEqYecazhWP!&J2<$z1l~$obv!xd#jN^O4#V%wp*!x_f^aVZ3Zx3} zF^N$pxQ>o$gTaT4d!uhmu{;>dT{%YGExbWdEi;Lr_8!5EX4;^wy%GGM1#6dX zUo01*)bfK>q-On}9=7!laQ2eCM^&5B0^_{gp=IJ(LTyMeck0=+nR6t&}8e1vks|LtjePSs(SMR-Y zxe%D>u0e&0I1#f1w}V!VxTrR`#DQ(t@qI)jGYy)A3!Xncyg2uh{ZcBgVK__kqMOKlL;XFOdgHpD?FLiDlntd_1k4Mi#G^#WwOoqIeY9B z@3`C<-T@UJYJ(8_9C7A5wNH;^?=hI?i0)TwDaqIs=x)}WCI_|J8W2VnqLfeZVxcnq zn4-C$@C6J49xR`Wuk^XnqK&jvo_$8&Vw8TnDE#(or5O*WWLB$m513x3)r(Gp#Nm3x zeCQ_Sjt((G0UIK@=0~|x7&0Y zuG#Z)|E?o@UCnVv^rS60+r@LsJMAUH{Nl^NpXJxE?~f@bk4-m2^bn^g*5YQcYbkr% z_<(}^@6DgWO!4nF;L+v>HwXy)KPBtr>|t%<1Z?`JI2SQ1Y`4#auZRj%-_BU*K8sUm ze_wqSDtA6Bzau*nE*c|&?36a#Po;KVdG9vMh_xpK6#`ql>lWBvn!ZTc^z!vR&z$y_ z^ZH3c!g6^0JFLu#!@g8HKtb(&r&`bINOMHt4^a$cYsIufY0kaxOWv33wh;bk#(ivm z=)P*ceQ!ro%sl2HJ{Y+}aHvZYiL@Aw&iXiHSxhlo3dqN71@_6}En<{In7*_N>rVsX zr@mZeobx#ZvXBGB-gE{>=@*$@xDbhX-=RvUDj^*k(-w?fY=-hBjjb&4ayTM`ok!$A zss%%YxBsxT+Z5OkkOzauMhMnh_gB{Z;xmFEWQ7aH4@Jt^I00Acxww&cI%N5y)75P~ zJD<{Gt7eyZoQ^Vv=JNepj^0~k*Tdc*?9BiRe~%}zE`L`fHeXqA&Re$PTXFH*)U-*9 z9)Hhll=&FAcg6BZsy^D2>93)HOkFdHz|?X!c~Wf8tjmhO{yg%l?LP^VJzq*3aZt+&^QKB-@Pc6QGmA3mxa#SJ5m+*uWb5{6Z+~683(< ztp2Jkk4yJsePD$f``6iwO;SNS${x~fmitDyC=z@Z0;XKF#;*_zn=5bjoS$Q#e@;=m z#J{rL;xV$c94m?hA5*>SZ-AQ6JtP&;G8rtFH|q}f3nQ!yjF{8Bac2Fz@OMNQYFTvn zj6DP5VTdJ098cU!`2FJO*c+~!So7X|?8tB#2kZsrHi{S|5En^Zw2SBuPOsFt!}g2gtM1~u1k z4v1VlNu7=FVt~-0iL?D99_Ad#rz*yNXa@LWSE>-FzCCGXoi53?Li@W`nM&yk6pQqG zT}p9@{I>@j*cV6=!lY+pEH~M&aUDPON?df~+Yo{~qWUwA#q7^3&{ongz5jWvO zvS@c9BgeJ`qQCKuyl|?v&ObJ^=A`pWXCU@PC1QlBDeXO_?U6fmP7Aun8+9Y(6P7*3 zloL|=J%h8549nq*2s`pT3$l=~zALbjpr!GE!jFcTBkb%&+lb5xE-AQ>;0~x%kq~{Z zV~n_>DD>sOgG#+Kc@5-9ThUWN7e9GiPBf7~nry|3IR7{eW$7=KU z3WZ#MwxE=@9Z*7vW0f>^(XzhMKJ{P-#;5#h8t@knVe${;j+oArI8AO4CMy;)Z0Ow6JsF zwnVCgk5Ut%i$C&d4@E>RCdY1Y4|~J`)XyNs8K*A_^I@?#()rHMmQJsw#_s7(bG*}f z0lQ?Wy6J5EBz?WLy|eqgWwPDl&Te~b7Y~DM4_>a+rViUI4{DKWIbaFm8h@v`I@?|0 zaJ-5oH*26v$1WYC+2r?ANwJC*i$cY3%j}h=ZkvUgjHq#(4m)!D7FgX%7Wi>RH5Q2L zzgXnmYv|Saeks-vguPY>$YLa)iM#n$p8?0y|2_;01M~-d!9hS`kwHLE|1}KF4IE93 zm7E`^$GG`2RWP;CB8S=jQV&y-`{(`S9F`rJP z2I-tR-FCx4}+roxd5ax0y0a zDfu?{2MiezBJodiTmRb2(&J+Z`axf8=Z}`jB&3u3El$ctJZB{zuH_=N(9Bq9 zT;1QEdfxx^wiD{XtWOUBuMiudA){ezOqi7B5gPO3#FLB2*Bx)_+62M35^@bZk z-g=AIpN@6VDDM=2613{hACxK<^|${n?(C65CZXa4XR?KfHtha<@Y};HpV8?@>tR*x zb7L_d@)FLs5TD$A=m|r@^;*b7aHl#^enI>F5F_nk5ae zrAD@hqEGNH9VMCsd{~r5zf738*0L8NJ6)aa5DyEbP~%o}NIP^j$t6_E)Jmth4VpKq zP6ZG2uVO+lk#PH4(uOruQkrXrJNZh z5c@}AHeXtg?I^Q=6fb_0PM~PUu^p9B_sqR45(Bhh9eYuE(rQ11DILeY?lw*!IF^P= zeD}LpUCTG|pykzZY4_hC%nKX8Pmt8CEZuG3&(+}1Wdc7%uWCJi-L{TG(AvqUN?2SN znR_t3XW_8_Ci%?5SSx5GvBs^k;a%F%wQGQziYt6qBH*RX|1*nUd0j0I@hRS16;H?F zC?x09qxGKW6nxFFmAZv>A(t^BMCOzZN!@xk{DAMft_U}F7~Y+|%Ss2H_p$0!`X8yc zx(X7U&$%5ejlUK{4aO6EjN1}J61BcE<3qfup~lc#CDHgq`ql-AkhX}8nx%Ig>zM~` zunU|OF~FveTH0y3Za&|;c=ex zk<>#`nJh8<^$Y0FP4Ml&${}{?E5RlrvZ~z-C}vz%udY*!=VRQ`5;(^!357kgG zk~$b-GjqvL2le#_)YHbNP-MDHN{vFiJw() z?rUaqdbEC3iERs2e%GU{$gI(-g`HcPc%fP`H)@Dk?#;Q=ZD@SMdDO=v)`A~WumhXK z)@=_=p;>(v`x-9}gSXozmAM`R^(yMdbhL3nUB5wb?s9+>l<90wYAQ@j{gX*+J7V*M zDcH4WZgkXaIKHRU`3>+?{onhQKkJElC!kM}0-nZ+|LIr2=WQo*6BB2rf4#){xM2FP zS2#andSL+Xs6{RU-jV*=&Uzxn6?cXHsyKwIJZgq-mK+hA>0$pPDtO6qitub&Vu^P{ za*n#}S(29s0qr>C_8T61s-)i%HsDJ;0{MkRe*$K@XIp7Bi@}&U&&p3CrLR_)N-*3- zOOY(Z()c4LCHD?PiNhSF{`=vd%3Ktzm0yenUI$TaN(h^EK5yT`aX#{|-gmJ!-tV&| zNb?gZ_l=8Sg*xOG3Xa_eZ`LP2YRJ13b&oC3148@n!S`Yyb<0A5fD91;Kg@i*Y;ZO= zu`!|l_|5q7{Gu@#fy0j4gYm=<=j8Unx)VdX@n_mPVV%S{EAeYn^QnR=GgEvg&KEFJ z&O1el!lD!*JKn@uflu&Vw=thd8jtX2$S0SGtM*7Ttfe$v;UmP~x=Kp!vwb~poUdlP zQa!~}Vf*5f^}6M+c{3xIQc32L{j4}BSiI#V5+jjKKHEOR(!5Bo=J+}y+l)dFFMWCx zvCd1zm*iZfLLY<(4pcvF5$|xK{g{d-nQ55Jp~GiulXbC z>j6d!J^G9)naCcbhOlk!J5!sCzPI{})AdoWRuN zfTZH)C9abs+gJm5`KN`v4z&xFarBK}dO8hlxaBcHi@C~vwZZss?SDjJYXm9zwEIJ{ zOiRp87IRVcwE7pN&vfNmZmr}+Bpq9W>4KUp-P%^rjQb9wzihw-3Ut?`cM!Gx34=gDH|oZjTPa$^C+^Z;hbf{4=mhItPtn7mPxt->OUrFQxKO!}tBI zm^i$dfvGS_M?Xv*NAa(_;lQX&^9yzE0y_bHHm}#)<-A#-GN*T z?#k*{+|*0Lu)53YEu#yv2!rnk&sU)QSpy701MvdLhpwgP<0D|YS_H>^F12TUt6$ZJ zAUb(^td`sHui8kW(`v-(Al8f`T`}Fb{*yE9U5(RqCk|j>N6#5Dwj2YZNvN z9q%(C__1<5xnWb&Uuw0$>upSI0PussH?(YTXxyAm;Z%`Rgpn1uJHmLE$)dm zQ#z(VQ=8mhCEC=Q**OHbqf>+-Zx%jci>yoOaO`C&duBx=eEY)+wuiqPF-N%wamWzg z(Ia^h1+8J0;)#Cltz%E^Yu7NWueZT_)(wv3ZHYzjx8?67l7dwLk3ldr3>?OKKq%Uq zwn$cmruBJZ#!?0w;wMxw)vhlIyHSJFVfEyIBRifOs1qbajMmk2B3A~5$$`lChR^r- zG*+JG*=s-T<13whd#E_+E`%*-Z>Kq#ZbDc&`#cF2|7jekj|P)vzACqyW>E{PtLRw^9xQ>*kt`@ zX1L6qvO6NE1kDS4V=4tp>RHfU(>dw>6k zcI|}-t_TL3eoZ_uLMv%Z>x`_1nMxD$Okgfc1C=+VXC{boR$6X%@UV2TDDM(2q$Q4Y zZir%-WeC97qT!xQe%2UjPYao6l4~<;!*OIjjzUDX5+x#U{Z2-v^lO0I_OZzlx`m3E z#p?0PA!h%gJ7gR2ycR~jQmZSLWVY>tn?W)bMtz7#BA0f8>=-0tT&h>%0IeRaUlKga z%-4JyYBhf(KFytU0c!jV2P9|i5qG9uVvFE)OoeP&{O?;z)%I`YgPXXOB+Fm>y6~f7 zx;}9oup<|$tJ70MMThxE1Uep1GJemfMT^^eblcV+GhgfspXE%9CgzHecg;^V&hBFk ztDcyVqsGUSTTbuIJE7xAE&uelOKzPVe__lC(qiANc#!IN-Z|kYgnJjh;#zpVo~p?9 zRhHJV+KR3X0cF8Ms&i}JC*o5t18vR((>IMy+5Yf`28Go|W*TTXxp}q+8y7JS-m7YI z{*kN+O&0;06RE6+r?Iup1yd-u?>wINejFu=hw?&pDZ~^{vp6G(Z2A#v2^vw*o1L8G zwC}!@)==wGOSFmD20cj1fr@#^%@sken5yHiwc5unREU4{;}o zFVdaw?9omJAxA{W=uKcWZ9Q#wYcG2{Tp$x%@w3u zrF8-Cxn4W-mFKdH7#?9|!B+l+9j3{#MGM-J)Wo+yqZBGhio3K0=Qa10fZ9lZkJ87u z8|2=yqxt=ReAi!^c?a_U>Fn__i9bFc{r~6ep*Z$JQ`)Ymw|9*3Kb}2K+F5ST0Z)iU z{vaTj|C~Mk`43=cX&}rE$iY6wg ziB^18n@#Y|OI^j-4Q+IL7B(|;d9VI4Zeam`d13c(J*S(OAHLffad`c0&vPkL4*_a5 zW%AAU{`$!CVcM^9YQMkts?oPikN-@sd9h!wd3YcK^z>?q5|iT+UzOaS_bZ2cPZFzXoS3$QyRC!i8ncYo8|u`DRyZ6cwa7@o75-G zBKA)^?k~*D<}QX38tx+=x2=~aOe;*gEi(om{Q5K8?zvn03Cnv8p6z*Gs@tA^H79Hh zPIj~gzBR4-@|wQ$aGdGA*ZXj++va3fhqO%EU*^2NJziwEw0cdFx+A%s4!^z~*zeu{ z871}q+9J35ZHYUO_2tSWqgq#1f9{>Tua6&WTNEnoow>JW8}EIK;h~k!*6v=8|Lj~Y z2Gp6Ob(61>pFhiY&F}Tb_5SDzeAa@Yb(z0+;qo17y5n-K*Hz0e!q4{`M$5sZvo~ju zKNNn;@SG(E9WDY}PE5%wGiYv+@h4mLMo_=_sKH0`dEMxAcJ=Qr;i`R}dE{+qpZp@# z`f}X&N;z|S(D1jT9xll>(*y*jNK>~5FUfV+WTr~GT{w=mh+29_#v@zP{p(6=Wcpl@#i6t zIm*{fm~u;hQ>YASQJGyR0~(jW0h>={w`!FUZp%`6 ztVL3$%u4i|+motr3`$37UgrHwkrRkT? zLLaKiCr1C|68`OHc7cf*dF8P4?}?$vAF43%1R$a%?Q}_0a>*W&iabz}fp$1$#A<{` zs7E=2t*56yRFF)vx1r4h2IG#w4wH0=rFaujR|RPN3zmer2icHd1zh{UGOvW>u8aqq z`6##+(4hC?6%R|O#wJ3eDjTu0QP8qJca*r5DkX~XP+F>=GHP3Jb#k0KyCbjt*p}1? zQC8ZsH)to_ANQe&AqzA`Q_?%xz0WsL6YANVYlVm8r zW>s{GszA*}WI2nha3V^Osc_k%r6I%m0*_dO?Q${TCRBe)QrC?p*BHgFOQj~ryU3p_kn?#zx zqeP-4CR#cLD?BihDi3CL`ek1nelUNLa9dmbIlOngiZ1=zo*80cs(?!sK!7}nQTc+kR@h3 z4L2??deQzC7QZ;9QCX(RXg|#!OGMqhO$ILEU_&}Lp@u68FFJ(ifFgIPrOJkGz{CD} z|748c^AVySj}>7CkNL%ytL+oQ)WeM{^4A8f>a?-4akk7rzJYQ4#gMaC2Hcsz7t1zi zZdVMs#WeiwT)H~FE%BUtX?|rs?PjNQaiQQd5?E7t1j$K=5|sIR9ZdVkSJm9pAe^$u zI&emCT7>5M=Eg!yl)WhZ4leo#S`~T!=}MLZ#IW+b$nrZrlWdbwVDNmOT4v zjG2`jboD)onAm5|nw%qtKP~o}&@*N3&`4tR-n>>wbDvu<-P45|I2mumQQTBxU~M=k z7DZ@p+*NA2hZHIPRb>&IY1Ntn=ydLUmBHA9aI(>g_ClfSlefS0< z&DEoXEOM1G+iG_eMf9=xR3zAqrwg#SS@~xCjKd_-TkBfx2cVKprHAOoWlPTa{JgZc zSRr&&`J!X)tkDJ|V-?F_59-!45G*uQFy4n+^CPs~bf-mj5>3NPAVu5UvPRUovMoj$ z$GLeIB2CH(70z{1eBdtJ%L%#hF33E~!?v%d;{OTzN?91At#eLk68uJLh=XLTOPJPa z6L8a2d*i5#tnuoHoK>3}#aP#g$k57_vQV+k#!;JbfCkZyFp7!yQUt&#U0wu_H^+>V zB&r^w6W?ysC%00gYl9M_*69Rz-JPxeuxzXR)O8OTn#ZgUSQY`1W-U5Rf={>K_&5L>P069+mv2lcXe&hXP z5tUvysQ_Rwufjb-W?vVKZbrsf)^9R~Trc`tAVU8DHk4z`#;Fqu5 z+2`iIq4qOpptX{WL3d$bxg`TU9T7fc=3N(Y7!C3E+RT&f4as+5Dxy7UK)O)T$Oa~xK z7IDfYRwUZ8gGb3heA)ylfE7-=C>zK%Pse>< zklKj=#M=izza4+^k)mU7_N}%bbdJCs+IS#|0h{h%TKDPceE6X@5tv$q8}4|)6<6oV zqZSKfMs@1AwjdDJ>eNeZK_ETb4C$O8fHAch_Bla(cpKg}f%f5T_-Fq8f4pTJrioqf zBN;pH(N*4bQ}Ue<#qc=pY0IY0PhIeP@xgQne~M}O?8X)R+zJ1=h7y5;+U~}QH${Ze ztGHue#^;id_QZ$7%2Lw$8^)d+AMxb&$*cA>slr6(35xgy04d{5vl;HrksX~=SZSNR zM~p)Xx=jEz&&G9)*VMD65A(hCe*d=3JBX(+eU4Wc#yw6wV97#o;*UzDPp>ffGQFH< zhtLdll96%E^5Zv;9Stlmtf)g9xkRFa3caE#?{Tj^!nBaHLLE7kQ3+7Scq8k(L{59> zL3H7co*w~2R^{AJb4!CdIKl1lB&u2L#sfPeikGc-s6i2)=5}oaYmv5bMI!<%@`hhR z-F2}Pn{K~xU^kYrriDJ(8H9cv6$Hp9;HJlL0vr%Wvowg}M4G?^3NxvB#b?A(Zr>+S zR~{_yJkvDN&=V5I9VpG2(3+jPHf22_eGz$^m?9((CJEEdSW7k#i4%{lNl%9S)D1>` z_IFD=EvGURR)KPxdQ?*KP2(Y)qOop}vgR?A!c=}3zb2TIifUFz))dbc>sXwQkU3+f zohZdU$xua`v?2=5dk7c5M5;&7!WFiNSSML?!F9wkCTxLl+1FoX(y@kbF!Q2wo_nkE zPGz&G0_7z&;FLq^1z4{1)UT?OMN_L?|U zJqwq@D*jIUH|>Uqv9zN_?rXvV0pJSuZ?DBF(U{cH;=tn^IOpioZQz=^dM_WxP`a>b z&Gg=q2HUcxkme~f#_5+y_ZGQnKGMQLJ}1Be=i^mA-si+v^k*9I=RcW6i1lVUD6@t+ zLHhV#({2U-o+<&<8e)ZS%e1fmeT8%y7#K)5Vx3&;5AN|wr~&=A_mL0ZSnt2gU}m4R zMFu*;p!u(b0$iV3eat_#%3+d<@IepoSz({&v-z*JBFwUXKl@$aL|>=;iSXP3M0u(L)uNICQQFX&=w++yQT&NG(HY!nxw%~B&VW72nJ1ElrR-?R3#-l^vQ1# z_{h{nD8lj4GPK6!A>~u?h&m5{*PzSVg^b1 z2u#TX>Lh8YyXq1Nj`+6|jPf0rQuhy)lW}X$I&H0lkbzc%z?u&CDI73Os_D<)_z1opD=@|seX7_ zBjoU`cWRO+bn!5ai~{0TV;Uk*_Qliy;0qShhcC0^!2J>o0KPC)y7LLz0%acbA2O;B znUXf&1Po$tWl|8OJG5B?%mm+PGAFmJ6y-GeKU+Ge*b7zto*=6pd$zcir*?-PE_9qY z{el+JaIFbBCqpxJ>(iPhQ~k$o=(8N=*Nr~-KYn#m)D$pK1>P;~LJADsg*09`V(L9> zEQTv(y$TV8d9`FQG z^x{8+nIaAbrU?`fh~L+MvK!J5GqE8+*g}N7Q_=7Omf=5A=J~(?(E5V)q4nnyXn&uE z2AI8+t^P^?TjbP%j94KWuEg^gT81iugJ}CsDMo>vnfI}n4EJL(mV*9o%LI;++(C=$ zSWGu_`;ENToF+$ZS$y+UGQ=>#V8{~8a1JZ)jBkvnJm8L2HV}wg) zS{MK~2EKoA0z)5|cTO;1-g8$sfdR~cLYUeh4(j^Y*nGo7p?!z{`-1V@JPWfjfZz>3 zw@WxPl5@(zUo_b5`EixKsqfc);R}c*eK+cv6OHG`w>!QGDPHid3-sdBkXp5k5RI~s zT#b!B)H@`$#SVrBgol6-fe*fQy8;-E7l7^vgr_<483<3-77(6Ol6xRLPhCKAFX5l} zSI!In8niJ8_k`}~_5pI+vw;@CZ3Fri#4nAFbYO?AYz(4-u7S8K5SzapT~AX~TM>6Z zEOq=H)Yu|CjBW;mZNT0H4BL~NHLEMk_jn&3e&Mns_2cr=K0A$Yf^JaBsW5P1#t7{{CAvD(rNnmPH-4u&l23=$2&`wcwHU z>o{sbCljdSXXAorc{g>8kgy2YE-I}_6~p1UY5}+SPagZNYKw-QOBf*I=GC&UV+T&E zkFcYwm2K?&NR0>nqou6o=0j0J`Stt^9GH(Od7%>uHaQni;$K z3`F`D4tC}05>}N#`d#c{t*mS3y^Jec}eR4F#&MJcy2{t~t$2%d+`FN{VB6-X)tNDDIIe4$-pP zV6xLj&L$3(@Z)V%)V-rV*&d~A-|nY7hxdBkGq%f)UBu@UrH4T$_guN2&c2Jho>RMf zdcEe5hk~n1-glQ*i|56=t-13(4)*|jg^(OOPN-sz!W^2IcR2nUydwEppS7Gn;v+|! zcr7Q-v@c+P_c(XMLtfuR-oaeuPGaO%@qdTRIn*xu`G)lvWJ^MYR9q%phFn}237?79 zAn;Fo^{wW8!@i&VpI;CYqB8Eb0siS!>F59JJJOHO(uF<>PHPg5w;jYU_?X`H_#`O8 zQ*dRm&UHirlj~Le7;eoM9wJeyk)*6loE7U0{qO4#xfLDlObV%UqTX+fDV4|P*3Jbe z5HgD=o3DQ#?5}O^Z@qioulE~0JbXRtpB-D?-QV|0*h}6Y@muJtW#zIFSLyLv5TEHg z*h~CYd2`;*&-mZxPV@lp?)d#S&Jf6F`%(_rOL7oHYHFsYvM=~9@LHzn@AcgDcIk8e z%Ehb(zD$?oOl9}*oi*b_l?;b83_d;{pE`KG?>Spq z%XNgD2@bu#JieVYH2-yXlW~e!Ey?kFeA>2se^5z(uz$DrdszK-cr?1RUa|RpYx3Us zdP&gfXGPcIM&83a`mQzdu4B&r34xb)W0UtR=ROC4zG$z(VM5~l>Ga9kD@9A_O`LU3 zI~(vNZ2caimZj;Tn~-&U?RP$l>s3}%m7~$CGjG?^-rG*b+`EpR4t@Ko>(%!9;Bg4X zxLb-E{e}z1WW*q1gi1rJb$hkW`{vQ=BL2l5%zdS7wrkEt=G(8%CkKa(%$m6K+SkjJ_5Sno+63M7xrF!S3;cJ-mNWW|ySpRF9$o&^d;WXh9*hX5qiv7c zi;krY-1D9@TUSIxA35q}i0SvN_M~@0pX@!^GrtoM+Yptvl9B|()r0lPx2>9ce8e0R z)Y+-w^^!As#1Q@qzxC5|zb9`b=LL567C$7r$9Flri{~tISlj2-%Zr+Vo4vf@X_q=!NG_J;MJ(J;s_^^Q(LTn^|8}bi6k9ZV$1lrU;BOSd z(aE1Y-Y%!9*?-wv7~FozFKbcgDHz7(I6ZOoTI%+BZG68IvF&>$@mv2(SmohD>K4|4 z_mU?*j7#Blq4CGgt|qx=y88~EG{bG6nA6U(0O$8F51TnAoJHATYjhXxmWloPW{+uW zI?Ien^SPRJA>S;UDdX+y)6qMUhQ$IqS&WD+yoKq5jvv~_yJW;g3HzP5OxnT8*gA{- zXJQ58V%4)HEq-tJJ#XVZ-LYwp^Loteb1kFFZ=(~*(XY>InYc?y8TrN}6%6c+bZiT# zVeo1BcuADlf&C1kpEXh_!3rS?$3tWBhps)I8=u{|#AeR7Ra)Y?*Kb~tKu_8ns889N zNbYl(*nRJIH%`}Ded;8|97|HOaF*MQZ9N;aGk&DDfqvM?$Z+7=ExtUf+7uck%>+L* zPl!Dc89RSqTpz@&sgWO3mZwbvJZEM_FfGg`g{4pOzoJ4AsvY8 zyZq_gl~%c=Y?Eyr+3V&k8_%bI*`?QPrdM|rzr{6p ztk_6NwzOD23U_f94YYGwO_$H@+V|rOIp~f3SUlBHVL8%stlTu{REJdqtyHw4S^!k326myWy`oPCO;^f+xi+2Hn8&;--8D}$2LUfW76E@-~dZcZ@Wmj8C%mg6vb=SE2V(6>~Y|Y#}rS>}z zUF~-a?Gku<+!9nKZrp$BM(w4~3g{78o+(obfGL_uq?~*{Res-@qzR?bOwfTqmi9@j zUMHhvQ`a>_3H>Nf(nzK{uH+M4=9kqh2WbL2oqOy8a9Rz`CHV=tT-8jYT(WN|!Rc$u5wI`N9-S)Iwa;6d{CqEVdHe>jf1rAlJb!O%a@Ka zS>-9K5iTGGjIx zgNXzQ6`doo9)3HUQVa!6emQ!P0n$5n1zaklQtwim&2XDt*0(iZ0w{G7NCcm!cSW3a zwDq#|s*}GF*DPpDyc=28On=(H7hI&ne3OWhl3svlZw&vfoeNqs7$HP9K{yY@Ak~{* zZGp0r(9jGg=rWi>&k0q~vMiqnSLP%%T0TM^P_pG}g~zB$K^SWQb|_a7H7O@7F(bdC z+-}1E)0oPh?z}1hP$d=uppuoCl};>#S%!#=N38Dzpad{%5>3WX$E zy|O}lKCl;1d9SCWN0;T3EKET!e3tYKi&q9@mz44&yPlHe|6y}n;dB`T8z$}c^T(cG z<+}0ZN~LqPfYg`H?cQMeLdklt7C=JIarr3{+=Kbj!xM17BFN?#OiUaxS$7tDrI_5cO75QEgYXSpS0qlQsGAVoqrLv4l zsO|vTU$b{e&%42B6qjE7Q>G`}fTGCn26l&@Wu5#^r4c4kkAL-s4WP}vEP&0I$#ay2 zEWm!{+>OAd5|ramSZq{Wdfv$Vp=a2wKsb)NdHRurG7L9BLmu=l_?P15DV1^Bc81P} z=3V5z8=7J{X z<8WXj5-&^esn+eYgH4FW_WOI^$FE?8)323v{M~hsbpd2?nh$1qAvzrfn9RzqVny`ego2wGAxw0-?Mp)lJFC_{$JYxgK+FAFMDyY&! zoV8>9GjztDe@NdOkM|(N3P{H{ zM9V|5Dj5`5!12QPI~=T}*cn7Rmx@-ePTV~Zkb1OM0j)d%r4d_CRP%p)2g-Zb-g99A zWc(qs$P>o;^Nv+zgh8}av=rF;VOd;YOkn?+f?zgLVBY}bNKpSTT|nHqz_=k+uoKh) z8BQG#`XK6}ZZ42<3F^Q^eQzEjNd_>EtnQ!mN6-V(Z-^od;0;~t?}Eg-d@aH+ng1Sg z0n%AQGf`PKs6-*^_PtHAibI_fiX-3$U}=Bg#8nE5t-(X&w4|hat=$!hWewnl4D3*a z^1Al(t^L%FkP=zRDN0~HHoed^)t z6tq%x!EZ^Hv>FKjc?C5;hJ*gGOClhrdGApG;%kdnDTq@Vr{zZjV*`xK0>HQo2iO%Z zR?`-Tx9^feW0Lu|_gqq0Ld8I=`w~w|spl1dtS|UieNq5fAFT+ePk>0qnbO#h?w=-^ zrt5(V7#S0TfRSM^(Y4KG>3<@UB1E>2KH|-DgdbWK_wG-Eb#;?BJGYs%sCleh1od)I zShUA9MC~V%h#mL1bzH$eHk0!iqOAz0iAezykpEt(%VX)Ra@Gq!1Z_>awLNNeH<4V; zIGdjk%V?%QQR{K=nDv2B5L^rb#vJepn5sILAUia)dYP*#B4CqC^{fNTIVDuBf5{A` z0qGz7n6UpTQmk9hiDDAtOM(-FI;bTj*HGHqCCo9WqFp`Pm&;PF5Ij}UXr``CgM65@ zc#o6iBq+avVkf13OylOHyDolNXmmL5xieC|)RJ69&Ri>Ov83;qFY_ed3i$av>&SN_ zP3X$!&Wt`qfX0O( zzete_pv9FB;XiPI0^#u1D+S2Zq!&w*f&Gs5pMIw%4eWPKzlv5+TasTnp zoGb&1`S1(?gH--aK}mUiNV_OD6>*bbjQ!K9*ruN$Jugrq1RqeAMe*1xDu@qazc zkpwBeJ`Ooipj<{=MXMj@)mW|tmsk7x>9=lqnNsIkUPIJV+}@OnhF*6+ei&?60ZvoB zOm8_gpyhC2us3~S9@I{D4VKBcDQj?8-fI2KoZ@m@)4dnJQ6GLv~n=YZj zY))oe1`n1AT}`17Shhupx+vBct>u=b&wJJw^1%&`3s%8Q<&|sr1rsi+PSHZtMrbC9 zngg;FW*rt|juzf7&@LHUk)G6UBOFeHq~u8n<8WXHWUFaDG7MXpKEzY@^;PYY_F{WU z+{T%0f8%om5i=`@dC(fn+=<9KI3LsPyx`Csf|)Iw${4g05KOpB1oeN~PPM_{I6S6~ ze$|O(baMUPdpg&QxH4}IAMzD3P_l$lj+eS$7Ne1V!4*M&$oZ=3tb>Yn2$0V+O zoU5XlTk6_Cz_1zJBsk>IwFVqGh$0D-iG+A%x6e`hbl&jVOp}c0&=jcx>w@kyTD@G()td^5)-j@ z6wCx(2=o86cNKn7ZEKqjrAtN-=@M~hknS3!l@13fX;4C>C5E9v2OS25K@gBs8U=wt zq+4JF>6C6nz76Nx>p9$WzrWzZ?>Bqzwch91E8ch3>{!n-<=5@G3cl|(;3oCq{s5fk zO=o7dfS6b~&s=_S+t*kwCZFg@<#G-@-Ohux{jXSvv4ch$=}P#Pqxp$wq>TXr-{(~! z8XCd-)I_gxKR)z|mVf*J+n6k^l94u-bftK_X{$rw7K) zX4ekM6Tw>$6GBhrcKJ3vuFxb>#FyHE7w%zkk6=Zw$a^W#6GfF;coUC7j;d>)JI&^- zX&wiFYdb9*0yCb=g62s#o_!%7I7*L}e_t>p{*`nd+H8$KrTfiZayoVp%Qh|ZYWrQP z!uw1`y|xG3T9iVQf$+YqVx@cXJe8m>mBlwarxpgJp}^C$QY~CKd%V2kE zR80$Iza)61`;9WqDi4fR)C|%PnEXO01xLap6*t$OvFClil?;T~Coz19f!JqEQZsy> zEjdJPfQj`v?;u;A8xCwl9j6(ML(jR5#v7z2RjEc;UCuYJ1C=QANu}N7d|{iFtdvbp zv_h@`bbT9ZR)&WhcX(9@Sr!lq+#r=5pnZg+%}ifTL4>1Ca21P0sNHN$2_CPQDiCet zeIh|CS9kS)a?Rsv7!v>RA&q^}!}&&Igvi&n2Xbmv2j%rSA4c^*kxSEcwWV0jlTNCA z;e^k=$WUm_C;0@jD!woejTpm=7}IZ|(TMuwZ&pRVL-_RphVuJm1EElxPavOE4}j*n zLe&*x@lYRLq+!&`OHtey6=ubR$^cC|;wfkFIlchY7Eft>@heJWMEH?y5vw%H znFYPJ!76R_%Z0m-SlCqeO)-DW>e_Kxvs$^N><66AJU7pPI#HIK)8MlXI8tqy)#O-# zU(&AD`Ev9vq`(yTSCz$RlJzsnOrf^o_MDlJf(nYAD_*Uo&)Ml&%6MMH#rXE1KPxNe z%TN_^Ap~F=iWJ>9CdR)QZ{;848Bn5|bTEwbq=cIJvZ81#KG5*`iMB0K9UwY%4d9-e z6ah6$$|6RZtiHWQvaeueuo2!^ga`N9OIi%=e7ZNNyFN%aP;M+%R3s~_Q0dK#&+dPS^7|( zatskBz0UO3EOWl|Y;@ZyTU$$*>M*lte$9w9(Ig}}cBySOnf9_+nr7Z6AI#V*l=D*W zts?JKi;iK?Ozx>~wyB=_W^%0A>dQW&^@`os`n6h2AsHU=RvZpptaO8}ks|(ag{TN` zW4>3&!{J0NQc(GD`hXVeLj!r~!y&LYk?H3puJ5DVgtT5!@U7aRg5ym*tnv>i5gT~z>gcnzB^%U47 zjAaQFv7ab%X*u*&LvI9$b7sNqQqvy z9GvLBCLp%cdFxAzls@2w^g&x_NF1`ZU$=9K((cfxVIRvpbEZbbJx=)n<98$-0tuMS zzubP;Zi4&0LA+Yo3!jmnJaM^@p2VJIKP6qps65kKVz%3s1(j~gGQLZAV`$3&w-ks& z7E}V==DM@m=DIQ$zIcjekm=(v|9vB3HXY8H$@a|Y7|3H|C-!~p#IBfBlHTMi{mS$h zPUS@RRje&bwUBrc?P9Bu!mEIT?5|b7ECP%k&hW|{ArmyCt7~Ii4D26H3WlwWxiGAZ zagi83D3~Mn@(s-UMSzeY5_hjhLN9`s2W)7@#VS-HW}Yu!86JvpDLA~>CB(^~P=WGNL#8QME^WWt?X(;kOME4*Gde8>c?@Pkhu09d5@yc#DX$CbH))<>JyZcmo zJ}Q5}rYrbZn8O@7T(j`pNaSuFxy)N)g#_m}q?+Yv)^88WQ99GJ25)#!-@lO=U%_a< z4@@h6D~u6Jmk?2-3O3{X6i>a>^a9h#Xt{ooduL=YWaO%LAs2Is&^qV^1)S_?(GXx0ghJ_2w{`$%oYxAa6a_LFBP?%K@4XFsU zBkqL|_mw7$$%nFnR!Oz}bRi|t;VGg&Gc+49CQ81t7@^HhIJJ^1zc#p%#e3Qw&Nomd z^i;(V$S^p~$R46Wq_<*$b6<#afpdutL7AJzIvCkf7Z;EJV0!KM1!FSaFbHLKKN5jP z^kmPkcEg1v+%O2QYj*It&%d1Eiwj4<$&tOZThl^MG3|_lDL_Rh^IQEONK-{*Z~3YN z2Eil&MaGLXm2Pq}yq=z$_K#@#!6chA9#8FUpW`WlS(FrECh5iihz;u!ta!kOpB*yE zlG&&gGu`HNpXQ?u86~8qo5)^kUsZbRsc}iy+y+8&x;yfjKcx4rJ&Pt%UspVV)|2~6 zx|~P?mBTiACtc{2!3BPr_)tznEm|Z%?XZLK%n}nLnG(;J3F2r5$$ks8hjVu2@i0xR zAT^2M-EitDI7%A;&^QdFz$g&ajX@D|5qg z`h6V~aMn1_DSz$^DS+G$)tjB~fYF$O2b2lj0@}iC8|a>{1-5<>D5s~I>qe)91LpoBvL1eawC#&lpuxL-W}G!R z|DTCx4W7F*#n@jQRP?O4rp4nq`sb2*klOd49dB}Kjf9g7kZg>?Qk$AQb!Z=HU0`Gs zytYoNK9VFAYrl%j@hmsU6>*;Hm^dt=yEm}O$cDE_S|hThf$|wh>6~s(xplMoAy5~* z#gR&&v2<^qmU;u75}yeaLxolL{X?K^cyD;(J#D*c-wy{g=j=LLU#B0(&fNdOkyz8R z+$)M2hVI%yXQ&;q9p%t%YK?Dmm}qL=N6&>&vZv3gf9#e#J~~|9&HeV#H8ZH@WHWHH zkZpr$(5@+!H>sX0E3;Z}WfJfxuKTWQwBu7?|wI8vgE8vTsaM zrut-|g;^Tr+a+1J$qyZFy@tN3;EXOzS{c4mp+7uAf&Y->fCVLISXLufp)+L5xopYy zG}gin5Dz%!_{xd9PC_8=CJmkGXj ze9<2ij9*`8HZ!s5Gh3dXoJnc*@gHRs%H7NEYXGk70I0@N|J9YD?q2u)=gWW-|M>?` zw$^Q8rE8hc`AI>(cD?7o9sPsGa(4zEBX)U$YPABR#MJQMXt(cSf#qCy0@i!qvx~gV zCHITXMGQmQE$TRu3ktDX3;`Kg!-3S}uNrO^aoxB^&NmvaTE4Q$PAx{87V2O)Xk&pZ zzRu~Io@e;Zv&f#&ycD;^b>_-wY{3`a)t|kEo}De1tnuSXs~aycKf`)r@tOiyv+xaI zxTe7`%J4NpUl97eO+{nOvNHqVB#XUdvB|z7^oj9RC^!5Pal( zCrdq?EKp$RnIyk^N|gTx1yjg^C}%&ITdLZA2G+Z%estJ&EN(Ba7e#i$hLMT^)!!3k zp-u=9XmqgVIQqw#wOX;Apf*5-==qh?Z_+bi3#hFNRN2wi$?eqpT++wf*zZuOPH@a# z)%)nM@c57g)UBKvsJMwsA_CR65Kz$H+*53FGiaIe>{=1mo}D%u?Q9a!$AI1imQr zYFQ&l;Ts3dt)kDA>FEb2xgpoqFErqlh6sQ!o%^2%F5PpY154PrHDE)kalP^9h&sp- zOkfEFu*=YK9bpcxv~g?1hE)@KUpz~Y2K(BqHef@mr!%i2{(V5~O*zNXA&Ynf-ot`y zRvWS5)x=vkbGRM&2x2g$4NHTJM{lS<4v<9M!GTZ*C)ltw%7pn7Y<>Pg1|-oUc)+?g zs0Nu(f4nV%InoZ=w9RI|R4tu?fdMU@;sH8so$>)AZJo-2RBfF@2QAKejT?Qj+q!l8 zDsbJ7eU&($Y+m)=_$(Gxc~}@7IUm1)4?0h!Hztct^%~5KuAUdBFPfdF)*F|_tSSu) zpgZQhU?7Ul)96jg;#Ad!J*Si9gBghCi*_JqyR4f53(rsg{8>St!jtA@ge1{-!XqF^-i*ZG}|w)1!mdeK>0s?T7;gP&(_ zWx(XpKgdJ632e;l+Lk^Ym%E0-3NY%r zWzy@qQNVd52r(&RUeP?2AB+6(?A>P(xaGcHpZ&O6X~B=!TFDUg@lc`;D~ynLZOR5g z$9OZ_v?{Z1!-^QQh|MldJP7=V@YE zwkp{m@ZJqLvlX)k2!>7xOqA8co@UgU7+(151=ZvWX^-Q|2@#Zdnu=G4HM#pGj_b-K z>NAk$VK{?HHmJIGYJ_E|E=AL=w*P71x$7pt*D_KIq&chsM#y??2&B3h&CxZ^#hoMh z=oun)YQ^%d0jxY%aGr+tDjGablVX6B&5(MA*k)Zk&DjG8!~vfs5-Mg@x8Gzl!Tu+{Nj3%Ym?kUwsZ8K09-O@AE z`%~0ki{Tp+!^i*d%&x!e9LPTS*nXvTSd-0oVRWi8obSoUvkl?l=|Rh_8Q@bjpr&G< zseGT+(){N`aE^yJY=Yu7o!hOAvBuO-oqR#kjD|tdhoV5q{^AIjF(1U{y?Cp?3MRKSi^TuRx9$nn{E>yxjbT` zP%jh()r>T?F9aHi>F&vmJUYY=T$>1`tk`n%TJ|8eNjEQcbr^Tz6xf<8h%2a8>a}j> z7c_an;t`Bxa{J4z zF{`V;0>rlMWp$Z^k2t#fIjdeCExPah@SOgjSVy%=WB_JS`w?_ZWlVz8r+DHg(AQEw zPMGU*6|QU5XgPbg(QBOFXxKGwAX(oiKTC--z(&=oEawnqAA8hxu+HcMc6b^1I;#kJ z-~MR4c+(pD`g7e6aeY6EFpfB%=`TdlODbG#5IlOv&w}g>xqVv0YmuH>H!GQ%Wa8oz z?#Xo)kMwv;CfmH>Z=rV83e{)?^T$SV2sZ9}@e$gu(AOBc1T!7krH;yh%dl6`V}IGTo= zw?`vc*>OJp*xzsWA)%ONm%0C1Y)~`f8up2Pv=<*~OJ3gS1=~-Y{CuuSQ|LJW-wkYL}2Rol$+h#*=1)DTBl^H+0=N#3qCsEBqZw=njF*3(G_*yR%^4*VYfV zPC6WwkrD*n^0=S2L+c|gzUvn}y;2?|0rQpds})-piquv9IlS0&FMz{tqDL;?MFVH@S%8HDEVD6_?PQ?DzsSHdjBVbM!-P zcfgzhLuw@_sHd{at?`#gyhO(C8v7cT&adsd($??W79P1#rw}u%e<(OK{w8~4sykD_ zz*CfH_^n01ZxHp>pNt>Pe;u~VROMpSJ!+XQZE#2Y5YWUpPn%1~ZJSRt$}a~wT82!o zBjIC>wS!d~a_@AMgcvlJmjvb5I!2d1hP-pzFB{9scdry2(0yPS)kJ+Qe$;t)AG^~u zFvvbm*&C$sF?=mb;=8LQ`SI7{Cj1bt;{eM$zjP8JxWa?q@Hh$TEuJ*fI0!5hSY5w+ z0ny|lar`stg5ule3$~i1>|su5msg27pj_A&C5MAb$t8=6O^=`3M~oE&V8vJ0=XE^S zmsJbfRw!Yb%unR1?0@zIA6G4Y4Ey+fmB?isAJC0Eq^=Ud@oKC`8Py?cEf-wB5y-1l zI?g}z%;)V#yd1D&rjHb|Ls0W(6JC$L9@o2Rjug;kYdf+Zeh4+%sTCBMikV_W86M|7 zLA=wjZux%sVm6=p&}(L)PLjUFODYc{-{w^7VUR71*GR@XNj8b6IB?PXN(x3O8aA$m zd}b%9_cu)9RZw>^?~@@G18zTK-Q7smW$~zvloa^72-wI-JGGj{uIZ_Hg?X4QVDD-_ zA$)B00|}{bytKET;B-)w_}YYljE?_-6ZJFNpdtnCPr|5+_JuPJKRxypS%WBp0|Xq1 zP3#?SUx@Wm0%t|)FHGp6$qm^ho-bQuY)o#z<*<;3hAH6flp@c@;#+d&CPW@qLHo;V z6G7@esGlq0{$6SEmHM{BaToZsU?4|@YDLbdJl>>Gs!?ICH*-&_NH%;(O6rRGQR9YT z*0eMEAzv5q=waHarjbb%gj5g&9W^S zPk8*8ZGOG4yH-CDsdD{J$+B$}#5zOJ(zrWL-~<>*{upL(@vZ}b^Uo{#{OelgU)z6J z-$zgT?*xBeRpej5(``KvrGHst3^v1p9h~; z{QeD|AUgy9*8e^aJ+F`Y8@d80@B!ubKChN~p5eS=;co^cpriBWdI4wpIsZk!@I2vp z6~Nzw>7X;h^O}I?3C`;n{U%^!`+rLGTh-`1;dyPK--Pt+=Lvr+1)XO(KYQjkinh4i4`f9GvsF=+2}6ejnto=q=N~p#ODONW>5QnE%-BdXIz!i9p!|Bog0c^Z_ AhX4Qo literal 0 HcmV?d00001 diff --git a/schemas/SystemSchema.json b/schemas/SystemSchema.json new file mode 100644 index 0000000..bae75f3 --- /dev/null +++ b/schemas/SystemSchema.json @@ -0,0 +1,54 @@ +// HybridRow RecordIO Schema +{ + "name": "Microsoft.Azure.Cosmos.HybridRow.RecordIO", + "version": "v1", + "schemas": [ + { + "name": "EmptySchema", + "id": 2147473650, + "type": "schema", + "properties": [] + }, + { + "name": "Segment", + "id": 2147473648, + "type": "schema", + "properties": [ + { + "path": "length", + "type": { "type": "int32", "storage": "fixed" }, + "comment": + "(Required) length (in bytes) of this RecordIO segment header itself. Does NOT include the length of the records that follow." + }, + { + "path": "comment", + "type": { "type": "utf8", "storage": "sparse" }, + "comment": "A comment describing the data in this RecordIO segment." + }, + { + // TODO: this should be converted to a HybridRow UDT instead. + "path": "sdl", + "type": { "type": "utf8", "storage": "sparse" }, + "comment": "A HybridRow Schema in SDL (json-format)." + } + ] + }, + { + "name": "Record", + "id": 2147473649, + "type": "schema", + "properties": [ + { + "path": "length", + "type": { "type": "int32", "storage": "fixed", "nullable": false }, + "comment": "(Required) length (in bytes) of the HybridRow value that follows this record header." + }, + { + "path": "crc32", + "type": { "type": "uint32", "storage": "fixed", "nullable": false }, + "comment": "(Optional) CRC-32 as described in ISO 3309." + } + ] + } + ] +} diff --git a/test-data/BatchApiSchema.json b/test-data/BatchApiSchema.json new file mode 100644 index 0000000..7922591 --- /dev/null +++ b/test-data/BatchApiSchema.json @@ -0,0 +1,96 @@ +{ + "name": "Microsoft.Azure.Cosmos.BatchApi", + "version": "v1", + "schemas": [ + { + "name": "BatchRequestHeaders", + "id": 1, + "type": "schema", + "properties": + [ + { + "path": "sampleRequestHeader", + "type": { "type": "int64", "storage": "fixed" } + } + ] + }, + { + "name": "BatchOperation", + "id": 2, + "type": "schema", + "properties": + [ + { + "path": "operationType", + "type": { "type": "int32", "storage": "fixed" } + }, { + "path": "headers", + "type": { "type": "schema", "name": "BatchRequestHeaders" } + }, { + "path": "resourceType", + "type": { "type": "int32", "storage": "fixed" } + }, { + "path": "resourcePath", + "type": { "type": "utf8", "storage": "variable", "length": 1024 } + }, { + "path": "resourceBody", + "type": { "type": "binary", "storage": "variable" } + } + ] + }, + { + "name": "BatchRequest", + "id": 3, + "type": "schema", + "properties": + [ + { + "path": "operations", + "type": { "type": "array", "items": { "type": "schema", "name": "BatchOperation" } } + } + ] + }, + { + "name": "BatchResponseHeaders", + "id": 4, + "type": "schema", + "properties": + [ + { + "path": "sampleResponseHeader", + "type": { "type": "utf8", "storage": "variable", "length": 1024 } + } + ] + }, + { + "name": "BatchOperationResponse", + "id": 5, + "type": "schema", + "properties": + [ + { + "path": "statusCode", + "type": { "type": "int32", "storage": "fixed" } + }, { + "path": "headers", + "type": { "type": "schema", "name": "BatchResponseHeaders" } + }, { + "path": "resourceBody", + "type": { "type": "binary", "storage": "variable" } + } + ] + }, + { + "name": "BatchResponse", + "id": 6, + "type": "schema", + "properties": + [ + { + "path": "operations", + "type": { "type": "array", "items": { "type": "schema", "name": "BatchOperationResponse" } } + } + ] + } + ] +} diff --git a/test-data/CoverageSchema.json b/test-data/CoverageSchema.json new file mode 100644 index 0000000..70ab311 --- /dev/null +++ b/test-data/CoverageSchema.json @@ -0,0 +1,211 @@ +{ + "schemas": [ + { + "name": "myUDT", // Question: what should the namespace/structure of schema identifiers. + "id": 1, + "type": "schema", // Optional: implied at the top-level (only "schema" types can be defined at the root of schemas) + "options": { + "disallowUnschematized": false // Optional: defaults to false + }, + "properties": [ + { + "path": "a", + "type": { + "type": "int8", + "storage": "fixed" + } + }, + { + "path": "b", + "type": { + "type": "utf8", + "storage": "variable" + } + } + ] + }, + { + "name": "someTable", + "id": -1, + "options": { + "disallowUnschematized": true + }, + "properties": [ + { + "path": "myBool", + "comment": "A sample fixed boolean column", + "type": { + "type": "bool", + "storage": "fixed" + } + }, + { + "path": "myInt8", + "comment": "A sample fixed 8-byte integer column", + "type": { + "type": "int8", + "storage": "fixed" + } + }, + { + "path": "nested.x", + "comment": "A sample nested integer column", + "type": { + "type": "int32", + "storage": "fixed" + } + }, + { + "path": "nested.y", + "comment": "A sample nested float column", + "type": { + "type": "float32", + "storage": "fixed" + } + }, + { + "path": "nested.deeper.z", + "comment": "A sample deeper nested double column", + "type": { + "type": "float64", + "storage": "fixed" + } + }, + { + "path": "State", + "comment": "A sample fixed 2-byte UTF-8 encoded text column", + "type": { + "type": "utf8", + "storage": "fixed", + "length": 2 + } + }, + { + "path": "myString", + "comment": "A sample variable length UTF-8 encoded text column (up to 127 bytes)", + "type": { + "type": "utf8", + "storage": "variable" + } + }, + { + "path": "lob", + "comment": "A sample extended UTF-8 encoded text column (up to 2M bytes)", + "type": { + "type": "utf8", + "storage": "sparse" + } + }, + { + "path": "canbelob", + "comment": + "A sample extended UTF-8 encoded text column (up to 2M bytes) that stores variable if 'small' (<127 bytes), but sparse if 'large'", + "type": { + "type": "utf8", + "storage": "variable" + } + }, + { + "path": "primitiveArray", + "comment": "A sample array of primitives (4-byte ints)", + "type": { "type": "array", "items": { "type": "int32" } } + }, + { + "path": "shreddedArray[0]", + "comment": "A sample fixed-length array of primitives", + "type": { "type": "int32" } + }, + { + "path": "shreddedArray[1]", + "comment": "A sample fixed-length array of primitives", + "type": { "type": "int32" } + }, + { + "path": "nestedArray", + "comment": "A sample array of nested arrays", + "type": { + "type": "array", + "items": { + "type": "array", + "items": { "type": "int32" } + } + } + }, + { + "path": "nestedNestedArray", + "comment": "A sample array of nested nested arrays", + "type": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "array", + "items": { "type": "int32" } + } + } + } + }, + { + "path": "arrayOfObject", + "comment": "A sample array of semi-structured objects", + "type": { + "type": "array", + "items": { + "type": "object", + "properties": [ + { + "path": "a", + "type": { "type": "int8" } + }, + { + "path": "b", + "type": { "type": "utf8" } + } + ] + } + } + }, + { + "path": "arrayOfAny", + "comment": "A sample heterogenous array", + "type": { + "type": "array", + "items": { "type": "any" } + } + }, + { + "path": "arrayOfUDT", + "comment": "A sample array of schematized rows", + "type": { + "type": "array", + "items": { + "type": "schema", + "name": "myUDT" // see definition above - should this be called $ref or ref or something? + } + } + }, + { + "path": "nestedObject", + "comment": "A sample nested objects", + "type": { + "type": "object", + "properties": [ + { + "path": "a", + "type": { + "type": "int8" + } + }, + { + "path": "b", + "type": { + "type": "utf8" + } + } + ] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test-data/CrossVersioningExpected.json b/test-data/CrossVersioningExpected.json new file mode 100644 index 0000000..4628eff --- /dev/null +++ b/test-data/CrossVersioningExpected.json @@ -0,0 +1,8 @@ +{ + "CrossVersionFixed": "8101000000FFFF1FAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA3E555555555555D53F2A00000000000000000000000000000000001C00CA44C50A55555505CB00B714006E39578A01D6082A00000000000000B9259C2A2E921146BB0A244A9496503C2A0000000000000000000000616263000102", + "CrossVersionNullFixed": "810100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "CrossVersionVariable": "81020000000FADD5AAD5AAD5AAD5AA01AAD5AAD5AAD5AAD5AA010361626303000102", + "CrossVersionNullVariable": "810200000000", + "CrossVersionSparse": "8103000000010103020503AA0604AAAA0705AAAAAAAA0806AAAAAAAAAAAAAAAA0907AA0A08AAAA0B09AAAAAAAA0C0AAAAAAAAAAAAAAAAA0F0BABAAAA3E100C555555555555D53F160D2A000000000000000000000000000000110E00001C00CA44C50A55555505CB00B714120F006E39578A01D60817102A000000000000001311B9259C2A2E921146BB0A244A9496503C18122A000000000000000000000014130361626315140300010222051503000000AAAAAA22220F1602000000030000000000803F0000004000004040030000000000803F00000040000040402214170300000003616263036465660368696A26020D0818ADD5AAD5AAD5AAD5AA01AAAAAAAAAAAAAAAA260201260205051901AAAA26020344040000001A02030100000002000000462E141B03000000036162630365666703787A792E22051C030000000300000001020303000000040506030000000708092E2E071D030000000300000001000000020000000300000003000000040000000500000006000000030000000700000008000000090000002E44040000001E030000000301000000020000004603030000000400000046030500000006000000462A14141F02000000044D61726B044C756B65084861727269736F6E0348616E2A0522052002000000010300000001020302030000000405062A062A0707210200000001000200000001000000020000000300000004000000020002000000050000000600000007000000080000002A1044040000002203000000000000000000004003030000000400000046000000000000084003050000000600000046000000000000F03F03010000000200000046", + "CrossVersionNullSparse": "8103000000" +} diff --git a/test-data/CrossVersioningSchema.json b/test-data/CrossVersioningSchema.json new file mode 100644 index 0000000..e5f9f0a --- /dev/null +++ b/test-data/CrossVersioningSchema.json @@ -0,0 +1,127 @@ +// Set of types used in the cross versioning tests. +{ + "schemas": [ + { "name": "Fixed", "id": 1, "type": "schema", + "properties": [ + { "path": "null", "type": { "type": "null", "storage": "fixed" } }, + { "path": "bool", "type": { "type": "bool", "storage": "fixed" } }, + { "path": "int8", "type": { "type": "int8", "storage": "fixed" } }, + { "path": "int16", "type": { "type": "int16", "storage": "fixed" } }, + { "path": "int32", "type": { "type": "int32", "storage": "fixed" } }, + { "path": "int64", "type": { "type": "int64", "storage": "fixed" } }, + { "path": "uint8", "type": { "type": "uint8", "storage": "fixed" } }, + { "path": "uint16", "type": { "type": "uint16", "storage": "fixed" } }, + { "path": "uint32", "type": { "type": "uint32", "storage": "fixed" } }, + { "path": "uint64", "type": { "type": "uint64", "storage": "fixed" } }, + { "path": "float32", "type": { "type": "float32", "storage": "fixed" } }, + { "path": "float64", "type": { "type": "float64", "storage": "fixed" } }, + { "path": "float128", "type": { "type": "float128", "storage": "fixed" } }, + { "path": "decimal", "type": { "type": "decimal", "storage": "fixed" } }, + { "path": "datetime", "type": { "type": "datetime", "storage": "fixed" } }, + { "path": "unixdatetime", "type": { "type": "unixdatetime", "storage": "fixed" } }, + { "path": "guid", "type": { "type": "guid", "storage": "fixed" } }, + { "path": "mongodbobjectid", "type": { "type": "mongodbobjectid", "storage": "fixed" } }, + { "path": "utf8", "type": { "type": "utf8", "storage": "fixed", "length": 3 } }, + { "path": "binary", "type": { "type": "binary", "storage": "fixed", "length": 3 } } + ]}, + { "name": "Variable", "id": 2, "type": "schema", + "properties": [ + { "path": "varint", "type": { "type": "varint", "storage": "variable" } }, + { "path": "varuint", "type": { "type": "varuint", "storage": "variable" } }, + { "path": "utf8", "type": { "type": "utf8", "storage": "variable"} }, + { "path": "binary", "type": { "type": "binary", "storage": "variable" } } + ]}, + { "name": "Sparse", "id": 3, "type": "schema", + "properties": [ + { "path": "null", "type": { "type": "null" } }, + { "path": "bool", "type": { "type": "bool" } }, + { "path": "int8", "type": { "type": "int8" } }, + { "path": "int16", "type": { "type": "int16" } }, + { "path": "int32", "type": { "type": "int32" } }, + { "path": "int64", "type": { "type": "int64" } }, + { "path": "uint8", "type": { "type": "uint8" } }, + { "path": "uint16", "type": { "type": "uint16" } }, + { "path": "uint32", "type": { "type": "uint32" } }, + { "path": "uint64", "type": { "type": "uint64" } }, + { "path": "float32", "type": { "type": "float32" } }, + { "path": "float64", "type": { "type": "float64" } }, + { "path": "float128", "type": { "type": "float128" } }, + { "path": "decimal", "type": { "type": "decimal" } }, + { "path": "datetime", "type": { "type": "datetime" } }, + { "path": "unixdatetime", "type": { "type": "unixdatetime" } }, + { "path": "guid", "type": { "type": "guid" } }, + { "path": "mongodbobjectid", "type": { "type": "mongodbobjectid" } }, + { "path": "utf8", "type": { "type": "utf8" } }, + { "path": "binary", "type": { "type": "binary" } }, + { "path": "array_t", "type": { + "type": "array", + "items": { "type": "int8", "nullable": false } + } }, + { "path": "array_t>", "type": { + "type": "array", + "items": { "type": "array", "nullable": false, "items": { "type": "float32", "nullable": false } } + } }, + { "path": "array_t", "type": { "type": "array", "items": { "type": "utf8", "nullable": false } } }, + { "path": "tuple", "type": { + "type": "tuple", + "items": [ { "type": "varint", "nullable": false }, { "type": "int64", "nullable": false }] + } }, + { "path": "tuple>", "type": { + "type": "tuple", "items": [ + { "type": "null", "nullable": false }, + { "type": "tuple", "nullable": false, "items": [ { "type": "int8", "nullable": false }, { "type": "int8", "nullable": false } ] } + ]}}, + { "path": "tuple", "type": { + "type": "tuple", "items": [ + { "type": "bool", "nullable": false }, + { "type": "schema", "name": "Point", "nullable": false} + ]}}, + { "path": "set_t", "type": { + "type": "set", + "items": { "type": "utf8", "nullable": false } + } }, + { "path": "set_t>", "type": { + "type": "set", + "items": { "type": "array", "nullable": false, "items": { "type": "int8", "nullable": false } } + } }, + { "path": "set_t>", "type": { + "type": "set", + "items": { "type": "set", "nullable": false, "items": { "type": "int32", "nullable": false } } + } }, + { "path": "set_t", "type": { + "type": "set", + "items": { "type": "schema", "name": "Point", "nullable": false} + } }, + { "path": "map_t", "type": { + "type": "map", + "keys": { "type": "utf8", "nullable": false }, + "values": { "type": "utf8", "nullable": false } + } }, + { "path": "map_t>", "type": { + "type": "map", + "keys": { "type": "int8", "nullable": false }, + "values": { "type": "array", "nullable": false, "items": { "type": "int8", "nullable": false } } + } }, + { "path": "map_t>", "type": { + "type": "map", + "keys": { "type": "int16", "nullable": false }, + "values": { + "type": "map", + "nullable": false, + "keys": { "type": "int32", "nullable": false }, + "values": { "type": "int32", "nullable": false } + } + } }, + { "path": "map_t", "type": { + "type": "map", + "keys": { "type": "float64", "nullable": false }, + "values": { "type": "schema", "name": "Point", "nullable": false} + } } + ]}, + { "name": "Point", "id": 4, "type": "schema", + "properties": [ + { "path": "x", "type": { "type": "int32", "storage": "fixed" } }, + { "path": "y", "type": { "type": "int32", "storage": "fixed" } } + ]} + ] +} diff --git a/test-data/CustomerSchema.json b/test-data/CustomerSchema.json new file mode 100644 index 0000000..1777ca2 --- /dev/null +++ b/test-data/CustomerSchema.json @@ -0,0 +1,76 @@ +// Partial implementation of Cassandra Hotel Schema described here:: +// https://www.oreilly.com/ideas/cassandra-data-modeling +{ + "name": "Microsoft.Azure.Cosmos.Serialization.HybridRow.Tests.Unit.CustomerSchema", + "schemas": [ + { + "name": "PostalCode", + "id": 1, + "type": "schema", + "properties": [ + { "path": "zip", "type": { "type": "int32", "storage": "fixed" } }, + { "path": "plus4", "type": { "type": "int16", "storage": "sparse" } } + ] + }, + { + "name": "Address", + "id": 2, + "type": "schema", + "properties": [ + { "path": "street", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "city", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "state", "type": { "type": "utf8", "storage": "fixed", "length": 2 } }, + { "path": "postal_code", "type": { "type": "schema", "name": "PostalCode" } } + ] + }, + { + "name": "Hotels", + "id": 3, + "type": "schema", + "partitionkeys": [{ "path": "hotel_id" }], + "properties": [ + { "path": "hotel_id", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "name", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "phone", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "address", "type": { "type": "schema", "name": "Address", "immutable": true } } + ] + }, + { + "name": "Available_Rooms_By_Hotel_Date", + "id": 4, + "type": "schema", + "partitionkeys": [{ "path": "hotel_id" }], + "primarykeys": [{ "path": "date" }, { "path": "room_number", "direction": "desc" }], + "properties": [ + { "path": "hotel_id", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "date", "type": { "type": "datetime", "storage": "fixed" } }, + { "path": "room_number", "type": { "type": "uint8", "storage": "fixed" } }, + { "path": "is_available", "type": { "type": "bool" } } + ] + }, + { + "name": "Guests", + "id": 5, + "type": "schema", + "partitionkeys": [{ "path": "guest_id" }], + "primarykeys": [{ "path": "first_name" }, { "path": "phone_numbers", "direction": "desc" }], + "properties": [ + { "path": "guest_id", "type": { "type": "guid", "storage": "fixed" } }, + { "path": "first_name", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "last_name", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "title", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "emails", "type": { "type": "array", "items": { "type": "utf8", "nullable": false } } }, + { "path": "phone_numbers", "type": { "type": "array", "items": { "type": "utf8", "nullable": false } } }, + { + "path": "addresses", + "type": { + "type": "map", + "keys": { "type": "utf8", "nullable": false }, + "values": { "type": "schema", "name": "Address", "immutable": true, "nullable": false } + } + }, + { "path": "confirm_number", "type": { "type": "utf8", "storage": "variable" } } + ] + } + ] +} diff --git a/test-data/MovieSchema.json b/test-data/MovieSchema.json new file mode 100644 index 0000000..11a6730 --- /dev/null +++ b/test-data/MovieSchema.json @@ -0,0 +1,40 @@ +// Todo demo schema that utilizes typed maps. +{ + "schemas": [ + { "name": "Movie", "id": 1, "type": "schema", + "properties": [ + { "path": "cast", "type": { + "type": "map", + "keys": { "type": "utf8", "nullable": false }, + "values": { "type": "utf8", "nullable": false } + } }, + { "path": "stats", "type": { + "type": "map", + "keys": { "type": "guid", "nullable": false }, + "values": { "type": "float64", "nullable": false } + } }, + { "path": "related", "type": { + "comment": "map: actor -> { map: moveId -> roleName }", + "type": "map", + "keys": { "type": "utf8", "nullable": false }, + "values": { + "type": "map", + "nullable": false, + "keys": { "type": "int64", "nullable": false }, + "values": { "type": "utf8", "nullable": false } + } + } }, + { "path": "revenue", "type": { + "comment": "map: releaseDate -> Earnings }", + "type": "map", + "keys": { "type": "datetime", "nullable": false }, + "values": { "type": "schema", "name": "Earnings", "nullable": false } + } } + ]}, + { "name": "Earnings", "id": 2, "type": "schema", + "properties": [ + { "path": "domestic", "type": { "type": "decimal", "storage": "fixed" } }, + { "path": "worldwide", "type": { "type": "decimal", "storage": "fixed" } } + ]} + ] +} \ No newline at end of file diff --git a/test-data/NullableSchema.json b/test-data/NullableSchema.json new file mode 100644 index 0000000..cf55e42 --- /dev/null +++ b/test-data/NullableSchema.json @@ -0,0 +1,26 @@ +// Demo schema that utilizes nullable typed scopes. +{ + "schemas": [ + { + "name": "Nullables", + "id": 1, + "type": "schema", + "properties": [ + { "path": "nullbool", "type": { "type": "array", "items": { "type": "bool" } } }, + { "path": "nullset", "type": { "type": "set", "items": { "type": "utf8" } } }, + { "path": "nullarray", "type": { "type": "array", "items": { "type": "float32" } } }, + { + "path": "nulltuple", + "type": { + "type": "array", + "items": { "type": "tuple", "nullable": false, "items": [{ "type": "int32" }, { "type": "int64" }] } + } + }, + { + "path": "nullmap", + "type": { "type": "map", "keys": { "type": "guid" }, "values": { "type": "uint8" } } + } + ] + } + ] +} diff --git a/test-data/PerfCounterSchema.json b/test-data/PerfCounterSchema.json new file mode 100644 index 0000000..8bb24d7 --- /dev/null +++ b/test-data/PerfCounterSchema.json @@ -0,0 +1,72 @@ +// Performance Counter demo schema that utilizes tuples. +{ + "schemas": [ + { + "name": "Coord", + "id": 2, + "type": "schema", + "properties": [ + { "path": "lat", "type": { "type": "int64", "storage": "fixed" } }, + { "path": "lng", "type": { "type": "int64", "storage": "fixed" } } + ] + }, + { + "name": "Counters", + "id": 1, + "type": "schema", + "partitionkeys": [{ "path": "name" }], + "properties": [ + { "path": "name", "type": { "type": "utf8", "storage": "variable" } }, + { + "path": "value", + "type": { + "type": "tuple", + "immutable": true, + "items": [{ "type": "utf8", "nullable": false }, { "type": "int64", "nullable": false }] + } + }, + { + "path": "minmeanmax", + "type": { + "type": "tuple", + "immutable": true, + "items": [ + { "type": "utf8", "nullable": false }, + { + "type": "tuple", + "nullable": false, + "items": [ + { "type": "int64", "nullable": false }, + { "type": "int64", "nullable": false }, + { "type": "int64", "nullable": false } + ] + } + ] + } + }, + { + "path": "coord", + "type": { + "type": "tuple", + "immutable": true, + "items": [{ "type": "utf8", "nullable": false }, { "type": "schema", "name": "Coord", "nullable": false }] + } + } + ] + }, + { + "name": "CounterSet", + "id": 3, + "type": "schema", + "properties": [ + { + "path": "history", + "type": { + "type": "array", + "items": { "type": "schema", "name": "Counters", "nullable": false } + } + } + ] + } + ] +} diff --git a/test-data/ReaderSchema.json b/test-data/ReaderSchema.json new file mode 100644 index 0000000..69f08b6 --- /dev/null +++ b/test-data/ReaderSchema.json @@ -0,0 +1,143 @@ +// Set of types used in the IO tests. +{ + "schemas": [ + { "name": "Mixed", "id": 1, "type": "schema", + "properties": [ + { "path": "null", "type": { "type": "null", "storage": "fixed" } }, + { "path": "bool", "type": { "type": "bool", "storage": "fixed" } }, + { "path": "int8", "type": { "type": "int8", "storage": "fixed" } }, + { "path": "int16", "type": { "type": "int16", "storage": "fixed" } }, + { "path": "int32", "type": { "type": "int32", "storage": "fixed" } }, + { "path": "int64", "type": { "type": "int64", "storage": "fixed" } }, + { "path": "uint8", "type": { "type": "uint8", "storage": "fixed" } }, + { "path": "uint16", "type": { "type": "uint16", "storage": "fixed" } }, + { "path": "uint32", "type": { "type": "uint32", "storage": "fixed" } }, + { "path": "uint64", "type": { "type": "uint64", "storage": "fixed" } }, + { "path": "float32", "type": { "type": "float32", "storage": "fixed" } }, + { "path": "float64", "type": { "type": "float64", "storage": "fixed" } }, + { "path": "float128", "type": { "type": "float128", "storage": "fixed" } }, + { "path": "decimal", "type": { "type": "decimal", "storage": "fixed" } }, + { "path": "datetime", "type": { "type": "datetime", "storage": "fixed" } }, + { "path": "unixdatetime", "type": { "type": "unixdatetime", "storage": "fixed" } }, + { "path": "guid", "type": { "type": "guid", "storage": "fixed" } }, + { "path": "mongodbobjectid", "type": { "type": "mongodbobjectid", "storage": "fixed" } }, + { "path": "utf8", "type": { "type": "utf8", "storage": "fixed", "length": 3 } }, + { "path": "utf8_span", "type": { "type": "utf8", "storage": "fixed", "length": 3 } }, + { "path": "binary", "type": { "type": "binary", "storage": "fixed", "length": 3 } }, + { "path": "binary_span", "type": { "type": "binary", "storage": "fixed", "length": 3 } }, + { "path": "binary_sequence", "type": { "type": "binary", "storage": "fixed", "length": 3 } }, + { "path": "var_varint", "type": { "type": "varint", "storage": "variable" } }, + { "path": "var_varuint", "type": { "type": "varuint", "storage": "variable" } }, + { "path": "var_utf8", "type": { "type": "utf8", "storage": "variable"} }, + { "path": "var_utf8_span", "type": { "type": "utf8", "storage": "variable"} }, + { "path": "var_binary", "type": { "type": "binary", "storage": "variable" } }, + { "path": "var_binary_span", "type": { "type": "binary", "storage": "variable" } }, + { "path": "var_binary_sequence", "type": { "type": "binary", "storage": "variable" } }, + { "path": "sparse_null", "type": { "type": "null" } }, + { "path": "sparse_bool", "type": { "type": "bool" } }, + { "path": "sparse_int8", "type": { "type": "int8" } }, + { "path": "sparse_int16", "type": { "type": "int16" } }, + { "path": "sparse_int32", "type": { "type": "int32" } }, + { "path": "sparse_int64", "type": { "type": "int64" } }, + { "path": "sparse_uint8", "type": { "type": "uint8" } }, + { "path": "sparse_uint16", "type": { "type": "uint16" } }, + { "path": "sparse_uint32", "type": { "type": "uint32" } }, + { "path": "sparse_uint64", "type": { "type": "uint64" } }, + { "path": "sparse_float32", "type": { "type": "float32" } }, + { "path": "sparse_float64", "type": { "type": "float64" } }, + { "path": "sparse_float128", "type": { "type": "float128" } }, + { "path": "sparse_decimal", "type": { "type": "decimal" } }, + { "path": "sparse_datetime", "type": { "type": "datetime" } }, + { "path": "sparse_unixdatetime", "type": { "type": "unixdatetime" } }, + { "path": "sparse_guid", "type": { "type": "guid" } }, + { "path": "sparse_mongodbobjectid", "type": { "type": "mongodbobjectid" } }, + { "path": "sparse_utf8", "type": { "type": "utf8" } }, + { "path": "sparse_utf8_span", "type": { "type": "utf8" } }, + { "path": "sparse_binary", "type": { "type": "binary" } }, + { "path": "sparse_binary_span", "type": { "type": "binary" } }, + { "path": "sparse_binary_sequence", "type": { "type": "binary" } }, + { "path": "array_t", "type": { + "type": "array", + "items": { "type": "int8", "nullable": false } + } }, + { "path": "array_t>", "type": { + "type": "array", + "items": { "type": "array", "nullable": false, "items": { "type": "float32", "nullable": false } } + } }, + { "path": "array_t", "type": { "type": "array", "items": { "type": "utf8", "nullable": false } } }, + { "path": "tuple", "type": { + "type": "tuple", + "items": [ { "type": "varint", "nullable": false }, { "type": "int64", "nullable": false }] + } }, + { "path": "tuple>", "type": { + "type": "tuple", "items": [ + { "type": "null", "nullable": false }, + { "type": "tuple", "nullable": false, "items": [ { "type": "int8", "nullable": false }, { "type": "int8", "nullable": false } ] } + ]}}, + { "path": "tuple", "type": { + "type": "tuple", "items": [ + { "type": "bool", "nullable": false }, + { "type": "schema", "name": "Point", "nullable": false} + ]}}, + { "path": "nullable", "type": { + "type": "tuple", + "items": [ { "type": "int32", "nullable": true }, { "type": "int64", "nullable": true }] + } }, + { "path": "tagged", "type": { + "type": "tagged", "items": [ + { "type": "utf8", "nullable": false } + ]}}, + { "path": "tagged", "type": { + "type": "tagged", "items": [ + { "type": "bool", "nullable": false }, + { "type": "utf8", "nullable": false } + ]}}, + { "path": "set_t", "type": { + "type": "set", + "items": { "type": "utf8", "nullable": false } + } }, + { "path": "set_t>", "type": { + "type": "set", + "items": { "type": "array", "nullable": false, "items": { "type": "int8", "nullable": false } } + } }, + { "path": "set_t>", "type": { + "type": "set", + "items": { "type": "set", "nullable": false, "items": { "type": "int32", "nullable": false } } + } }, + { "path": "set_t", "type": { + "type": "set", + "items": { "type": "schema", "name": "Point", "nullable": false} + } }, + { "path": "map_t", "type": { + "type": "map", + "keys": { "type": "utf8", "nullable": false }, + "values": { "type": "utf8", "nullable": false } + } }, + { "path": "map_t>", "type": { + "type": "map", + "keys": { "type": "int8", "nullable": false }, + "values": { "type": "array", "nullable": false, "items": { "type": "int8", "nullable": false } } + } }, + { "path": "map_t>", "type": { + "type": "map", + "keys": { "type": "int16", "nullable": false }, + "values": { + "type": "map", + "nullable": false, + "keys": { "type": "int32", "nullable": false }, + "values": { "type": "int32", "nullable": false } + } + } }, + { "path": "map_t", "type": { + "type": "map", + "keys": { "type": "float64", "nullable": false }, + "values": { "type": "schema", "name": "Point", "nullable": false} + } } + ]}, + { "name": "Point", "id": 4, "type": "schema", + "properties": [ + { "path": "x", "type": { "type": "int32", "storage": "fixed" } }, + { "path": "y", "type": { "type": "int32", "storage": "fixed" } } + ]} + ] +} diff --git a/test-data/RootSegment.bin b/test-data/RootSegment.bin new file mode 100644 index 0000000000000000000000000000000000000000..0e9b9e8cd38220b31e19651835b3342c95362d8f GIT binary patch literal 1048576 zcmeI&Npf686a~-{eUE7jrtiU~$4nS{BaC1vEKgfu4Z?E0TOVgSOG(rqsfbgdh+FwG z^Z)lwXrO^EcDvoJ-QU0Nb`O6ZeePD?YjRY-YCacF*Tvs%|MB3?U%TIHd5G)ty9X~F z)=&O&`RMcHy_>3+mw(og`}@4OsP!nf8TRkZ`ldHMzJGc7_BGJ2CmxRE%l?p_ffs6PlIL4etx>KQXgiBQ>X~gWdx6_^ag^%?+Rh@7`rPC>)eF2+Tccbr z&~_Gq)HB;$_5$zL#Zj&oXgiBQ>T{FlR4;I+wnn*LpzSOIsb{vi>;>Mdi=$jG&~_Gq z)aNG8sb1jy+8X70fwr>f$KZ3$&d@AoaP)bE+5k zw6;dMUZCwP0;$&klhF%&RyRkvUZCwP0;x}qUdMWY&ueFt>jm1*B9Qv20$X%Jl+mXAwyKRDpZ-fKjd&XgiBQ>i<=sJ- zZf82S?*D`Frn$HMRRZ7DK*thqQd*>+deGQR}z_xCuJhnbZfgft1WCXVLv5DKg za}@ZohDb(WTenjlTc4xAPc=|70^9o7#O>ZW3jAC{BqOk`+bNH&&r#r)8YmfoZGCLw zcJCYo?$;2>2yE+i%46$u6gW1IJpu#>5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF R5FkK+009C72>j0l{sGAQn%V#W literal 0 HcmV?d00001 diff --git a/test-data/RootSegment.hybridrow b/test-data/RootSegment.hybridrow new file mode 100644 index 0000000000000000000000000000000000000000..6ce93f853d8f9cdff15b7ca189d1e52a8f2a9ed8 GIT binary patch literal 14147 zcmd^_+j84R5JX#Y>?F4A-0yeUN$lL?{6HR9_>%lczFffyeK^W&fFjp5tV$6N=$QsM zy?ZQDVi|wm%*XC^Nf-KKKDXofB742Kw2`H~R)0SHm%Y0;w^uLhq0_DXm=>LOZ_GD7 zX>;x#({#PNm@iziqBiZOoopb*4PNcot+JTw~Em}r|fJ_8GR<^A3(DOJEKEhBFp+(Dx z5Ri%BkABFG6KS7x?LbY07A+$}Kqi78D_hoi=y{w-`_0@A)I?~}G9mNG?iIR-TmTC|J^0htKC6xC^nTsa0c5n8m22mzT0{`@WK7!dn=$KN%4 z$3RVl7A+$}Kqi8J=UdQzw}%wtM4os&Y9h2~84&_95&ZeP^C1Abd&Y^p>hFGaNhpu03q`+*45#p+(Dx5Ri%BOHpkA=q`;D`NFeM6QM=Rh!Bv8;7d_;+ukt7iG1m)sEN>` zWkd+bMDV4kHUM;&#)*98S*VH7qGdz~xY_S%d0GNrifVt$0mV3xuRR?#5n8m22mzT0 zz7&;?IL3*5;}q0HXwfnv1Y{!kQdCC(d4>P4xpoX{BD8235dtz1d?~8a5P9kt)I?~} zG9mO6>C@9xhVz1KGT4`$RDZvX%Q literal 0 HcmV?d00001 diff --git a/test-data/RootSegment.json b/test-data/RootSegment.json new file mode 100644 index 0000000..df28b9b --- /dev/null +++ b/test-data/RootSegment.json @@ -0,0 +1,609 @@ +{ + "version": "v1", + "schemas": [{ + "name": "RootSegment", + "id": -1, + "type": "schema", + "properties": [{ + "path": "PropertyBag", + "type": { + "type": "schema", + "name": "RootSegmentPropertyBag", + "id": 7 + } + }, + { + "path": "SegmentInfos", + "type": { + "type": "array", + "items": { + "type": "schema", + "name": "SegmentInfo", + "id": 1, + "nullable": false + } + } + }, + { + "path": "SnapshotInfos", + "type": { + "type": "array", + "items": { + "type": "schema", + "name": "SnapshotInfo", + "id": 5, + "nullable": false + } + } + } + ] + }, + { + "name": "InvalidationManifest", + "id": -2, + "type": "schema", + "properties": [{ + "path": "PropertyBag", + "type": { + "type": "schema", + "name": "InvalidationManifestPropertyBag", + "id": 9 + } + }, + { + "path": "StreamInfos", + "type": { + "type": "array", + "items": { + "type": "schema", + "name": "InvalidationStreamInfo", + "id": 10, + "nullable": false + } + } + } + ] + }, + { + "name": "SegmentInfo", + "id": 1, + "type": "schema", + "properties": [{ + "path": "LSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "PSID", + "type": { + "type": "schema", + "name": "FileId", + "id": 2 + } + }, + { + "path": "SegmentMetadata", + "type": { + "type": "schema", + "name": "SegmentMetadata", + "id": 4 + } + }, + { + "path": "ReferenceCount", + "type": { + "type": "uint8", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "ZeroUtilizationTimestamp", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "Control", + "type": { + "type": "uint8", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "FileId", + "id": 2, + "type": "schema", + "properties": [{ + "path": "StorageAccountIndex", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "FileType", + "type": { + "type": "int16", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "FileIndex", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "PartitionId", + "type": { + "type": "guid", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "PartitionKeyRangeRid", + "type": { + "type": "binary", + "storage": "fixed", + "length": 30, + "nullable": false + } + } + ] + }, + { + "name": "SequenceVector", + "id": 3, + "type": "schema", + "properties": [{ + "path": "GlobalSequenceNumber", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "LocalSequenceNumber", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "SegmentMetadata", + "id": 4, + "type": "schema", + "properties": [{ + "path": "InitialRecordCount", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "TombstoneRecordCount", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "InvalidatedRecordCount", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "SegmentSize", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "MinSequenceVector", + "type": { + "type": "schema", + "name": "SequenceVector", + "id": 3 + } + }, + { + "path": "MaxSequenceVector", + "type": { + "type": "schema", + "name": "SequenceVector", + "id": 3 + } + }, + { + "path": "InvalidationFileId", + "type": { + "type": "schema", + "name": "FileId", + "id": 2 + } + }, + { + "path": "InvalidationStats", + "type": { + "type": "schema", + "name": "InvalidationStats", + "id": 6 + } + }, + { + "path": "SchemaHash", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "ExpiredRecordCount", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "MinRecordTimestamp", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "MaxRecordTimestamp", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "PartialSegment", + "type": { + "type": "bool", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "SnapshotInfo", + "id": 5, + "type": "schema", + "properties": [{ + "path": "SnapshotId", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "Timestamp", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "PSID", + "type": { + "type": "schema", + "name": "FileId", + "id": 2 + } + }, + { + "path": "TTL", + "type": { + "type": "int32", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "InvalidationStats", + "id": 6, + "type": "schema", + "properties": [{ + "path": "Count", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "SizeInBytes", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "RootSegmentPropertyBag", + "id": 7, + "type": "schema", + "properties": [{ + "path": "Control", + "type": { + "type": "uint8", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "NumberOfEntries", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "NumberOfSnapshots", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "LastCheckpointedLSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "LastCheckpointedSequenceVector", + "type": { + "type": "schema", + "name": "SequenceVector", + "id": 3 + } + }, + { + "path": "LastFlushedLSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "LastFlushedSequenceVector", + "type": { + "type": "schema", + "name": "SequenceVector", + "id": 3 + } + }, + { + "path": "LastRestoredSourceOffset", + "type": { + "type": "schema", + "name": "Logoffset", + "id": 8 + } + }, + { + "path": "LogVersion", + "type": { + "type": "uint8", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "Timestamp", + "type": { + "type": "uint64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "ArchivalPartitionId", + "type": { + "type": "guid", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "TTL", + "type": { + "type": "int32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "PhysicalUsageInKB", + "type": { + "type": "uint64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "LogicalUsageInKB", + "type": { + "type": "uint64", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "Logoffset", + "id": 8, + "type": "schema", + "properties": [{ + "path": "LSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "RecordGroupID", + "type": { + "type": "int32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "RecordIndex", + "type": { + "type": "int32", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "InvalidationManifestPropertyBag", + "id": 9, + "type": "schema", + "properties": [{ + "path": "NumberOfEntries", + "type": { + "type": "uint32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "MaxMergedLevel0LSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "Timestamp", + "type": { + "type": "uint64", + "storage": "fixed", + "nullable": false + } + } + ] + }, + { + "name": "InvalidationStreamInfo", + "id": 10, + "type": "schema", + "properties": [{ + "path": "InvalidationFileId", + "type": { + "type": "schema", + "name": "FileId", + "id": 2 + } + }, + { + "path": "State", + "type": { + "type": "uint8", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "StartLSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "EndLSID", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "Level", + "type": { + "type": "int32", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "CreationTimestamp", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "ObsoletionTimestamp", + "type": { + "type": "int64", + "storage": "fixed", + "nullable": false + } + }, + { + "path": "InvalidationStats", + "type": { + "type": "schema", + "name": "InvalidationStats", + "id": 6 + } + } + ] + } + ] +} \ No newline at end of file diff --git a/test-data/SchemaHashCoverageSchema.json b/test-data/SchemaHashCoverageSchema.json new file mode 100644 index 0000000..37b423b --- /dev/null +++ b/test-data/SchemaHashCoverageSchema.json @@ -0,0 +1,171 @@ +{ + "name": "Microsoft.Azure.Cosmos.Serialization.HybridRow.Tests.Unit.SchemaHashTest", + "schemas": [ + { + "version": "v1", + "comment": "Some UDT definition", + "name": "UDT", + "id": 1, + "type": "schema", + "properties": [ + { + "path": "item1", + "type": { + "length": 0, + "storage": "fixed", + "type": "int32", + "nullable": false + } + }, + { + "path": "item2", + "type": { + "length": 10, + "storage": "variable", + "type": "utf8" + } + } + ], + "partitionkeys": [], + "primarykeys": [] + }, + { + "version": "v1", + "comment": "Some table definition", + "name": "Table", + "id": 2, + "options": { + "disallowUnschematized": true, + "enablePropertyLevelTimestamp": true + }, + "type": "schema", + "properties": [ + { + "path": "fixed", + "type": { + "length": 0, + "storage": "fixed", + "apitype": "myfixed", + "type": "int32" + } + }, + { + "path": "array", + "type": { + "items": { + "length": 0, + "storage": "sparse", + "type": "int8" + }, + "immutable": true, + "type": "array" + } + }, + { + "path": "obj", + "type": { + "properties": [ + { + "path": "nested", + "type": { + "length": 0, + "storage": "sparse", + "type": "int32" + } + } + ], + "immutable": false, + "type": "object" + } + }, + { + "path": "map", + "type": { + "keys": { + "length": 0, + "storage": "sparse", + "type": "int8" + }, + "values": { + "length": 0, + "storage": "sparse", + "type": "int8" + }, + "immutable": false, + "type": "map" + } + }, + { + "path": "set", + "type": { + "items": { + "length": 0, + "storage": "sparse", + "type": "int8" + }, + "immutable": false, + "type": "set" + } + }, + { + "path": "tagged", + "type": { + "items": [ + { + "length": 0, + "storage": "sparse", + "type": "int32" + } + ], + "immutable": false, + "type": "tagged" + } + }, + { + "path": "tuple", + "type": { + "items": [ + { + "length": 0, + "storage": "sparse", + "type": "int32" + }, + { + "length": 0, + "storage": "sparse", + "type": "float32" + } + ], + "immutable": false, + "type": "tuple" + } + }, + { + "path": "udt", + "type": { + "name": "UDT", + "id": 1, + "immutable": false, + "type": "schema" + } + } + ], + "partitionkeys": [ + { + "path": "fixed" + } + ], + "primarykeys": [ + { + "path": "fixed", + "direction": "asc" + } + ], + "statickeys": [ + { + "path": "fixed" + } + ] + } + ] +} diff --git a/test-data/TagSchema.json b/test-data/TagSchema.json new file mode 100644 index 0000000..fcc1b07 --- /dev/null +++ b/test-data/TagSchema.json @@ -0,0 +1,28 @@ +// Tag demo schema that utilizes typed arrays. +{ + "schemas": [ + { "name": "Tagged", "id": 1, "type": "schema", + "properties": [ + { "path": "title", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "tags", "type": { "type": "array", + "items": { "type": "utf8", "nullable": false } } }, + { "path": "options", "type": { "type": "array", + "items": { "type": "int32", "nullable": true } } }, + { "path": "ratings", "type": { "type": "array", + "items": { "type": "array", "nullable": false, "items": { "type": "float64", "nullable": false } } } }, + { "path": "similars", "type": { "type": "array", + "items": { "type": "schema", "name": "SimilarMatch", "nullable": false } } }, + { "path": "priority", "type": { "type": "array", + "items": { "type": "tuple", "nullable": false, + "items": [ + { "type": "utf8", "nullable": false }, + { "type": "int64", "nullable": false } + ]}}} + ]}, + { "name": "SimilarMatch", "id": 2, "type": "schema", + "properties": [ + { "path": "thumbprint", "type": { "type": "utf8", "storage": "fixed", "length": 18 } }, + { "path": "score", "type": { "type": "float64", "storage": "fixed" } } + ]} + ] +} \ No newline at end of file diff --git a/test-data/TaggedApiSchema.json b/test-data/TaggedApiSchema.json new file mode 100644 index 0000000..0bafcf1 --- /dev/null +++ b/test-data/TaggedApiSchema.json @@ -0,0 +1,28 @@ +// Tagged demo schema that utilizes tagged types. +{ + "schemas": [ + { + "name": "TaggedApi", + "id": 1, + "type": "schema", + "properties": [ + { + "path": "tag1", + "type": { + "type": "tagged", + "immutable": true, + "items": [{ "type": "utf8", "nullable": false }] + } + }, + { + "path": "tag2", + "type": { + "type": "tagged", + "immutable": false, + "items": [{ "type": "int32", "nullable": false }, { "type": "int64", "nullable": false }] + } + } + ] + } + ] +} diff --git a/test-data/TodoSchema.json b/test-data/TodoSchema.json new file mode 100644 index 0000000..cb91662 --- /dev/null +++ b/test-data/TodoSchema.json @@ -0,0 +1,75 @@ +// Todo demo schema that utilizes typed sets. +{ + "schemas": [ + { + "name": "Todo", + "id": 1, + "type": "schema", + "properties": [ + { "path": "attendees", "type": { "type": "set", "items": { "type": "utf8", "nullable": false } } }, + { "path": "projects", "type": { "type": "set", "items": { "type": "guid", "nullable": false } } }, + { "path": "checkboxes", "type": { "type": "set", "items": { "type": "bool", "nullable": false } } }, + { + "path": "prices", + "type": { + "type": "set", + "items": { + "type": "set", + "immutable": true, + "nullable": false, + "items": { "type": "float32", "nullable": false } + } + } + }, + { + "path": "nested", + "type": { + "type": "set", + "items": { + "type": "set", + "immutable": true, + "nullable": false, + "items": + { + "type": "set", + "immutable": true, + "nullable": false, + "items": { + "type": "int32", + "nullable": false + } + } + } + } + }, + { + "path": "shopping", + "type": { "type": "set", "items": { "type": "schema", "name": "ShoppingItem", "nullable": false } } + }, + { + "path": "work", + "type": { + "type": "set", + "items": { + "type": "tuple", + "nullable": false, + "items": [ + { "type": "bool", "nullable": false }, + { "type": "varuint", "nullable": false } + ] + } + } + } + ] + }, + { + "name": "ShoppingItem", + "id": 2, + "type": "schema", + "properties": [ + { "path": "label", "type": { "type": "utf8", "storage": "variable" } }, + { "path": "count", "type": { "type": "uint8", "storage": "fixed" } } + ] + } + ] +}