Skip to content

Commit

Permalink
Removed ImmutablePatternValidator from DefinitionIdentifier. Added Im…
Browse files Browse the repository at this point in the history
…mutableFeature tests.

Signed-off-by: David Joos <david.joos@bosch-si.com>
  • Loading branch information
David Joos committed May 8, 2020
1 parent 36ed598 commit 73179ae
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 54 deletions.
Expand Up @@ -36,6 +36,9 @@ public final class JsonPointerInvalidException extends JsonRuntimeException {
private static final String OUTER_SLASHES_DESCRIPTION =
"Leading or trailing slashes in JSON pointers are not supported.";

private static final String NO_SLASHES_NO_CONTROL_CHARACTERS_DESCRIPTION =
"Neither slashes nor any control characters are allowed at any place in your JSON Pointer. Please check!";

private static final long serialVersionUID = -6773700329225961931L;

private JsonPointerInvalidException(@Nullable final String message,
Expand All @@ -46,6 +49,12 @@ private JsonPointerInvalidException(@Nullable final String message,
super(ERROR_CODE, message, description, cause, href);
}

public static String getFullRestrictionMessage() {
return NO_SLASHES_NO_CONTROL_CHARACTERS_DESCRIPTION;
}

public static String getOuterSlashesDescription() { return OUTER_SLASHES_DESCRIPTION; }

/**
* Returns a builder for fluently creating instances of {@code JsonPointerInvalidException}s..
*
Expand Down Expand Up @@ -73,7 +82,7 @@ static JsonExceptionBuilder<JsonPointerInvalidException> newBuilderForConsecutiv
* Returns a new builder already containing a generic message that leading or trailing slashes are not supported for JSON
* pointers.
*
* @param jsonPointer The JSON pointer containing the consecutive slashes.
* @param jsonPointer The JSON pointer containing the leading and/or trailing slashes.
* @return a builder for {@code JsonPointerInvalidException} objects.
*/
public static JsonExceptionBuilder<JsonPointerInvalidException> newBuilderForOuterSlashes(
Expand All @@ -83,6 +92,33 @@ public static JsonExceptionBuilder<JsonPointerInvalidException> newBuilderForOut
.description(OUTER_SLASHES_DESCRIPTION);
}

/**
* Returns a new builder containing the given message for the given JSON pointers.
*
* @param jsonPointer The JSON pointer the message is about.
* @param description The description to be in the exception.
* @return a builder for {@code JsonPointerInvalidException} objects.
*/
public static JsonExceptionBuilder<JsonPointerInvalidException> newBuilderWithDescription(
final CharSequence jsonPointer, final String description) {
return new Builder()
.jsonPointer(jsonPointer)
.description(description);
}

/**
* Returns a new builder already containing a default message that the JSON pointer is no valid.
*
* @param jsonPointer The JSON pointer the message is about.
* @return a builder for {@code JsonPointerInvalidException} objects.
*/
public static JsonExceptionBuilder<JsonPointerInvalidException> newBuilderWithoutDescription(
final CharSequence jsonPointer) {
return new Builder()
.jsonPointer(jsonPointer)
.description(DEFAULT_DESCRIPTION);
}

/**
* A mutable builder for a {@code JsonPointerInvalidException}.
*/
Expand Down
8 changes: 8 additions & 0 deletions model/things/pom.xml
Expand Up @@ -124,6 +124,14 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
Expand Up @@ -19,6 +19,7 @@

import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonObject;
import org.eclipse.ditto.json.JsonPointerInvalidException;

/**
* Factory that creates new {@code attributes} objects.
Expand Down Expand Up @@ -62,7 +63,13 @@ public static Attributes newAttributes(final JsonObject jsonObject) {
checkNotNull(jsonObject, "JSON object for initialization");

if (!jsonObject.isNull()) {
ImmutablePatternValidator.toBuilder().withAttributePattern().buildFor(jsonObject).validate();

ImmutablePatternValidator.toBuilder()
.withAttributePattern()
.withExceptionDescription(JsonPointerInvalidException.getFullRestrictionMessage())
.build()
.validate(jsonObject);

return ImmutableAttributes.of(jsonObject);
} else {
return nullAttributes();
Expand Down
Expand Up @@ -16,6 +16,7 @@
import static org.eclipse.ditto.model.base.common.ConditionChecker.checkNotNull;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.concurrent.Immutable;
Expand Down Expand Up @@ -80,16 +81,10 @@ static DefinitionIdentifier ofParsed(final CharSequence definitionIdentifier) {
return (DefinitionIdentifier) definitionIdentifier;
}


ImmutablePatternValidator.toBuilder().withPattern(IDENTIFIER_PATTERN).buildFor(definitionIdentifier).validate();

// final Matcher matcher = IDENTIFIER_PATTERN.matcher(definitionIdentifier);



// if (!matcher.matches()) {
// throw new DefinitionIdentifierInvalidException(definitionIdentifier);
// }
final Matcher matcher = IDENTIFIER_PATTERN.matcher(definitionIdentifier);
if (!matcher.matches()) {
throw new DefinitionIdentifierInvalidException(definitionIdentifier);
}

final String parsedNamespace = matcher.group(CapturingGroup.NAMESPACE);
final String parsedName = matcher.group(CapturingGroup.NAME);
Expand Down
Expand Up @@ -83,7 +83,12 @@ public static ImmutableFeature of(final String featureId, @Nullable final Featur
public static ImmutableFeature of(final String featureId, @Nullable final FeatureDefinition definition,
@Nullable final FeatureProperties properties) {

ImmutablePatternValidator.toBuilder().withFeaturePattern().buildFor(featureId).validate();
ImmutablePatternValidator.toBuilder()
.withFeaturePattern()
.withExceptionDescription(JsonPointerInvalidException.getFullRestrictionMessage())
.withTargetDescription("ID of the Feature")
.build()
.validate(featureId);

return new ImmutableFeature(featureId, definition, properties);
}
Expand Down
Expand Up @@ -2,6 +2,7 @@

import static org.eclipse.ditto.model.base.common.ConditionChecker.checkNotNull;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Nullable;
Expand All @@ -12,53 +13,54 @@
import org.eclipse.ditto.json.JsonPointerInvalidException;

@Immutable
final class ImmutablePatternValidator<T> {
final class ImmutablePatternValidator {

private final Pattern pattern;
private final T t;
@Nullable
private final String exceptionDescription;
@Nullable
private final String targetDescription;

public static ImmutablePatternValidatorBuilder toBuilder() {
return new ImmutablePatternValidatorBuilder();
}

private ImmutablePatternValidator(final Pattern pattern, final T t) {
private ImmutablePatternValidator(final Pattern pattern, @Nullable final String exception, @Nullable String targetDescription) {
this.pattern = pattern;
this.t = t;
this.exceptionDescription = exception;
this.targetDescription = targetDescription;
}

private void validateCharSequence(final CharSequence featureId) {
if (!pattern.matcher(featureId).matches()) {
throw JsonPointerInvalidException.newBuilder().build();
public void validate(final JsonObject target) {
for (final JsonKey key : target.getKeys()) {
validate(key);
}
}

private void validateJsonKeys(final JsonObject jsonObject) {
for (final JsonKey key : jsonObject.getKeys()) {
if (!pattern.matcher(key).matches()) {
throw JsonPointerInvalidException.newBuilder().build();
}
}
}

public void validate() {
if (t instanceof JsonObject) {
this.validateJsonKeys((JsonObject) t);
}

if (t instanceof CharSequence) {
this.validateCharSequence((CharSequence) t);
public Matcher validate(final CharSequence target) {
checkNotNull(target, this.targetDescription != null ? this.targetDescription : "Target");
final Matcher matcher = pattern.matcher(target);
if (!matcher.matches()) {
throw this.exceptionDescription != null ?
JsonPointerInvalidException.newBuilderWithDescription(target, this.exceptionDescription).build() :
JsonPointerInvalidException.newBuilderWithoutDescription(target).build();
}
return matcher;
}

static final class ImmutablePatternValidatorBuilder {

@Nullable
private Pattern pattern;
@Nullable
private String exceptionDescription;
@Nullable
private String targetDescription;

private final Pattern ATTRIBUTE_FEATURE_PATTERN = Pattern.compile("^[^/<>\\\\&%$\\s]*$");
private final Pattern ATTRIBUTE_FEATURE_PATTERN = Pattern.compile("^[^/<>\\\\&%$?\\s]*$");

public ImmutablePatternValidatorBuilder withPattern(final Pattern pattern) {
checkNotNull(pattern, "pattern to be set");
checkNotNull(pattern, "Pattern");
this.pattern = pattern;
return this;
}
Expand All @@ -72,16 +74,20 @@ public ImmutablePatternValidatorBuilder withFeaturePattern() {
return withAttributePattern();
}

public ImmutablePatternValidator<?> buildFor(JsonObject target) {
checkNotNull(target, "target to check must be set");
return new ImmutablePatternValidator<JsonObject>(this.pattern, target);
public ImmutablePatternValidatorBuilder withExceptionDescription(final String description) {
this.exceptionDescription = description;
return this;
}

public ImmutablePatternValidator<?> buildFor(CharSequence target) {
checkNotNull(target, "target to check must be set");
return new ImmutablePatternValidator<CharSequence>(this.pattern, target);
public ImmutablePatternValidatorBuilder withTargetDescription(final String description) {
this.targetDescription = description;
return this;
}

public ImmutablePatternValidator build() {
checkNotNull(this.pattern, "Pattern");
return new ImmutablePatternValidator(this.pattern, this.exceptionDescription, this.targetDescription);
}
}

}

This file was deleted.

Expand Up @@ -265,7 +265,7 @@ public static FeatureProperties newFeatureProperties(final JsonObject jsonObject
checkNotNull(jsonObject, "JSON object for initialization");

if (!jsonObject.isNull()) {
ImmutablePatternValidator.toBuilder().withFeaturePattern().buildFor(jsonObject).validate();
ImmutablePatternValidator.toBuilder().withFeaturePattern().build().validate(jsonObject);
return ImmutableFeatureProperties.of(jsonObject);
} else {
return nullFeatureProperties();
Expand Down
Expand Up @@ -23,6 +23,7 @@
import static org.mutabilitydetector.unittesting.MutabilityMatchers.areImmutable;

import java.lang.ref.SoftReference;
import java.util.List;

import org.eclipse.ditto.json.JsonFactory;
import org.eclipse.ditto.json.JsonObject;
Expand All @@ -46,6 +47,56 @@ public final class ImmutableFeatureTest {
private static final String KNOWN_FEATURE_ID = "myFeature";
private static final String LEADING_SLASH_FEATURE_ID = "/wrongFeature";
private static final String ENDING_SLASH_FEATURE_ID = "wrongFeature/";
private static final String SLASH_INBETWEEN_ID = "wrong/Feature";

private static final List<String> wrongFeatureIDs = List.of(
"//",
"/wrong",
"wrong/",
"//wrong",
"wrong//",
"wrong/wrong",
"wrong//wrong",
"<WRONG>",
"wrong<>wrong",
"wronger>wrong",
"wrong<wronger",
"wrong%2",
"%wrong",
"wrong%wrong",
"wrong?",
"wrong&wrong",
"$wrong",
"wrong and wrong",
"wrong wrong",
"folder\no!",
"folder\\no",
"wrong\ttab",
"wrong\nwrong"
);

private static final List<String> allowedFeatureIDs = List.of(
"right",
"right:right",
"this-is-right",
"right+allowed",
"right§right",
"why.not",
"guess@what",
"@right",
"right.",
"~folder",
"#1",
"right,allowed,legal",
"RIGHT!",
"--------right,allowed,legal!RIGHT(sure#1)!`allowed`",
"*notice",
"notice*",
"right.allowed:legal",
"123",
"|-.-|",
"{right]"
);

private static final JsonObject KNOWN_JSON_OBJECT = JsonFactory.newObjectBuilder()
.set(Feature.JsonFields.SCHEMA_VERSION, KNOWN_SCHEMA_VERSION.toInt())
Expand Down Expand Up @@ -103,6 +154,28 @@ public void createInstanceWithEndingSlash() {
.isThrownBy(() -> ImmutableFeature.of(ENDING_SLASH_FEATURE_ID, null));
}

@Test
public void createInstanceWithInbetweenSlash() {
assertThatExceptionOfType(JsonPointerInvalidException.class)
.isThrownBy(() -> ImmutableFeature.of(SLASH_INBETWEEN_ID, null));
}

@Test
public void testWrongFeatureIds() {
wrongFeatureIDs.forEach(featureId ->
assertThatExceptionOfType(JsonPointerInvalidException.class).isThrownBy(
() -> ImmutableFeature.of(featureId, null))
);
}

@Test
public void testAllowedFeatureIds() {
allowedFeatureIDs.forEach(featureId -> {
final Feature underTest = ImmutableFeature.of(featureId);
assertThat(underTest.getId()).isEqualTo(featureId);
});
}

@Test
public void getIdReturnsExpected() {
final Feature underTest = ImmutableFeature.of(KNOWN_FEATURE_ID);
Expand Down

0 comments on commit 73179ae

Please sign in to comment.