Skip to content

Commit

Permalink
Support contextual info in validation
Browse files Browse the repository at this point in the history
  • Loading branch information
benfortuna committed Feb 28, 2022
1 parent 3a6a40b commit 2eac581
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 36 deletions.
22 changes: 19 additions & 3 deletions src/main/java/net/fortuna/ical4j/validate/ValidationRule.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.fortuna.ical4j.validate;

import net.fortuna.ical4j.util.CompatibilityHints;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
Expand All @@ -21,7 +23,7 @@ public enum ValidationType {
OneExclusive("If one is present, ALL others MUST NOT be present."),
AllOrNone("If one is present, ALL must be present.");

String description;
private final String description;

ValidationType(String description) {
this.description = description;
Expand Down Expand Up @@ -56,7 +58,21 @@ public List<String> getInstances() {
return instances;
}

public boolean isRelaxedModeSupported() {
return relaxedModeSupported;
public String getMessage(String...instances) {
List<String> match = getInstances();
if (instances.length > 0) {
match = Arrays.asList(instances);
}
return String.format("%s %s", getType().getDescription(), String.join(",", match));
}

public ValidationEntry.Level getLevel() {
boolean warnOnly = CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_RELAXED_VALIDATION)
&& relaxedModeSupported;
if (warnOnly) {
return ValidationEntry.Level.WARNING;
} else {
return ValidationEntry.Level.ERROR;
}
}
}
54 changes: 21 additions & 33 deletions src/main/java/net/fortuna/ical4j/validate/Validator.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,117 +70,105 @@ static <T> void assertFalse(Predicate<T> predicate, String message, boolean warn
*/
void validate(T target) throws ValidationException;

default List<String> apply(ValidationRule rule, ComponentContainer target) {
default List<ValidationEntry> apply(ValidationRule rule, String context, ComponentContainer<?> target) {
int total = rule.getInstances().stream().mapToInt(s -> target.getComponents(s).size()).sum();
switch (rule.getType()) {
case None:
return rule.getInstances().stream().filter(s -> target.getComponent(s) != null)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case One:
return rule.getInstances().stream().filter(s -> target.getComponents(s).size() != 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneOrLess:
return rule.getInstances().stream().filter(s -> target.getComponents(s).size() > 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneOrMore:
return rule.getInstances().stream().filter(s -> target.getComponents(s).size() < 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneExclusive:
for (String instance : rule.getInstances()) {
int count = target.getComponents(instance).size();
if (count > 0 && count != total) {
return Collections.singletonList(
String.format("%s %s", rule.getType().getDescription(),
String.join(",", rule.getInstances())));
return Collections.singletonList(new ValidationEntry(rule, context));
}
}
case AllOrNone:
if (total > 0 && total != rule.getInstances().size()) {
return Collections.singletonList(
String.format("%s %s", rule.getType().getDescription(),
String.join(",", rule.getInstances())));
return Collections.singletonList(new ValidationEntry(rule, context));
}
}
return Collections.emptyList();
}

default List<String> apply(ValidationRule rule, PropertyContainer target) {
default List<ValidationEntry> apply(ValidationRule rule, String context, PropertyContainer target) {
int total = rule.getInstances().stream().mapToInt(s -> target.getProperties(s).size()).sum();
switch (rule.getType()) {
case None:
return rule.getInstances().stream().filter(s -> target.getProperty(s) != null)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case One:
return rule.getInstances().stream().filter(s -> target.getProperties(s).size() != 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneOrLess:
return rule.getInstances().stream().filter(s -> target.getProperties(s).size() > 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneOrMore:
return rule.getInstances().stream().filter(s -> target.getProperties(s).size() < 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneExclusive:
for (String instance : rule.getInstances()) {
int count = target.getProperties(instance).size();
if (count > 0 && count != total) {
return Collections.singletonList(
String.format("%s %s", rule.getType().getDescription(),
String.join(",", rule.getInstances())));
return Collections.singletonList(new ValidationEntry(rule, context));
}
}
break;
case AllOrNone:
if (total > 0 && total != rule.getInstances().size()) {
return Collections.singletonList(
String.format("%s %s", rule.getType().getDescription(),
String.join(",", rule.getInstances())));
return Collections.singletonList(new ValidationEntry(rule, context));
}
break;
}
return Collections.emptyList();
}

default List<String> apply(ValidationRule rule, Property target) {
default List<ValidationEntry> apply(ValidationRule rule, String context, Property target) {
int total = rule.getInstances().stream().mapToInt(s -> target.getParameters(s).size()).sum();
switch (rule.getType()) {
case None:
return rule.getInstances().stream().filter(s -> target.getParameter(s) != null)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case One:
return rule.getInstances().stream().filter(s -> target.getParameters(s).size() != 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneOrLess:
return rule.getInstances().stream().filter(s -> target.getParameters(s).size() > 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneOrMore:
return rule.getInstances().stream().filter(s -> target.getParameters(s).size() < 1)
.map(s -> String.format("%s %s", rule.getType().getDescription(), s))
.map(s -> new ValidationEntry(rule, context, s))
.collect(Collectors.toList());
case OneExclusive:
for (String instance : rule.getInstances()) {
int count = target.getParameters(instance).size();
if (count > 0 && count != total) {
return Collections.singletonList(
String.format("%s %s", rule.getType().getDescription(),
String.join(",", rule.getInstances())));
return Collections.singletonList(new ValidationEntry(rule, context));
}
}
case AllOrNone:
if (total > 0 && total != rule.getInstances().size()) {
return Collections.singletonList(
String.format("%s %s", rule.getType().getDescription(),
String.join(",", rule.getInstances())));
return Collections.singletonList(new ValidationEntry(rule, context));
}
}
return Collections.emptyList();
Expand Down

0 comments on commit 2eac581

Please sign in to comment.