Skip to content

Commit

Permalink
maintaining nest class path instead of fields in violationContext
Browse files Browse the repository at this point in the history
  • Loading branch information
Gunda Abhishek committed Dec 10, 2024
1 parent 77b18d0 commit 33b3517
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,20 @@ public class SchemaValidationUtils {

private static final String TYPE_VIOLATION = "Incompatible Type, expected: %s, provided: %s";

public Set<LeiaSchemaViolation> valid(final SchemaDetails schemaDetails,
final Class<?> klass) {
public List<LeiaSchemaViolation> valid(final SchemaDetails schemaDetails,
final Class<?> klass) {
return valid(schemaDetails.getValidationType(), schemaDetails.getAttributes(), klass, new ViolationContext());
}

public Set<LeiaSchemaViolation> valid(final SchemaValidationType validationType,
final Set<SchemaAttribute> attributes,
final Class<?> klass,
final ViolationContext context) {
public List<LeiaSchemaViolation> valid(final SchemaValidationType validationType,
final Set<SchemaAttribute> attributes,
final Class<?> klass,
final ViolationContext context) {
context.pushClass(klass);
final var fields = FieldUtils.getAllFields(klass);
validSchema(validationType, attributes, fields, klass, context);
attributes.forEach(each -> validAttribute(each, fields, validationType, context));
context.popClass();
return context.getViolations();
}

Expand All @@ -84,8 +86,7 @@ private void validSchema(final SchemaValidationType validationType,
public Void strict() {
final var mismatchedAttributes = Sets.symmetricDifference(fieldNames, attributesListed);
if (!mismatchedAttributes.isEmpty()) {
context.addViolation(String.format("%s - [STRICT] Validation: attributes not found or extra attributes :%s",
klass.getSimpleName(), mismatchedAttributes));
context.addViolation(String.format("[STRICT] Validation: attributes not found or extra attributes :%s", mismatchedAttributes));
}
return null;
}
Expand All @@ -94,8 +95,7 @@ public Void strict() {
public Void matching() {
final var attributesMissing = Sets.difference(attributesListed, fieldNames);
if (!attributesMissing.isEmpty()) {
context.addViolation(String.format("%s - [MATCHING] Validation: Missing attributes found :%s",
klass.getSimpleName(), attributesMissing));
context.addViolation(String.format("[MATCHING] Validation: Missing attributes found :%s", attributesMissing));
}
return null;
}
Expand All @@ -109,13 +109,11 @@ private void validAttribute(final SchemaAttribute attribute,
final var field = fields.stream()
.filter(each -> each.getName().equals(attribute.getName()))
.findFirst().orElse(null);
context.pushPath(attribute.getName());
if (field == null) {
context.addViolation("Missing Field");
context.addViolation("Missing Field", attribute.getName());
return;
}
valid(validationType, attribute, field.getGenericType(), context);
context.popPath();
}

private void valid(final SchemaValidationType validationType,
Expand All @@ -134,22 +132,24 @@ private void valid(final SchemaValidationType validationType,
}

private void valid(final SchemaValidationType validationType,
final SchemaAttribute attribute,
final SchemaAttribute schemaAttribute,
final Class<?> klass,
final ViolationContext context) {
if (!isMatchingType(klass, attribute)) {
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), klass.getSimpleName()));
if (!isMatchingType(klass, schemaAttribute)) {
context.addViolation(String.format(TYPE_VIOLATION, schemaAttribute.getType(), klass.getSimpleName()),
schemaAttribute.getName());
return;
}

attribute.accept(new SchemaAttributeHandler<Void>(attribute1 -> null) {
schemaAttribute.accept(new SchemaAttributeHandler<Void>(a -> null) {
@Override
public Void accept(ArrayAttribute attribute) {
if (klass.isArray()) {
valid(validationType, attribute.getElementAttribute(), klass.getComponentType(), context);
return null;
} else if (!Objects.isNull(attribute.getElementAttribute())) {
context.addViolation(String.format("Missing Type arguments, expected ParameterizedType:%s", attribute.getElementAttribute().getType()));
context.addViolation(String.format("Missing Type arguments, expected ParameterizedType:%s",
attribute.getElementAttribute().getType()), attribute.getName());
}
return null;
}
Expand All @@ -158,7 +158,7 @@ public Void accept(ArrayAttribute attribute) {
public Void accept(MapAttribute attribute) {
if (!Objects.isNull(attribute.getKeyAttribute()) || !Objects.isNull(attribute.getValueAttribute())) {
context.addViolation(String.format("Missing Type Arguments, expected parameterized Types key:%s value:%s",
attribute.getKeyAttribute().getType(), attribute.getValueAttribute().getType()));
attribute.getKeyAttribute().getType(), attribute.getValueAttribute().getType()), attribute.getName());
}
return null;
}
Expand Down Expand Up @@ -189,7 +189,7 @@ private void valid(final SchemaValidationType validationType,
valid(validationType, mapAttribute.getKeyAttribute(), typeArguments[0], context);
valid(validationType, mapAttribute.getValueAttribute(), typeArguments[1], context);
} else {
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), parameterizedType));
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), parameterizedType), attribute.getName());
}
}

Expand All @@ -201,7 +201,7 @@ private void valid(final SchemaValidationType validationType,
valid(validationType, arrayAttribute.getElementAttribute(), arrayType.getGenericComponentType(), context);
return;
}
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), arrayType));
context.addViolation(String.format(TYPE_VIOLATION, attribute.getType(), arrayType), attribute.getName());
}

