Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.10.0')
testImplementation('org.mockito:mockito-core:5.4.0')
testImplementation('org.mockito:mockito-junit-jupiter:5.4.0')
testImplementation('nl.jqno.equalsverifier:equalsverifier:3.15')
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.10.0')

testImplementation 'org.assertj:assertj-core:3.24.2'
Expand Down
103 changes: 103 additions & 0 deletions lib/src/main/java/io/cloudquery/scalar/UUID.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package io.cloudquery.scalar;

import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.ArrowType.FixedSizeBinary;

import java.nio.ByteBuffer;
import java.util.Objects;

public class UUID implements Scalar {
private static final int BYTE_WIDTH = 16;
private static final FixedSizeBinary dt = new FixedSizeBinary(BYTE_WIDTH);

private java.util.UUID value;

public UUID() {
}

public UUID(Object value) throws ValidationException {
this.set(value);
}

@Override
public boolean isValid() {
return this.value != null;
}

@Override
public ArrowType dataType() {
return dt;
}

@Override
public void set(Object value) throws ValidationException {
if (value == null) {
this.value = null;
return;
}

if (value instanceof Scalar scalar) {
if (!scalar.isValid()) {
this.value = null;
return;
}

if (scalar instanceof UUID uuid) {
this.value = uuid.value;
return;
}

this.set(scalar.get());
return;
}

if (value instanceof java.util.UUID uuid) {
this.value = uuid;
return;
}

if (value instanceof CharSequence sequence) {
this.value = java.util.UUID.fromString(sequence.toString());
return;
}

if (value instanceof byte[] b) {
if (b.length != BYTE_WIDTH) {
throw new ValidationException("[]byte must be " + BYTE_WIDTH + " bytes to convert to UUID", this.dataType(), b);
}
ByteBuffer byteBuffer = ByteBuffer.wrap(b);
long mostSig = byteBuffer.getLong();
long leastSig = byteBuffer.getLong();
this.value = new java.util.UUID(mostSig, leastSig);
return;
}

throw new ValidationException(ValidationException.NO_CONVERSION_AVAILABLE, this.dataType(), value);
}

@Override
public Object get() {
return this.value;
}

@Override
public final boolean equals(Object other) {
if (other instanceof UUID o) {
return this.value == o.value || Objects.equals(this.value, o.value);
}
return false;
}

@Override
public final int hashCode() {
return Objects.hash(value);
}

@Override
public String toString() {
if (this.value != null) {
return this.value.toString();
}
return NULL_VALUE_STRING;
}
}
162 changes: 162 additions & 0 deletions lib/src/test/java/io/cloudquery/scalar/UUIDTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package io.cloudquery.scalar;

import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class UUIDTest {
private static final byte[] COMPLETE_BYTE_SEQUENCE = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
private static final byte[] INCOMPLETE_BYTE_SEQUENCE = {1, 2, 3, 4};

@Test
public void testNew() {
assertDoesNotThrow(() -> {
new UUID();
});
}

@Test
public void testNewWithValidParam() {
assertDoesNotThrow(() -> {
new UUID("123e4567-e89b-12d3-a456-426614174000");
new UUID(java.util.UUID.randomUUID());
new UUID(COMPLETE_BYTE_SEQUENCE);

Scalar s = new UUID(java.util.UUID.randomUUID());
new UUID(s);
}
);
}

@Test
public void testNewWithInvalidParam() {
assertThrows(ValidationException.class, () -> {
new UUID(false);
});

assertThrows(ValidationException.class, () -> {
new UUID(INCOMPLETE_BYTE_SEQUENCE);
});
}

@Test
public void testToString() {
UUID uuid = new UUID();
assertEquals(Scalar.NULL_VALUE_STRING, uuid.toString());

java.util.UUID u = java.util.UUID.randomUUID();
assertDoesNotThrow(() -> {
uuid.set(u);
});
assertEquals(u.toString(), uuid.toString());

assertDoesNotThrow(() -> {
uuid.set(u.toString());
});
assertEquals(u.toString(), uuid.toString());
}

@Test
public void testDataType() {
UUID uuid = new UUID();
assertEquals(new ArrowType.FixedSizeBinary(16), uuid.dataType());
}

@Test
public void testIsValid() {
UUID uuid = new UUID();
assertFalse(uuid.isValid());

assertDoesNotThrow(() -> {
uuid.set(java.util.UUID.randomUUID());
});
assertTrue(uuid.isValid());
}

@Test
public void testSet() {
UUID uuid = new UUID();
assertDoesNotThrow(() -> {
uuid.set("123e4567-e89b-12d3-a456-426614174000");
uuid.set(java.util.UUID.randomUUID());
uuid.set(COMPLETE_BYTE_SEQUENCE);

Scalar s = new UUID(java.util.UUID.randomUUID());
uuid.set(s);
});
}

@Test
public void testSetWithInvalidParam() {
UUID uuid = new UUID();
assertThrows(ValidationException.class, () -> {
uuid.set(false);
});
assertThrows(ValidationException.class, () -> {
uuid.set(INCOMPLETE_BYTE_SEQUENCE);
});
}

@Test
public void testGet() {
UUID uuid = new UUID();
assertFalse(uuid.isValid());
assertNull(uuid.get());

java.util.UUID u = java.util.UUID.randomUUID();
assertDoesNotThrow(() -> {
uuid.set(u);
});
assertTrue(uuid.isValid());
assertEquals(u, uuid.get());
}

@Test
public void testEquals() {
UUID uuid1 = new UUID();
UUID uuid2 = new UUID();

assertEquals(uuid1, uuid2);
assertNotEquals(uuid1, null);
assertNotEquals(uuid1, new Bool());
assertNotEquals(null, uuid1);

assertDoesNotThrow(() -> {
uuid1.set(java.util.UUID.randomUUID());
});
assertNotEquals(uuid1, uuid2);

java.util.UUID u = java.util.UUID.randomUUID();
assertDoesNotThrow(() -> {
uuid1.set(u);
assertEquals(uuid1, new UUID(u));
});
}

@Test
public void testCorrectEndianBehaviour() {
String expectUUID = "00010203-0405-0607-0809-0a0b0c0d0e0f";

UUID uuid = new UUID();
assertDoesNotThrow(() -> {
uuid.set(COMPLETE_BYTE_SEQUENCE);
assertEquals(expectUUID, uuid.toString());
});
}

@Test
public void equalsContractVerification() {
EqualsVerifier.forClass(UUID.class).
suppress(Warning.NONFINAL_FIELDS). // Scalar classes are intentionally mutable
verify();
}
}