diff --git a/api/src/main/java/jakarta/data/Restrict.java b/api/src/main/java/jakarta/data/Restrict.java index faa96602e..debaee3f3 100644 --- a/api/src/main/java/jakarta/data/Restrict.java +++ b/api/src/main/java/jakarta/data/Restrict.java @@ -192,7 +192,8 @@ public static TextRestriction startsWith(String prefix, String field) { * @throws IllegalArgumentException if the same character is supplied for * both wildcard types. */ - private static String toLikeEscaped(char charWildcard, + // TODO I make default package, but it should be private when we make it as Pattern + static String toLikeEscaped(char charWildcard, char stringWildcard, boolean allowPrevious, String literal, diff --git a/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java b/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java new file mode 100644 index 000000000..a92c2c37c --- /dev/null +++ b/api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.Test; + + +class BasicRestrictionRecordTest { + + @Test + void shouldCreateBasicRestrictionWithDefaultNegation() { + BasicRestrictionRecord restriction = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("title"); + soft.assertThat(restriction.isNegated()).isFalse(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(restriction.value()).isEqualTo("Java Guide"); + }); + } + + @Test + void shouldCreateBasicRestrictionWithExplicitNegation() { + BasicRestrictionRecord restriction = new BasicRestrictionRecord<>("title", true, Operator.EQUAL, "Java Guide"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("title"); + soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(restriction.value()).isEqualTo("Java Guide"); + }); + } + + @Test + void shouldCreateBasicRestrictionWithNullValue() { + // Create a restriction with a null value + BasicRestrictionRecord restriction = new BasicRestrictionRecord<>("title", Operator.EQUAL, null); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("title"); + soft.assertThat(restriction.isNegated()).isFalse(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(restriction.value()).isNull(); + }); + } + + @Test + void shouldSupportNegatedRestrictionUsingDefaultConstructor() { + BasicRestrictionRecord restriction = new BasicRestrictionRecord<>("author", Operator.EQUAL, "Unknown"); + BasicRestrictionRecord negatedRestriction = new BasicRestrictionRecord<>(restriction.field(), true, restriction.comparison(), restriction.value()); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(negatedRestriction.field()).isEqualTo("author"); + soft.assertThat(negatedRestriction.isNegated()).isTrue(); + soft.assertThat(negatedRestriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(negatedRestriction.value()).isEqualTo("Unknown"); + }); + } +} diff --git a/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java b/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java new file mode 100644 index 000000000..3b88e18f3 --- /dev/null +++ b/api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data; + + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.Test; + +import java.util.List; + + +class CompositeRestrictionRecordTest { + + + @Test + void shouldCreateCompositeRestrictionWithDefaultNegation() { + Restriction restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide"); + Restriction restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe"); + + CompositeRestrictionRecord composite = new CompositeRestrictionRecord<>( + CompositeRestriction.Type.ALL, + List.of(restriction1, restriction2) + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(composite.type()).isEqualTo(CompositeRestriction.Type.ALL); + soft.assertThat(composite.restrictions()).containsExactly(restriction1, restriction2); + soft.assertThat(composite.isNegated()).isFalse(); + }); + } + + @Test + void shouldCreateCompositeRestrictionWithExplicitNegation() { + Restriction restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide"); + Restriction restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe"); + + CompositeRestrictionRecord composite = new CompositeRestrictionRecord<>( + CompositeRestriction.Type.ANY, + List.of(restriction1, restriction2), + true + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(composite.type()).isEqualTo(CompositeRestriction.Type.ANY); + soft.assertThat(composite.restrictions()).containsExactly(restriction1, restriction2); + soft.assertThat(composite.isNegated()).isTrue(); + }); + } + + @Test + void shouldHandleEmptyRestrictions() { + CompositeRestrictionRecord composite = new CompositeRestrictionRecord<>( + CompositeRestriction.Type.ALL, + List.of() + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(composite.type()).isEqualTo(CompositeRestriction.Type.ALL); + soft.assertThat(composite.restrictions()).isEmpty(); + soft.assertThat(composite.isNegated()).isFalse(); + }); + } + + @Test + void shouldPreserveRestrictionsOrder() { + Restriction restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide"); + Restriction restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe"); + + CompositeRestrictionRecord composite = new CompositeRestrictionRecord<>( + CompositeRestriction.Type.ALL, + List.of(restriction1, restriction2) + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(composite.restrictions().get(0)).isEqualTo(restriction1); + soft.assertThat(composite.restrictions().get(1)).isEqualTo(restriction2); + }); + } + + @Test + void shouldSupportNegationUsingDefaultConstructor() { + // Given multiple restrictions + Restriction restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide"); + Restriction restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe"); + + // When creating a composite restriction and manually setting negation + CompositeRestrictionRecord composite = new CompositeRestrictionRecord<>( + CompositeRestriction.Type.ALL, + List.of(restriction1, restriction2) + ); + CompositeRestrictionRecord negatedComposite = new CompositeRestrictionRecord<>( + composite.type(), + composite.restrictions(), + true + ); + + // Then validate the negated composite restriction + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(negatedComposite.type()).isEqualTo(CompositeRestriction.Type.ALL); + soft.assertThat(negatedComposite.restrictions()).containsExactly(restriction1, restriction2); + soft.assertThat(negatedComposite.isNegated()).isTrue(); + }); + } +} diff --git a/api/src/test/java/jakarta/data/RestrictTest.java b/api/src/test/java/jakarta/data/RestrictTest.java new file mode 100644 index 000000000..63a63c0b0 --- /dev/null +++ b/api/src/test/java/jakarta/data/RestrictTest.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; + +class RestrictTest { + + + @Test + void shouldCreateEqualToRestriction() { + Restriction restriction = Restrict.equalTo("value", "field"); + + assertThat(restriction).isInstanceOf(TextRestrictionRecord.class); + + TextRestrictionRecord basic = (TextRestrictionRecord) restriction; + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(basic.field()).isEqualTo("field"); + soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(basic.value()).isEqualTo("value"); + soft.assertThat(basic.isNegated()).isFalse(); + }); + } + + @Test + void shouldCreateNotEqualToRestriction() { + Restriction restriction = Restrict.notEqualTo("value", "field"); + + assertThat(restriction).isInstanceOf(TextRestrictionRecord.class); + + TextRestrictionRecord basic = (TextRestrictionRecord) restriction; + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(basic.field()).isEqualTo("field"); + soft.assertThat(basic.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(basic.value()).isEqualTo("value"); + soft.assertThat(basic.isNegated()).isTrue(); + }); + } + + @Test + void shouldCombineAllRestrictionsWithNegation() { + Restriction r1 = Restrict.notEqualTo("value1", "field1"); + Restriction r2 = Restrict.greaterThan(100, "field2"); + + Restriction combined = Restrict.all(r1, r2); + + assertThat(combined).isInstanceOf(CompositeRestrictionRecord.class); + + CompositeRestrictionRecord composite = (CompositeRestrictionRecord) combined; + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(composite.type()).isEqualTo(CompositeRestriction.Type.ALL); + soft.assertThat(composite.restrictions()).containsExactly(r1, r2); + soft.assertThat(composite.isNegated()).isFalse(); + }); + } + + @Test + void shouldCreateContainsRestriction() { + TextRestriction restriction = Restrict.contains("substring", "field"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("field"); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%substring%"); + soft.assertThat(restriction.isNegated()).isFalse(); + }); + } + + @Test + void shouldCreateNegatedContainsRestriction() { + TextRestriction restriction = Restrict.notContains("substring", "field"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("field"); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%substring%"); + soft.assertThat(restriction.isNegated()).isTrue(); + }); + } + + @Test + void shouldCreateStartsWithRestriction() { + TextRestriction restriction = Restrict.startsWith("prefix", "field"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("field"); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("prefix%"); + soft.assertThat(restriction.isNegated()).isFalse(); + }); + } + + @Test + void shouldCreateNegatedStartsWithRestriction() { + TextRestriction restriction = Restrict.notStartsWith("prefix", "field"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("field"); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("prefix%"); + soft.assertThat(restriction.isNegated()).isTrue(); + }); + } + + @Test + void shouldCreateEndsWithRestriction() { + TextRestriction restriction = Restrict.endsWith("suffix", "field"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("field"); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%suffix"); + soft.assertThat(restriction.isNegated()).isFalse(); + }); + } + + @Test + void shouldCreateNegatedEndsWithRestriction() { + TextRestriction restriction = Restrict.notEndsWith("suffix", "field"); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("field"); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%suffix"); + soft.assertThat(restriction.isNegated()).isTrue(); + }); + } + + @Test + void shouldEscapeToLikePatternCorrectly() { + String result = invokeToLikeEscaped('_', '%', true, "test_value", false); + + assertThat(result).isEqualTo("%test\\_value"); + } + + @Test + void shouldThrowExceptionForInvalidWildcard() { + assertThatThrownBy(() -> invokeToLikeEscaped('_', '_', true, "value", false)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot use the same character (_) for both types of wildcards."); + } + + private String invokeToLikeEscaped(char charWildcard, char stringWildcard, boolean allowPrevious, String literal, boolean allowSubsequent) { + return Restrict.toLikeEscaped(charWildcard, stringWildcard, allowPrevious, literal, allowSubsequent); + } +} diff --git a/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java b/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java new file mode 100644 index 000000000..ebb01e248 --- /dev/null +++ b/api/src/test/java/jakarta/data/TextRestrictionRecordTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data; + +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.Test; + + +class TextRestrictionRecordTest { + + @Test + void shouldCreateTextRestrictionWithDefaultValues() { + TextRestrictionRecord restriction = new TextRestrictionRecord<>( + "title", + Operator.LIKE, + "%Java%" + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("title"); + soft.assertThat(restriction.isNegated()).isFalse(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%Java%"); + soft.assertThat(restriction.isCaseSensitive()).isTrue(); + soft.assertThat(restriction.isEscaped()).isFalse(); + }); + } + + @Test + void shouldCreateTextRestrictionWithExplicitNegation() { + TextRestrictionRecord restriction = new TextRestrictionRecord<>( + "title", + true, + Operator.LIKE, + "%Java%" + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("title"); + soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%Java%"); + soft.assertThat(restriction.isCaseSensitive()).isTrue(); + soft.assertThat(restriction.isEscaped()).isFalse(); + }); + } + + @Test + void shouldIgnoreCaseForTextRestriction() { + TextRestrictionRecord restriction = new TextRestrictionRecord<>( + "title", + Operator.LIKE, + "%Java%" + ); + + Restriction caseInsensitiveRestriction = restriction.ignoreCase(); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(caseInsensitiveRestriction).isInstanceOf(TextRestrictionRecord.class); + TextRestrictionRecord textRestriction = (TextRestrictionRecord) caseInsensitiveRestriction; + soft.assertThat(textRestriction.field()).isEqualTo("title"); + soft.assertThat(textRestriction.isNegated()).isFalse(); + soft.assertThat(textRestriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(textRestriction.value()).isEqualTo("%Java%"); + soft.assertThat(textRestriction.isCaseSensitive()).isFalse(); + soft.assertThat(textRestriction.isEscaped()).isFalse(); + }); + } + + @Test + void shouldCreateTextRestrictionWithEscapedValue() { + TextRestrictionRecord restriction = new TextRestrictionRecord<>( + "title", + Operator.LIKE, + true, + "%Java%" + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("title"); + soft.assertThat(restriction.isNegated()).isFalse(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.LIKE); + soft.assertThat(restriction.value()).isEqualTo("%Java%"); + soft.assertThat(restriction.isCaseSensitive()).isTrue(); + soft.assertThat(restriction.isEscaped()).isTrue(); + }); + } + + @Test + void shouldSupportNegationForTextRestriction() { + TextRestrictionRecord restriction = new TextRestrictionRecord<>( + "author", + true, + Operator.EQUAL, + "John Doe" + ); + + SoftAssertions.assertSoftly(soft -> { + soft.assertThat(restriction.field()).isEqualTo("author"); + soft.assertThat(restriction.isNegated()).isTrue(); + soft.assertThat(restriction.comparison()).isEqualTo(Operator.EQUAL); + soft.assertThat(restriction.value()).isEqualTo("John Doe"); + soft.assertThat(restriction.isCaseSensitive()).isTrue(); + soft.assertThat(restriction.isEscaped()).isFalse(); + }); + } +}