diff --git a/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/ValueUtil.java b/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/ValueUtil.java index bc18bec33..9485ad02b 100644 --- a/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/ValueUtil.java +++ b/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/ValueUtil.java @@ -35,74 +35,105 @@ public final class ValueUtil { @SuppressWarnings("rawtypes") private static final Function CONVERT = o -> { if (o instanceof Value) { - return convert(Value.class.cast(o)); + return convert((Value) o); } - return getObject(o); + return getObject(o, VALUE_WRITER); }; private ValueUtil() { } /** - * converter a {@link Value} to Object + * Converts a {@link Value} to Object * * @param value the value - * @return a object converted + * @return an object converted */ public static Object convert(Value value) { + return convert(value, VALUE_WRITER); + } + + /** + * Converts a {@link Value} using a custom {@link ValueWriter}. + * + * @param value the value to be converted + * @param valueWriter the custom ValueWriter to use for conversion + * @return the converted object + */ + public static Object convert(Value value, ValueWriter valueWriter) { Objects.requireNonNull(value, "value is required"); + Objects.requireNonNull(valueWriter, "valueWriter is required"); Object val = value.get(); if (val instanceof Iterable) { - return getObjects(val); + return getObjects(val, valueWriter); } - return getObject(val); + return getObject(val, valueWriter); } - /** - * Converts the {@link Value} to {@link List} + * Converts a {@link Value} to {@link List} * * @param value the value * @return a list object */ - @SuppressWarnings("unchecked") public static List convertToList(Value value) { + return convertToList(value, VALUE_WRITER); + } + + /** + * Converts a {@link Value} to {@link List} using a custom {@link ValueWriter}. + * + * @param value the value + * @param valueWriter the custom ValueWriter to use for conversion + * @return a list object + */ + @SuppressWarnings("unchecked") + public static List convertToList(Value value, ValueWriter valueWriter) { Objects.requireNonNull(value, "value is required"); + Objects.requireNonNull(valueWriter, "valueWriter is required"); Object val = value.get(); if (val instanceof Iterable) { List items = new ArrayList<>(); Iterable.class.cast(val).forEach(items::add); if (items.size() == 1) { Object item = items.get(0); - //check if it is dynamic params + // check if it is dynamic params if (PARAM_CLASS_NAME.equals(item.getClass().getName())) { Object params = Value.class.cast(item).get(); if (params instanceof Iterable) { - return getObjects(Iterable.class.cast(params)); + return getObjects(Iterable.class.cast(params), valueWriter); } else { - return Collections.singletonList(getObject(params)); + return Collections.singletonList(getObject(params, valueWriter)); } } } - return (List) items.stream().map(CONVERT).collect(toList()); - + return (List) items.stream().map(o -> getObject(o, valueWriter)).collect(toList()); } - return Collections.singletonList(getObject(val)); + return Collections.singletonList(getObject(val, valueWriter)); } - @SuppressWarnings("unchecked") - private static List getObjects(Object val) { - return (List) StreamSupport.stream(Iterable.class.cast(val).spliterator(), false) - .map(CONVERT).collect(toList()); + @SuppressWarnings({"unchecked", "rawtypes"}) + private static List getObjects(Object val, ValueWriter valueWriter) { + return (List) StreamSupport.stream(((Iterable) val).spliterator(), false) + .map(o -> { + if (o instanceof Value) { + return convert((Value) o, valueWriter); + } + return getObject(o, valueWriter); + }) + .collect(toList()); } - @SuppressWarnings("unchecked") - private static Object getObject(Object val) { + @SuppressWarnings({"unchecked", "rawtypes"}) + private static Object getObject(Object val, ValueWriter valueWriter) { if (val == null) { return null; - } else if (VALUE_WRITER.test(val.getClass())) { - return VALUE_WRITER.write(val); + } else if (val instanceof Value) { + return convert(Value.class.cast(val), valueWriter); + } else if (valueWriter.test(val.getClass())) { + return valueWriter.write(val); } return val; } -} \ No newline at end of file +} + diff --git a/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/UUIDValueReader.java b/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/UUIDValueReader.java new file mode 100644 index 000000000..c0ed28e03 --- /dev/null +++ b/jnosql-communication/jnosql-communication-core/src/main/java/org/eclipse/jnosql/communication/reader/UUIDValueReader.java @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + * + */ +package org.eclipse.jnosql.communication.reader; + +import org.eclipse.jnosql.communication.CommunicationException; +import org.eclipse.jnosql.communication.ValueReader; + +import java.util.UUID; + +public class UUIDValueReader implements ValueReader { + + @SuppressWarnings("unchecked") + @Override + public T read(Class type, Object value) { + if (value instanceof UUID) { + return (T) value; + } + if (value instanceof CharSequence) { + return (T) getUuid(value); + } + return null; + } + + private static UUID getUuid(Object value) { + try { + return UUID.fromString(value.toString()); + } catch (IllegalArgumentException exp) { + throw new CommunicationException("There is an error to convert to UUID, because the value is not UUID format: " + value, exp); + } + } + + @Override + public boolean test(Class type) { + return UUID.class.equals(type); + } +} diff --git a/jnosql-communication/jnosql-communication-core/src/main/resources/META-INF/services/org.eclipse.jnosql.communication.ValueReader b/jnosql-communication/jnosql-communication-core/src/main/resources/META-INF/services/org.eclipse.jnosql.communication.ValueReader index 064ca188e..96da0208d 100644 --- a/jnosql-communication/jnosql-communication-core/src/main/resources/META-INF/services/org.eclipse.jnosql.communication.ValueReader +++ b/jnosql-communication/jnosql-communication-core/src/main/resources/META-INF/services/org.eclipse.jnosql.communication.ValueReader @@ -23,4 +23,5 @@ org.eclipse.jnosql.communication.reader.YearReader org.eclipse.jnosql.communication.reader.ZonedDateTimeReader org.eclipse.jnosql.communication.reader.LocalTimeReader org.eclipse.jnosql.communication.reader.OffsetDateTimeReader -org.eclipse.jnosql.communication.reader.OffsetTimeReader \ No newline at end of file +org.eclipse.jnosql.communication.reader.OffsetTimeReader +org.eclipse.jnosql.communication.reader.UUIDValueReader diff --git a/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/ValueUtilTest.java b/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/ValueUtilTest.java index 13ae551e6..4eed07b87 100644 --- a/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/ValueUtilTest.java +++ b/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/ValueUtilTest.java @@ -74,4 +74,76 @@ void shouldReturnNullWhenValueUtilHasNullValue() { Object result = ValueUtil.convert(Value.ofNull()); Assertions.assertNull(result); } -} \ No newline at end of file + + @Test + void shouldConvertWithCustomWriter() { + ValueWriter customWriter = new ValueWriter<>() { + @Override + public String write(Integer object) { + return "Custom-" + object; + } + + @Override + public boolean test(Class aClass) { + return Integer.class.equals(aClass); + } + }; + + Value value = Value.of(42); + assertEquals("Custom-42", ValueUtil.convert(value, customWriter)); + } + + @Test + void shouldConvertListWithCustomWriter() { + ValueWriter customWriter = new ValueWriter<>() { + @Override + public String write(Integer object) { + return "Custom-" + object; + } + + @Override + public boolean test(Class aClass) { + return Integer.class.equals(aClass); + } + }; + + Value value = Value.of(Arrays.asList(10, 20)); + assertEquals(Arrays.asList("Custom-10", "Custom-20"), ValueUtil.convertToList(value, customWriter)); + } + + @Test + void shouldConvertNestedValueWithCustomWriter() { + ValueWriter customWriter = new ValueWriter<>() { + @Override + public String write(Integer object) { + return "Custom-" + object; + } + + @Override + public boolean test(Class aClass) { + return Integer.class.equals(aClass); + } + }; + + Value value = Value.of(Arrays.asList(Value.of(10), Value.of(20))); + assertEquals(Arrays.asList("Custom-10", "Custom-20"), ValueUtil.convert(value, customWriter)); + } + + @Test + void shouldConvertNestedListWithCustomWriter() { + ValueWriter customWriter = new ValueWriter<>() { + @Override + public String write(Integer object) { + return "Custom-" + object; + } + + @Override + public boolean test(Class aClass) { + return Integer.class.equals(aClass); + } + }; + + Value value = Value.of(Arrays.asList(Value.of(10), Value.of(20))); + assertEquals(Arrays.asList("Custom-10", "Custom-20"), ValueUtil.convertToList(value, customWriter)); + } +} diff --git a/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/UUIDValueReaderTest.java b/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/UUIDValueReaderTest.java new file mode 100644 index 000000000..322312e11 --- /dev/null +++ b/jnosql-communication/jnosql-communication-core/src/test/java/org/eclipse/jnosql/communication/reader/UUIDValueReaderTest.java @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at http://www.opensource.org/licenses/apache2.0.php. + * + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * + * Otavio Santana + * + */ +package org.eclipse.jnosql.communication.reader; + +import org.eclipse.jnosql.communication.CommunicationException; +import org.junit.jupiter.api.Test; + +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; + +class UUIDValueReaderTest { + private final UUIDValueReader valueReader = new UUIDValueReader(); + + @Test + void shouldReadUUIDFromUUIDInstance() { + UUID uuid = UUID.randomUUID(); + UUID result = valueReader.read(UUID.class, uuid); + assertEquals(uuid, result); + } + + @Test + void shouldReadUUIDFromString() { + UUID uuid = UUID.randomUUID(); + UUID result = valueReader.read(UUID.class, uuid.toString()); + assertEquals(uuid, result); + } + + @Test + void shouldReturnNullForInvalidString() { + String invalidUUID = "invalid-uuid"; + assertThrows(CommunicationException.class, () -> valueReader.read(UUID.class, invalidUUID)); + } + + @Test + void shouldReturnNullForUnsupportedType() { + Integer unsupportedValue = 42; + UUID result = valueReader.read(UUID.class, unsupportedValue); + assertNull(result); + } + + @Test + void shouldTestUUIDType() { + assertTrue(valueReader.test(UUID.class)); + } + + @Test + void shouldNotTestNonUUIDType() { + assertFalse(valueReader.test(String.class)); + } +} diff --git a/pom.xml b/pom.xml index 480bd727c..11b7858bd 100644 --- a/pom.xml +++ b/pom.xml @@ -551,7 +551,7 @@ ${apache.pdm.plugin.version} - pmd/pmd-rules.xml + https://raw.githubusercontent.com/eclipse/jnosql/refs/heads/main/pmd/pmd-rules.xml **/org/eclipse/jnosql/query/**/*.java