Skip to content

Commit

Permalink
Merge pull request #1 from soujava/829-dynamic-query-restrictions
Browse files Browse the repository at this point in the history
Create test scenarions
  • Loading branch information
njr-11 authored Nov 21, 2024
2 parents 18c00b3 + c6f835e commit 711497c
Show file tree
Hide file tree
Showing 5 changed files with 483 additions and 1 deletion.
3 changes: 2 additions & 1 deletion api/src/main/java/jakarta/data/Restrict.java
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ public static <T> TextRestriction<T> 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,
Expand Down
75 changes: 75 additions & 0 deletions api/src/test/java/jakarta/data/BasicRestrictionRecordTest.java
Original file line number Diff line number Diff line change
@@ -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<String> 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<String> 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<String> 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<String> restriction = new BasicRestrictionRecord<>("author", Operator.EQUAL, "Unknown");
BasicRestrictionRecord<String> 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");
});
}
}
119 changes: 119 additions & 0 deletions api/src/test/java/jakarta/data/CompositeRestrictionRecordTest.java
Original file line number Diff line number Diff line change
@@ -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<String> restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide");
Restriction<String> restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe");

CompositeRestrictionRecord<String> 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<String> restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide");
Restriction<String> restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe");

CompositeRestrictionRecord<String> 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<String> 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<String> restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide");
Restriction<String> restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe");

CompositeRestrictionRecord<String> 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<String> restriction1 = new BasicRestrictionRecord<>("title", Operator.EQUAL, "Java Guide");
Restriction<String> restriction2 = new BasicRestrictionRecord<>("author", Operator.EQUAL, "John Doe");

// When creating a composite restriction and manually setting negation
CompositeRestrictionRecord<String> composite = new CompositeRestrictionRecord<>(
CompositeRestriction.Type.ALL,
List.of(restriction1, restriction2)
);
CompositeRestrictionRecord<String> 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();
});
}
}
165 changes: 165 additions & 0 deletions api/src/test/java/jakarta/data/RestrictTest.java
Original file line number Diff line number Diff line change
@@ -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<String> restriction = Restrict.equalTo("value", "field");

assertThat(restriction).isInstanceOf(TextRestrictionRecord.class);

TextRestrictionRecord<String> basic = (TextRestrictionRecord<String>) 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<String> restriction = Restrict.notEqualTo("value", "field");

assertThat(restriction).isInstanceOf(TextRestrictionRecord.class);

TextRestrictionRecord<String> basic = (TextRestrictionRecord<String>) 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<String> r1 = Restrict.notEqualTo("value1", "field1");
Restriction<String> r2 = Restrict.greaterThan(100, "field2");

Restriction<String> combined = Restrict.all(r1, r2);

assertThat(combined).isInstanceOf(CompositeRestrictionRecord.class);

CompositeRestrictionRecord<String> composite = (CompositeRestrictionRecord<String>) 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<String> 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<String> 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<String> 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<String> 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<String> 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<String> 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);
}
}
Loading

0 comments on commit 711497c

Please sign in to comment.