Code cleanup, especially in Utf8String class which is much improved.

This commit is contained in:
David Noble
2019-09-12 20:55:36 -07:00
parent 76e62cbd99
commit e942e2076c
14 changed files with 996 additions and 977 deletions

View File

@@ -23,7 +23,7 @@ public final class Reference<T> {
}
public T get() {
return value;
return this.value;
}
public void set(T value) {
@@ -41,7 +41,7 @@ public final class Reference<T> {
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
return this.value != null;
}
/**
@@ -66,12 +66,12 @@ public final class Reference<T> {
return false;
}
return Objects.equals(value, ((Reference)other).value);
return Objects.equals(this.value, ((Reference)other).value);
}
@Override
public String toString() {
return value == null ? "null" : value.toString();
return this.value == null ? "null" : this.value.toString();
}
}

View File

@@ -13,10 +13,13 @@ 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 com.google.common.base.Utf8;
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;
@@ -27,6 +30,7 @@ import java.util.Optional;
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;
@@ -40,32 +44,49 @@ import static java.nio.charset.StandardCharsets.UTF_8;
@SuppressWarnings("UnstableApiUsage")
public final class Utf8String implements ByteBufHolder, CharSequence, Comparable<Utf8String> {
public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER, 0);
public static final Utf8String NULL = new Utf8String();
public static final Utf8String EMPTY = new Utf8String(Unpooled.EMPTY_BUFFER);
public static final Utf8String NULL = new Utf8String(null);
private final ByteBuf buffer;
private final int length;
private final Supplier<Integer> codePointCount;
private final Supplier<Integer> utf16CodeUnitCount;
private Utf8String() {
this.buffer = null;
this.length = -1;
}
private Utf8String(@Nullable final ByteBuf buffer) {
private Utf8String(@Nonnull final ByteBuf buffer) {
this(buffer, decodedLength(buffer));
}
if (buffer == null) {
this.buffer = null;
this.codePointCount = Suppliers.memoize(() -> -1);
this.utf16CodeUnitCount = Suppliers.memoize(() -> -1);
return;
}
private Utf8String(@Nonnull final ByteBuf buffer, final int decodedLength) {
checkNotNull(buffer, "expected non-null buffer");
this.buffer = buffer.asReadOnly();
this.length = decodedLength;
if (buffer.writerIndex() == 0) {
this.buffer = Unpooled.EMPTY_BUFFER;
this.codePointCount = Suppliers.memoize(() -> 0);
this.utf16CodeUnitCount = Suppliers.memoize(() -> 0);
return;
}
this.buffer = buffer;
this.codePointCount = Suppliers.memoize(() -> {
final UTF8CodePointCounter counter = new UTF8CodePointCounter();
this.buffer.forEachByte(0, this.buffer.writerIndex(), counter);
return counter.value();
});
this.utf16CodeUnitCount = Suppliers.memoize(() -> {
final UTF16CodeUnitCounter counter = new UTF16CodeUnitCounter();
this.buffer.forEachByte(0, this.buffer.writerIndex(), counter);
return counter.value();
});
}
/**
* {@code true} if the length of this instance is zero
*/
public final boolean isEmpty() {
return this.length == 0;
return this.buffer != null && this.buffer.writerIndex() == 0;
}
/**
@@ -92,10 +113,10 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
* Non-allocating enumeration of each code point in the UTF-8 stream
*/
public final IntStream codePoints() {
if (this.length == 0) {
if (this.buffer == null || this.buffer.writerIndex() == 0) {
return IntStream.empty();
}
return StreamSupport.intStream(new CodePointIterable(this.buffer, this.length), false);
return StreamSupport.intStream(new CodePointIterable(this.buffer, this.codePointCount.get()), false);
}
@@ -130,7 +151,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
if (limit > 0) {
final CodePointIterable iterable = new CodePointIterable(this.buffer, this.length);
final CodePointIterable iterable = new CodePointIterable(this.buffer, this.utf16CodeUnitCount.get());
int index = 0;
for (int codePoint : iterable) {
@@ -182,16 +203,16 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
/**
* Encoded length of this {@link Utf8String}
* <p>
* This is the same value as would be returned by {@link String#getBytes()#length} with no time or space overhead.
* This is the same value as would be returned by {@link String#getBytes()#utf16CodeUnitCount} with no time or space overhead.
*
* @return encoded length of {@link Utf8String}
*/
public final int encodedLength() {
return this.buffer.writerIndex();
return this.buffer == null ? 0 : this.buffer.writerIndex();
}
public final boolean equals(ByteBuf other) {
return this.buffer.equals(other);
return Objects.equal(this.buffer, other);
}
public final boolean equals(String other) {
@@ -202,33 +223,25 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
public final boolean equals(Utf8String other) {
if (other == null) {
return false;
}
if (other == this) {
if (this == other) {
return true;
}
return this.buffer.equals(other.buffer);
if (null == other) {
return false;
}
return Objects.equal(this.buffer, other.buffer);
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false;
}
if (other == this) {
if (this == other) {
return true;
}
if (other instanceof ByteBuf) {
return this.equals((ByteBuf)other);
if (null == other || this.getClass() != other.getClass()) {
return false;
}
if (other instanceof String) {
return this.equals((String)other);
}
if (other instanceof Utf8String) {
return this.equals((Utf8String)other);
}
return false;
Utf8String that = (Utf8String) other;
return this.utf16CodeUnitCount == that.utf16CodeUnitCount && Objects.equal(this.buffer, that.buffer);
}
/**
@@ -247,11 +260,12 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
/**
* Creates a new {@link Utf8String} from a {@link ByteBuf} without UTF-8 character validation
* Creates a new {@link Utf8String} from a {@link ByteBuf} without UTF-8 character validation.
* <p>
* The {@link Utf8String} created retains the {@link ByteBuf}. (No data is transferred.)
* The {@link Utf8String} created retains the {@link ByteBuf} and ensures it is read-only by calling
* {@link ByteBuf#asReadOnly}. No data is transferred.
*
* @param buffer The {@link ByteBuf} to assign to the {@link Utf8String} created.
* @param buffer a {@link ByteBuf} to assign to the {@link Utf8String} created.
* @return a new {@link Utf8String}
*/
@Nonnull
@@ -266,12 +280,13 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
/**
* Returns the length of this character sequence
* Returns the length of this character sequence.
* <p>
* The length is the number of Unicode characters in the sequence.
* The length is the number of UTF-16 code units in the sequence. This is the same value as would be returned by
* {@link Utf8String#toUtf16()#length()} with no time or space overhead.
*/
public final int length() {
return this.length;
return this.utf16CodeUnitCount.get();
}
/**
@@ -285,10 +300,11 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
/**
* Decreases the reference count by {@code 1} and deallocates this object if the reference count reaches at
* {@code 0}.
* Decreases the reference count by {@code 1}.
*
* @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated
* 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() {
@@ -296,11 +312,12 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
/**
* Decreases the reference count by the specified {@code decrement} and deallocates this object if the reference
* count reaches at {@code 0}.
* Decreases the reference count by the specified {@code decrement}
*
* @param decrement
* @return {@code true} if and only if the reference count became {@code 0} and this object has been deallocated
* 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(int decrement) {
@@ -308,7 +325,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
/**
* Returns a new {@link Utf8String} which contains the specified {@code content}
* Returns a new {@link Utf8String} which contains the specified {@code content}.
*
* @param content text of the {@link Utf8String} to be created.
*/
@@ -330,7 +347,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
}
/**
* Duplicates this {@link Utf8String}
* Duplicates this {@link Utf8String}.
* <p>
* This method returns a retained duplicate unlike {@link #duplicate()}.
*
@@ -343,9 +360,8 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
@Override
public CharSequence subSequence(int start, int end) {
checkArgument(start < 0 || end < 0 || start > end || end > this.length, "start: %s, end: %s", start, end);
// TODO: DANOBLE: compute buffer index for start and end character positions and use them in the slice
return new Utf8String(this.buffer.slice(), end - start);
checkArgument(start < 0 || end < 0 || start > end || end > this.length(), "start: %s, end: %s", start, end);
return new Utf8String(this.buffer.slice(start, end));
}
@Override
@@ -394,43 +410,34 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
checkState(count == length, "count: %s, length: %s", count, length);
return new Utf8String(buffer, string.length());
return new Utf8String(buffer);
}
private static int decodedLength(final ByteBuf buffer) {
final CodePointIterable iterable = new CodePointIterable(buffer, -1);
int decodedLength = 0;
for (int ignored : iterable) {
decodedLength++;
}
return decodedLength;
}
private static final class CodePointIterable implements Iterable<Integer>, Iterator<Integer>, Spliterator.OfInt {
private static final class CodePointIterable extends UTF8CodePointGetter implements
Iterable<Integer>, Iterator<Integer>, Spliterator.OfInt {
private static final int CHARACTERISTICS = Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED;
private final ByteBuf buffer;
private final int length;
private int index;
private final int codePointCount;
CodePointIterable(final ByteBuf buffer, final int length) {
private int start, length;
CodePointIterable(final ByteBuf buffer, final int codePointCount) {
this.codePointCount = codePointCount;
this.buffer = buffer;
this.length = length;
this.index = 0;
this.start = 0;
this.length = buffer.writerIndex();
}
@Override
public int characteristics() {
return this.length == -1 ? CHARACTERISTICS : CHARACTERISTICS | Spliterator.SIZED | Spliterator.SUBSIZED;
return this.codePointCount == -1 ? CHARACTERISTICS : CHARACTERISTICS | Spliterator.SIZED | Spliterator.SUBSIZED;
}
@Override
public long estimateSize() {
return this.length < 0 ? Long.MAX_VALUE : this.length;
return this.codePointCount < 0 ? Long.MAX_VALUE : this.codePointCount;
}
@Override
@@ -440,7 +447,7 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
@Override
public boolean hasNext() {
return this.index < this.buffer.capacity();
return this.length > 0;
}
@Override
@@ -456,50 +463,10 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
throw new NoSuchElementException();
}
final int leadingByte = this.buffer.getByte(this.index++) & 0xFF;
this.start = this.buffer.forEachByte(this.start, this.length, this);
this.length -= this.start;
// A 1-byte UTF-8 code point is a special case that covers the 7-bit ASCII character set
if (leadingByte < 0x80) {
return leadingByte;
}
// The initial byte of 2-, 3- and 4-byte UTF-8 code points start with 2, 3, or 4 one bits followed by a 0
// bit
final int codePoint;
if ((leadingByte & 0b1110_0000) == 0b1100_0000) {
// 110xxxxx 10xxxxxx => 0x00000080 - 0x000007FF
codePoint = ((leadingByte & 0b0001_1111) << 6) |
(this.buffer.getByte(this.index++) & 0b0011_1111);
} else if ((leadingByte & 0b1111_0000) == 0b1110_0000) {
// 1110xxxx 10xxxxxx 10xxxxxx => 0x00000800 - 0x0000FFFF
codePoint = ((leadingByte & 0b0000_1111) << 12) |
((this.buffer.getByte(this.index++) & 0b0011_1111) << 6) |
((this.buffer.getByte(this.index++) & 0b0011_1111));
} else if ((leadingByte & 0b1111_1000) == 0b1111_0000) {
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx => 0x00010000 - 0x001FFFFF
codePoint = ((leadingByte & 0b0000_0111) << 18) |
((this.buffer.getByte(this.index++) & 0b0011_1111) << 12) |
((this.buffer.getByte(this.index++) & 0b0011_1111) << 6) |
((this.buffer.getByte(this.index++) & 0b0011_1111));
} else {
// leading byte is improperly encoded and we'll detect that before returning
codePoint = leadingByte;
}
checkState(Character.isDefined(codePoint), "invalid character: %s", codePoint);
return codePoint;
return this.codePoint();
}
@Override
@@ -563,4 +530,204 @@ public final class Utf8String implements ByteBufHolder, CharSequence, Comparable
generator.writeString(value.toString());
}
}
/**
* A {@link ByteProcessor} used by 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 <a href="https://tools.ietf.org/html/rfc3629">RFC 3629: UTF-8, a transformation format of ISO 10646</a>
*/
private static final class UTF16CodeUnitCounter implements ByteProcessor {
private int count = 0;
private int skip = 0;
@Override
public boolean process(byte value) throws Exception {
if (this.skip > 0) {
this.skip--;
} else {
final int leadingByte = value & 0xFF;
if (leadingByte < 0x7F) {
// UTF-8-1 = 0x00-7F
this.skip = 0;
this.count++;
} else if (0xC2 <= leadingByte && leadingByte <= 0xDF) {
// UTF8-8-2 = 0xC2-DF UTF8-tail
this.skip = 1;
this.count++;
} 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.count++;
} 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.count += 2;
} else {
this.skip = 0;
this.count++;
}
}
return true;
}
public int value() {
return this.count;
}
}
/**
* A {@link ByteProcessor} used by to count the number of Unicode code points in a UTF-8 encoded string.
*
* Lead bytes are identified and counted. All other bytes are skipped. Code points are not validated. The
* {@link #process} method counts undefined lead bytes as a single code point to be replaced.
*
* @see <a href="https://tools.ietf.org/html/rfc3629">RFC 3629: UTF-8, a transformation format of ISO 10646</a>
*/
private static final class UTF8CodePointCounter implements ByteProcessor {
private int count = 0;
private int skip = 0;
@Override
public boolean process(byte value) {
if (this.skip > 0) {
this.skip--;
} else {
final int leadingByte = value & 0xFF;
if (leadingByte < 0x7F) {
// UTF-8-1 = 0x00-7F
this.skip = 0;
} else if (0xC2 <= leadingByte && leadingByte <= 0xDF) {
// UTF8-8-2 = 0xC2-DF UTF8-tail
this.skip = 1;
} 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;
} 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;
} else {
// Undefined leading byte
this.skip = 0;
}
this.count++;
}
return true;
}
public int value() {
return this.count;
}
}
/**
* A {@link ByteProcessor} used to read a UTF-8 encoded string one Unicode code point at a time.
* <p>
* 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.
* <p>
* Code points are validated. The {@link #process(byte)} method returns the Unicode
* <a href="https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character">Replacement character</a>
* when an undefined code point is encountered.
*
* @see <a href="https://tools.ietf.org/html/rfc3629">RFC 3629: UTF-8, a transformation format of ISO 10646</a>
*/
private static class UTF8CodePointGetter implements ByteProcessor {
private static final int REPLACEMENT_CHARACTER = 0xFFFD;
private int codePoint = 0;
private int shift = -1;
/**
* Gets the next code unit in a UTF-8 code point sequence.
*
* @param value the next code unit in a UTF-8
*
* @return {@code true} if additional code units 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(byte value) {
switch (this.shift) {
default: {
// Next unit of code point sequence
this.codePoint |= (value & 0xFF << this.shift);
this.shift -= Byte.SIZE;
return true;
}
case 0: {
// End of code point sequence
this.codePoint |= value & 0xFF;
this.shift = -1;
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) {
// 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 = 3 * 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;
}
}
}

View File

@@ -17,274 +17,278 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public final class UtfAnyString implements CharSequence, Comparable<UtfAnyString> {
private static final UtfAnyString EMPTY = new UtfAnyString("");
private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381);
public static final UtfAnyString EMPTY = new UtfAnyString("");
public static final UtfAnyString NULL = new UtfAnyString();
private CharSequence buffer;
private static final int NULL_HASHCODE = reduceHashCode(5_381, 5_381);
public UtfAnyString(final String string) {
this.buffer = string;
}
private CharSequence buffer;
public UtfAnyString(final Utf8String utf8String) {
this.buffer = utf8String;
}
public UtfAnyString(final String value) {
this.buffer = value;
}
private UtfAnyString(final CharSequence sequence) {
this.buffer = sequence;
}
public UtfAnyString(final Utf8String value) {
this.buffer = value;
}
/**
* {@code true} if the {@link UtfAnyString} is empty
*/
public boolean isEmpty() {
return this.buffer != null && this.buffer.length() == 0;
}
private UtfAnyString() {
}
/**
* {@code true} if the {@link UtfAnyString} is {@code null}
*/
public boolean isNull() {
return null == this.buffer;
}
private UtfAnyString(final CharSequence sequence) {
this.buffer = sequence;
}
public boolean isUtf16() {
return this.buffer instanceof String;
}
/**
* {@code true} if the {@link UtfAnyString} is empty
*/
public boolean isEmpty() {
return this.buffer != null && this.buffer.length() == 0;
}
public boolean isUtf8() {
return this.buffer instanceof Utf8String;
}
/**
* {@code true} if the {@link UtfAnyString} is {@code null}
*/
public boolean isNull() {
return null == this.buffer;
}
/**
* Returns the {@code char} value at the specified {@code index}
* <p>
* 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 boolean isUtf16() {
return this.buffer instanceof String;
}
public int compareTo(@Nonnull final String other) {
public boolean isUtf8() {
return this.buffer instanceof Utf8String;
}
checkNotNull(other);
/**
* Returns the {@code char} value at the specified {@code index}
* <p>
* 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);
}
if (other == this.buffer) {
return 0;
}
public int compareTo(@Nonnull final String other) {
if (this.buffer == null) {
return -1;
}
checkNotNull(other, "expected non-null other");
return this.buffer instanceof String
? ((String) this.buffer).compareTo(other)
: ((Utf8String) this.buffer).compareTo(other);
}
if (other == this.buffer) {
return 0;
}
public int compareTo(@Nonnull final Utf8String other) {
if (this.buffer == null) {
return -1;
}
checkNotNull(other);
return this.buffer instanceof String
? ((String) this.buffer).compareTo(other)
: ((Utf8String) this.buffer).compareTo(other);
}
if (other == this.buffer) {
return 0;
}
public int compareTo(@Nonnull final Utf8String other) {
if (this.buffer == null) {
return -1;
}
checkNotNull(other, "expected non-null other");
return this.buffer instanceof String
? -other.compareTo((String) this.buffer)
: ((Utf8String) this.buffer).compareTo(other);
}
if (other == this.buffer) {
return 0;
}
@Override
public int compareTo(@Nonnull final UtfAnyString other) {
if (this.buffer == null) {
return -1;
}
checkNotNull(other);
return this.buffer instanceof String
? -other.compareTo((String) this.buffer)
: ((Utf8String) this.buffer).compareTo(other);
}
if (other.buffer == this.buffer) {
return 0;
}
@Override
public int compareTo(@Nonnull final UtfAnyString other) {
if (other.buffer == null) {
return 1;
}
checkNotNull(other, "expected non-null other");
if (this.buffer == null) {
return -1;
}
if (other.buffer == this.buffer) {
return 0;
}
if (this.buffer instanceof String) {
return other.buffer instanceof String
? ((String) this.buffer).compareTo((String) other.buffer)
: -((Utf8String) other.buffer).compareTo((String) this.buffer);
}
if (other.buffer == null) {
return 1;
}
return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer);
}
if (this.buffer == null) {
return -1;
}
public static UtfAnyString empty() {
return EMPTY;
}
if (this.buffer instanceof String) {
return other.buffer instanceof String
? ((String) this.buffer).compareTo((String) other.buffer)
: -((Utf8String) other.buffer).compareTo((String) this.buffer);
}
@Override
public boolean equals(final Object other) {
return ((Utf8String) this.buffer).compareTo((Utf8String) other.buffer);
}
if (other == null) {
return false;
}
public static UtfAnyString empty() {
return EMPTY;
}
if (other instanceof String) {
return this.equals((String) other);
}
@Override
public boolean equals(final Object other) {
if (other instanceof Utf8String) {
return this.equals((Utf8String) other);
}
if (other == null) {
return false;
}
if (other instanceof UtfAnyString) {
return this.equals((UtfAnyString) other);
}
if (other instanceof String) {
return this.equals((String) other);
}
return false;
}
if (other instanceof Utf8String) {
return this.equals((Utf8String) other);
}
public boolean equals(final String other) {
if (other instanceof UtfAnyString) {
return this.equals((UtfAnyString) other);
}
if (null == this.buffer) {
return null == other;
}
return false;
}
if (this.buffer instanceof String) {
return other.contentEquals(this.buffer); // skips the type check that String.equals performs
}
public boolean equals(final String other) {
return ((Utf8String) this.buffer).equals(other);
}
if (null == this.buffer) {
return null == other;
}
public boolean equals(final Utf8String other) {
if (this.buffer instanceof String) {
return other.contentEquals(this.buffer); // skips the type check that String.equals performs
}
if (null == other) {
return null == this.buffer;
}
return ((Utf8String) this.buffer).equals(other);
}
return other.equals(this.buffer);
}
public boolean equals(final Utf8String other) {
public boolean equals(final UtfAnyString other) {
if (null == other) {
return null == this.buffer;
}
if (null == other) {
return false;
}
return other.equals(this.buffer);
}
if (null == this.buffer) {
return null == other.buffer;
}
public boolean equals(final UtfAnyString other) {
return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer);
}
if (null == other) {
return false;
}
@Override
public int hashCode() {
if (null == this.buffer) {
return null == other.buffer;
}
final long[] hash = { 5_381, 5_381 };
return this.buffer instanceof String ? other.buffer.equals(this.buffer) : this.buffer.equals(other.buffer);
}
if (this.buffer == null) {
return NULL_HASHCODE;
}
@Override
public int hashCode() {
if (this.buffer instanceof String) {
final long[] hash = { 5_381, 5_381 };
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;
});
if (this.buffer == null) {
return NULL_HASHCODE;
}
return reduceHashCode(hash[0], hash[1]);
}
if (this.buffer instanceof String) {
return this.buffer.hashCode();
}
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;
});
/**
* 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();
}
return reduceHashCode(hash[0], hash[1]);
}
/**
* Returns a {@code CharSequence} that is a subsequence of this sequence
* <p>
* 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);
}
return this.buffer.hashCode();
}
@Override
@Nonnull
public String toString() {
return String.valueOf(this.buffer);
}
/**
* 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();
}
public String toUtf16() {
if (null == this.buffer) {
return null;
}
return this.buffer instanceof String ? (String) this.buffer : this.buffer.toString();
}
/**
* Returns a {@code CharSequence} that is a subsequence of this sequence
* <p>
* 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);
}
public Utf8String toUtf8() {
if (null == this.buffer) {
return null;
}
return this.buffer instanceof String ? transcodeUtf16((String) this.buffer) : (Utf8String) this.buffer;
}
@Override
@Nonnull
public String toString() {
return String.valueOf(this.buffer);
}
private static int reduceHashCode(final long h1, final long h2) {
return Long.valueOf(h1 + (h2 * 1_566_083_941L)).intValue();
}
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();
}
}

View File

@@ -16,7 +16,7 @@ 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<byte[]> {
public final class LayoutBinary extends LayoutTypePrimitive<ByteBuf> {
// implements
// LayoutListWritable<Byte>,
// LayoutListReadable<Byte>,
@@ -41,7 +41,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
@Nonnull final RowBuffer buffer,
@Nonnull final RowCursor scope,
@Nonnull final LayoutColumn column,
@Nonnull final Out<byte[]> value) {
@Nonnull final Out<ByteBuf> value) {
checkNotNull(buffer, "expected non-null buffer");
checkNotNull(scope, "expected non-null scope");
@@ -56,14 +56,14 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
return Result.NOT_FOUND;
}
value.set(ByteBufUtil.getBytes(buffer.readFixedBinary(scope.start() + column.offset(), column.size())));
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<byte[]> value) {
@Nonnull final RowBuffer buffer, @Nonnull final RowCursor edit, @Nonnull final Out<ByteBuf> value) {
checkNotNull(buffer, "expected non-null buffer");
checkNotNull(edit, "expected non-null edit");
@@ -76,7 +76,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
return result;
}
value.set(ByteBufUtil.getBytes(buffer.readSparseBinary(edit)));
value.set(buffer.readSparseBinary(edit));
return Result.SUCCESS;
}
@@ -86,7 +86,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
@Nonnull RowBuffer buffer,
@Nonnull RowCursor scope,
@Nonnull LayoutColumn column,
@Nonnull Out<byte[]> value) {
@Nonnull Out<ByteBuf> value) {
checkNotNull(buffer, "expected non-null buffer");
checkNotNull(scope, "expected non-null scope");
@@ -101,7 +101,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
}
final int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset());
value.set(ByteBufUtil.getBytes(buffer.readVariableBinary(valueOffset)));
value.set(buffer.readVariableBinary(valueOffset));
return Result.SUCCESS;
}
@@ -112,7 +112,7 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
@Nonnull RowBuffer buffer,
@Nonnull RowCursor scope,
@Nonnull LayoutColumn column,
@Nonnull byte[] value) {
@Nonnull ByteBuf value) {
checkNotNull(buffer, "expected non-null buffer");
checkNotNull(scope, "expected non-null scope");
@@ -121,23 +121,21 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
checkArgument(scope.scopeType() instanceof LayoutUDT);
checkArgument(column.size() >= 0);
checkArgument(value.length == column.size());
if (scope.immutable()) {
return Result.INSUFFICIENT_PERMISSIONS;
}
final ByteBuf valueBuffer = Unpooled.wrappedBuffer(value).asReadOnly();
final int valueOffset = scope.start() + column.offset();
buffer.setBit(scope.start(), column.nullBit());
buffer.writeFixedBinary(valueOffset, valueBuffer, column.size());
buffer.writeFixedBinary(valueOffset, value, column.size());
return Result.SUCCESS;
}
@Override
@Nonnull
public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull byte[] value) {
public Result writeSparse(@Nonnull RowBuffer buffer, @Nonnull RowCursor edit, @Nonnull ByteBuf value) {
return this.writeSparse(buffer, edit, value, UpdateOptions.UPSERT);
}
@@ -146,16 +144,21 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
public Result writeSparse(
@Nonnull RowBuffer buffer,
@Nonnull RowCursor edit,
@Nonnull byte[] value,
@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, Unpooled.wrappedBuffer(value).asReadOnly(), options);
buffer.writeSparseBinary(edit, value, options);
return Result.SUCCESS;
}
@@ -165,7 +168,12 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
@Nonnull RowBuffer buffer,
@Nonnull RowCursor scope,
@Nonnull LayoutColumn column,
@Nonnull byte[] value) {
@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);
@@ -173,16 +181,15 @@ public final class LayoutBinary extends LayoutTypePrimitive<byte[]> {
return Result.INSUFFICIENT_PERMISSIONS;
}
if ((column.size() > 0) && (value.length > column.size())) {
if ((column.size() > 0) && (value.readableBytes() > column.size())) {
return Result.TOO_BIG;
}
final boolean exists = buffer.readBit(scope.start(), column.nullBit());
final ByteBuf valueBuffer = Unpooled.wrappedBuffer(value).asReadOnly();
final int valueOffset = buffer.computeVariableValueOffset(scope.layout(), scope.start(), column.offset());
final Out<Integer> shift = new Out<>();
buffer.writeVariableBinary(valueOffset, valueBuffer, exists, shift);
buffer.writeVariableBinary(valueOffset, value, exists, shift);
buffer.setBit(scope.start(), column.nullBit());
scope.metaOffset(scope.metaOffset() + shift.get());
scope.valueOffset(scope.valueOffset() + shift.get());

View File

@@ -50,7 +50,7 @@ public final class LayoutTypedTuple extends LayoutIndexedScope {
@Nonnull final RowBuffer buffer, final int offset, @Nonnull final Out<Integer> lengthInBytes) {
checkNotNull(buffer, "expected non-null buffer");
lengthInBytes
checkNotNull(lengthInBytes, "expected non-null lengthInBytes");
checkArgument(offset >= 0, "expected non-negative offset, not %s", offset);
final int numTypeArgs = (int) buffer.readVariableUInt(offset, lengthInBytes);

View File

@@ -15,7 +15,7 @@ import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class LayoutUniqueScope extends LayoutIndexedScope {
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);

View File

@@ -14,7 +14,8 @@ 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<String> implements LayoutUtf8Readable, LayoutUtf8Writable {
public final class LayoutUtf8 extends LayoutTypePrimitive<String>
implements LayoutUtf8Readable, LayoutUtf8Writable {
public LayoutUtf8() {
super(LayoutCode.UTF_8, 0);

View File

@@ -15,199 +15,199 @@ 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 <paramref name="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;
/**
* Computes the logical hash for a logical schema.
*
* @param namespace The namespace within which <paramref name="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);
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.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.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.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);
}
}
if (schema.properties() != null) {
for (Property p : schema.properties()) {
hash = SchemaHash.computeHash(namespace, p, hash);
}
}
return hash;
}
return hash;
}
private static HashCode128 computeHash(Namespace namespace, SchemaOptions options, HashCode128 seed) {
private static HashCode128 computeHash(Namespace namespace, SchemaOptions options, HashCode128 seed) {
HashCode128 hash = 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);
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;
}
return hash;
}
private static HashCode128 computeHash(Namespace ns, Property p, HashCode128 seed) {
private static HashCode128 computeHash(Namespace ns, Property p, HashCode128 seed) {
HashCode128 hash = seed;
HashCode128 hash = seed;
hash = Murmur3Hash.Hash128(p.path(), hash);
hash = SchemaHash.computeHash(ns, p.propertyType(), hash);
hash = Murmur3Hash.Hash128(p.path(), hash);
hash = SchemaHash.computeHash(ns, p.propertyType(), hash);
return hash;
}
return hash;
}
private static HashCode128 computeHash(Namespace namespace, PropertyType p, HashCode128 seed) {
private static HashCode128 computeHash(Namespace namespace, PropertyType p, HashCode128 seed) {
HashCode128 hash = seed;
HashCode128 hash = seed;
hash = Murmur3Hash.Hash128(p.type().value(), hash);
hash = Murmur3Hash.Hash128(p.nullable(), hash);
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.apiType() != null) {
hash = Murmur3Hash.Hash128(p.apiType(), hash);
}
if (p instanceof PrimitivePropertyType) {
if (p instanceof PrimitivePropertyType) {
PrimitivePropertyType pp = (PrimitivePropertyType) p;
PrimitivePropertyType pp = (PrimitivePropertyType) p;
hash = Murmur3Hash.Hash128(pp.storage().value(), hash);
hash = Murmur3Hash.Hash128(pp.length(), hash);
hash = Murmur3Hash.Hash128(pp.storage().value(), hash);
hash = Murmur3Hash.Hash128(pp.length(), hash);
return hash;
}
return hash;
}
checkState(p instanceof ScopePropertyType);
ScopePropertyType pp = (ScopePropertyType) p;
hash = Murmur3Hash.Hash128(pp.immutable(), 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 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 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) {
if (p instanceof MapPropertyType) {
MapPropertyType spp = (MapPropertyType) p;
MapPropertyType spp = (MapPropertyType) p;
if (spp.keys() != null) {
hash = SchemaHash.computeHash(namespace, spp.keys(), hash);
}
if (spp.keys() != null) {
hash = SchemaHash.computeHash(namespace, spp.keys(), hash);
}
if (spp.values() != null) {
hash = SchemaHash.computeHash(namespace, spp.values(), hash);
}
if (spp.values() != null) {
hash = SchemaHash.computeHash(namespace, spp.values(), hash);
}
return hash;
}
return hash;
}
if (p instanceof SetPropertyType) {
if (p instanceof SetPropertyType) {
SetPropertyType spp = (SetPropertyType) p;
SetPropertyType spp = (SetPropertyType) p;
if (spp.items() != null) {
hash = SchemaHash.computeHash(namespace, spp.items(), hash);
}
if (spp.items() != null) {
hash = SchemaHash.computeHash(namespace, spp.items(), hash);
}
return hash;
}
return hash;
}
if (p instanceof TaggedPropertyType) {
if (p instanceof TaggedPropertyType) {
TaggedPropertyType spp = (TaggedPropertyType) p;
TaggedPropertyType spp = (TaggedPropertyType) p;
if (spp.items() != null) {
for (PropertyType pt : spp.items()) {
hash = SchemaHash.computeHash(namespace, pt, hash);
}
}
if (spp.items() != null) {
for (PropertyType pt : spp.items()) {
hash = SchemaHash.computeHash(namespace, pt, hash);
}
}
return hash;
}
return hash;
}
if (p instanceof TuplePropertyType) {
if (p instanceof TuplePropertyType) {
TuplePropertyType spp = (TuplePropertyType) p;
TuplePropertyType spp = (TuplePropertyType) p;
if (spp.items() != null) {
for (PropertyType pt : spp.items()) {
hash = SchemaHash.computeHash(namespace, pt, hash);
}
}
if (spp.items() != null) {
for (PropertyType pt : spp.items()) {
hash = SchemaHash.computeHash(namespace, pt, hash);
}
}
return hash;
}
return hash;
}
if (p instanceof UdtPropertyType) {
if (p instanceof UdtPropertyType) {
Stream<Schema> schemaStream = namespace.schemas().stream();
UdtPropertyType spp = (UdtPropertyType) p;
Optional<Schema> udtSchema;
Stream<Schema> schemaStream = namespace.schemas().stream();
UdtPropertyType spp = (UdtPropertyType) p;
Optional<Schema> 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()));
}
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);
}
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()));
}
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, 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 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);
}
private static HashCode128 computeHash(Namespace ns, StaticKey key, HashCode128 seed) {
return key == null ? seed : Murmur3Hash.Hash128(key.path(), seed);
}
}

View File

@@ -5,7 +5,7 @@ package tangible;
public final class StringHelper {
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'IndexOfAny' (1 parameter version).
// This method replaces the .NET string method 'IndexOfAny' (1 parameter version).
//------------------------------------------------------------------------------------
public static int indexOfAny(String string, char[] anyOf) {
int lowestIndex = -1;
@@ -26,7 +26,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'IndexOfAny' (2 parameter version).
// This method replaces the .NET string method 'IndexOfAny' (2 parameter version).
//------------------------------------------------------------------------------------
public static int indexOfAny(String string, char[] anyOf, int startIndex) {
int indexInSubstring = indexOfAny(string.substring(startIndex), anyOf);
@@ -38,7 +38,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'IndexOfAny' (3 parameter version).
// This method replaces the .NET string method 'IndexOfAny' (3 parameter version).
//------------------------------------------------------------------------------------
public static int indexOfAny(String string, char[] anyOf, int startIndex, int count) {
int endIndex = startIndex + count;
@@ -51,14 +51,14 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'IsNullOrEmpty'.
// This method replaces the .NET static string method 'IsNullOrEmpty'.
//------------------------------------------------------------------------------------
public static boolean isNullOrEmpty(String string) {
return string == null || string.length() == 0;
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'IsNullOrWhiteSpace'.
// This method replaces the .NET static string method 'IsNullOrWhiteSpace'.
//------------------------------------------------------------------------------------
public static boolean isNullOrWhiteSpace(String string) {
if (string == null) {
@@ -75,7 +75,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'Join' (2 parameter version).
// This method replaces the .NET static string method 'Join' (2 parameter version).
//------------------------------------------------------------------------------------
public static String join(String separator, String[] stringArray) {
if (stringArray == null) {
@@ -86,7 +86,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET static string method 'Join' (4 parameter version).
// This method replaces the .NET static string method 'Join' (4 parameter version).
//------------------------------------------------------------------------------------
public static String join(String separator, String[] stringArray, int startIndex, int count) {
String result = "";
@@ -109,7 +109,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOf' (char version).
// This method replaces the .NET string method 'LastIndexOf' (char version).
//------------------------------------------------------------------------------------
public static int lastIndexOf(String string, char value, int startIndex, int count) {
int leftMost = startIndex + 1 - count;
@@ -124,7 +124,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOf' (string version).
// This method replaces the .NET string method 'LastIndexOf' (string version).
//------------------------------------------------------------------------------------
public static int lastIndexOf(String string, String value, int startIndex, int count) {
int leftMost = startIndex + 1 - count;
@@ -139,7 +139,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOfAny' (1 parameter version).
// This method replaces the .NET string method 'LastIndexOfAny' (1 parameter version).
//------------------------------------------------------------------------------------
public static int lastIndexOfAny(String string, char[] anyOf) {
int highestIndex = -1;
@@ -158,7 +158,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOfAny' (2 parameter version).
// This method replaces the .NET string method 'LastIndexOfAny' (2 parameter version).
//------------------------------------------------------------------------------------
public static int lastIndexOfAny(String string, char[] anyOf, int startIndex) {
String substring = string.substring(0, startIndex + 1);
@@ -171,7 +171,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'LastIndexOfAny' (3 parameter version).
// This method replaces the .NET string method 'LastIndexOfAny' (3 parameter version).
//------------------------------------------------------------------------------------
public static int lastIndexOfAny(String string, char[] anyOf, int startIndex, int count) {
int leftMost = startIndex + 1 - count;
@@ -186,14 +186,14 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadLeft' (1 parameter version).
// This method replaces the .NET string method 'PadLeft' (1 parameter version).
//------------------------------------------------------------------------------------
public static String padLeft(String string, int totalWidth) {
return padLeft(string, totalWidth, ' ');
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadLeft' (2 parameter version).
// This method replaces the .NET string method 'PadLeft' (2 parameter version).
//------------------------------------------------------------------------------------
public static String padLeft(String string, int totalWidth, char paddingChar) {
StringBuilder sb = new StringBuilder();
@@ -207,14 +207,14 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadRight' (1 parameter version).
// This method replaces the .NET string method 'PadRight' (1 parameter version).
//------------------------------------------------------------------------------------
public static String padRight(String string, int totalWidth) {
return padRight(string, totalWidth, ' ');
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'PadRight' (2 parameter version).
// This method replaces the .NET string method 'PadRight' (2 parameter version).
//------------------------------------------------------------------------------------
public static String padRight(String string, int totalWidth, char paddingChar) {
StringBuilder sb = new StringBuilder(string);
@@ -227,21 +227,21 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Remove' (1 parameter version).
// This method replaces the .NET string method 'Remove' (1 parameter version).
//------------------------------------------------------------------------------------
public static String remove(String string, int start) {
return string.substring(0, start);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Remove' (2 parameter version).
// This method replaces the .NET string method 'Remove' (2 parameter version).
//------------------------------------------------------------------------------------
public static String remove(String string, int start, int count) {
return string.substring(0, start) + string.substring(start + count);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string constructor which repeats a character.
// This method replaces the .NET string constructor which repeats a character.
//------------------------------------------------------------------------------------
public static String repeatChar(char charToRepeat, int count) {
String newString = "";
@@ -252,9 +252,9 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method is used for string equality comparisons when the option
// 'Use helper 'stringsEqual' method to handle null strings' is selected
// (The Java String 'equals' method can't be called on a null instance).
// This method is used for string equality comparisons when the option
// 'Use helper 'stringsEqual' method to handle null strings' is selected
// (The Java String 'equals' method can't be called on a null instance).
//------------------------------------------------------------------------------------
public static boolean stringsEqual(String s1, String s2) {
if (s1 == null && s2 == null) {
@@ -265,8 +265,8 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Substring' when 'start' is a method
// call or calculated value to ensure that 'start' is obtained just once.
// This method replaces the .NET string method 'Substring' when 'start' is a method
// call or calculated value to ensure that 'start' is obtained just once.
//------------------------------------------------------------------------------------
public static String substring(String string, int start, int length) {
if (length < 0) {
@@ -277,14 +277,14 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'Trim' when arguments are used.
// This method replaces the .NET string method 'Trim' when arguments are used.
//------------------------------------------------------------------------------------
public static String trim(String string, Character... charsToTrim) {
return trimEnd(trimStart(string, charsToTrim), charsToTrim);
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'TrimEnd'.
// This method replaces the .NET string method 'TrimEnd'.
//------------------------------------------------------------------------------------
public static String trimEnd(String string, Character... charsToTrim) {
if (string == null || charsToTrim == null) {
@@ -316,7 +316,7 @@ public final class StringHelper {
}
//------------------------------------------------------------------------------------
// This method replaces the .NET string method 'TrimStart'.
// This method replaces the .NET string method 'TrimStart'.
//------------------------------------------------------------------------------------
public static String trimStart(String string, Character... charsToTrim) {
if (string == null || charsToTrim == null) {

View File

@@ -80,7 +80,7 @@ public final class JsonModelRowGenerator {
new Reference<RowBuffer>(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,
Result tempVar = RowWriter.writeBuffer(tempReference_row, value, (RowWriter RowWriter writer, TypeArgument typeArg,
HashMap<Utf8String, Object> dict) ->
{
for ((Utf8String propPath,Object propValue) :dict)
@@ -118,7 +118,7 @@ public final class JsonModelRowGenerator {
//ORIGINAL LINE: case bool x:
case
boolean x:
return writer.get().WriteBoolean(path, 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
@@ -155,7 +155,7 @@ public final class JsonModelRowGenerator {
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,
return writer.get().writeScope(path, new TypeArgument(LayoutType.Object), x,
(RowWriter RowWriter writer2, TypeArgument typeArg, HashMap<Utf8String, Object> dict) ->
{
for ((Utf8String propPath,Object propValue) :dict)
@@ -172,7 +172,7 @@ public final class JsonModelRowGenerator {
//ORIGINAL LINE: case List<object> 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<Object> list) ->
return writer.get().writeScope(path, new TypeArgument(LayoutType.Array), x, (RowWriter RowWriter writer2, TypeArgument typeArg, ArrayList<Object> list) ->
{
for (Object elm : list) {
Reference<com.azure.data.cosmos.serialization.hybridrow.io.RowWriter> tempReference_writer2 = new Reference<com.azure.data.cosmos.serialization.hybridrow.io.RowWriter>(writer2);

View File

@@ -16,7 +16,6 @@ public final class AssertThrowsException {
if (input1 == null) {
return "(null)";
}
return Assert.ReplaceNullChars(input1);
}

View File

@@ -10,6 +10,7 @@ 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;
@@ -25,16 +26,18 @@ import java.util.UUID;
// 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
{
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
}
Zip = 00830, Plus4 = 0001
}
}
};
private LayoutResolver customerResolver;
private Namespace customerSchema;
private Layout guestLayout;

View File

@@ -57,7 +57,7 @@ public final class RowWriterUnitTests {
new Reference<RowBuffer>(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,
ResultAssert.IsSuccess(RowWriter.writeBuffer(tempReference_row, null, (RowWriter RowWriter writer,
TypeArgument rootTypeArg, Object ignored) ->
{
ResultAssert.IsSuccess(writer.WriteNull("null"));