private boolean isMatchingType(final Class<?> klass,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ public interface LeiaSchemaViolation {
String message();

String fieldPath();

Class<?> rootKlass();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.grookage.leia.common.violation;

import com.google.common.base.Joiner;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -12,6 +13,7 @@
public class LeiaSchemaViolationImpl implements LeiaSchemaViolation {
private String message;
private String fieldPath;
private Class<?> rootKlass;

@Override
public String message() {
Expand All @@ -24,7 +26,13 @@ public String fieldPath() {
}

@Override
public Class<?> rootKlass() {
return rootKlass;
}

public String toString() {
return String.format("[Violation] %s: %s", fieldPath, message);
return Joiner.on(":")
.skipNulls()
.join(rootKlass, fieldPath, message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,34 @@
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.HashSet;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Set;
import java.util.List;

@Data
@Builder
@NoArgsConstructor
public class ViolationContext {
@Getter
private final Set<LeiaSchemaViolation> violations = new HashSet<>();
private final LinkedList<String> path = new LinkedList<>();
private final List<LeiaSchemaViolation> violations = new ArrayList<>();
private final LinkedList<Class<?>> klassPath = new LinkedList<>();

public void addViolation(final String message) {
String fullPath = String.join(".", path);
violations.add(new LeiaSchemaViolationImpl(message, fullPath));
violations.add(new LeiaSchemaViolationImpl(message, null, klassPath.peekLast()));
}

public void pushPath(final String element) {
path.addLast(element);
public void addViolation(final String message,
final String path) {
violations.add(new LeiaSchemaViolationImpl(message, path, klassPath.peekLast()));
}

public void popPath() {
if (!path.isEmpty()) {
path.removeLast();
public void pushClass(final Class<?> klass) {
klassPath.addLast(klass);
}

public void popClass() {
if (!klassPath.isEmpty()) {
klassPath.removeLast();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public StaticSchemaValidator(Supplier<List<SchemaDetails>> supplier,
}

@SneakyThrows
private Set<LeiaSchemaViolation> validate(final SchemaKey schemaKey, Class<?> klass) {
private List<LeiaSchemaViolation> validate(final SchemaKey schemaKey, Class<?> klass) {
final var details = supplier.get().stream()
.filter(each -> each.match(schemaKey)).findFirst().orElse(null);
if (null == details) {
Expand All @@ -64,7 +64,7 @@ private Set<LeiaSchemaViolation> validate(final SchemaKey schemaKey, Class<?> kl
@Override
public void start() {
log.info("Starting the schema validator");
Map<SchemaKey, Set<LeiaSchemaViolation>> violations = new HashMap<>();
Map<SchemaKey, List<LeiaSchemaViolation>> violations = new HashMap<>();
packageRoots.forEach(handlerPackage -> {
final var reflections = new Reflections(handlerPackage);
final var annotatedClasses = reflections.getTypesAnnotatedWith(SchemaDefinition.class);
Expand Down

0 comments on commit 33b3517

Please sign in to comment.