Skip to content

Commit

Permalink
moves qualifiers to set on attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Gunda Abhishek committed Nov 29, 2024
1 parent 41ed9fa commit ae6eeff
Show file tree
Hide file tree
Showing 23 changed files with 263 additions and 171 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.grookage.leia.client.utils;

import com.grookage.leia.models.annotations.Optional;
import com.grookage.leia.models.annotations.qualifiers.Encrypted;
import com.grookage.leia.models.annotations.qualifiers.PII;
import com.grookage.leia.models.annotations.qualifiers.ShortLived;
import com.grookage.leia.models.annotations.qualifiers.Standard;
import com.grookage.leia.models.attributes.ArrayAttribute;
import com.grookage.leia.models.attributes.BooleanAttribute;
import com.grookage.leia.models.attributes.DoubleAttribute;
Expand All @@ -11,20 +16,22 @@
import com.grookage.leia.models.attributes.ObjectAttribute;
import com.grookage.leia.models.attributes.SchemaAttribute;
import com.grookage.leia.models.attributes.StringAttribute;
import com.grookage.leia.models.qualifiers.EncryptedQualifier;
import com.grookage.leia.models.qualifiers.PIIQualifier;
import com.grookage.leia.models.qualifiers.QualifierInfo;
import com.grookage.leia.models.qualifiers.annotations.Qualifier;
import com.grookage.leia.models.qualifiers.ShortLivedQualifier;
import com.grookage.leia.models.qualifiers.StandardQualifier;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.ClassUtils;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand All @@ -49,93 +56,98 @@ private SchemaAttribute schemaAttribute(final Field field) {

private SchemaAttribute schemaAttribute(final Type type,
final String name,
final QualifierInfo qualifierInfo,
final Set<QualifierInfo> qualifiers,
final boolean optional) {
// Handle Class instances (eg. String, Enum classes, Complex POJO Objects etc.)
if (type instanceof Class<?> klass) {
return schemaAttribute(klass, name, qualifierInfo, optional);
return schemaAttribute(klass, name, qualifiers, optional);
}

// Handle ParameterizedType (e.g., List<String>, Map<String, Integer>)
if (type instanceof ParameterizedType parameterizedType) {
return schemaAttribute(parameterizedType, name, qualifierInfo, optional);
return schemaAttribute(parameterizedType, name, qualifiers, optional);
}

// Handle GenericArrayType (e.g., T[], List<T[]>)
if (type instanceof GenericArrayType genericArrayType) {
return schemaAttribute(genericArrayType, name, qualifierInfo, optional);
return schemaAttribute(genericArrayType, name, qualifiers, optional);
}

throw new UnsupportedOperationException("Unsupported field type: " + type.getTypeName());
}

private SchemaAttribute schemaAttribute(final ParameterizedType parameterizedType,
final String name,
final QualifierInfo qualifierInfo,
final Set<QualifierInfo> qualifiers,
final boolean optional) {
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
// Handle List<T> or Set<T>
if (ClassUtils.isAssignable(rawType, Collection.class)) {
return handleCollection(parameterizedType, name, qualifierInfo, optional);
return handleCollection(parameterizedType, name, qualifiers, optional);
}

// Handle Map<T,R>
if (ClassUtils.isAssignable(rawType, Map.class)) {
return handleMap(parameterizedType, name, qualifierInfo, optional);
return handleMap(parameterizedType, name, qualifiers, optional);
}
throw new UnsupportedOperationException("Unsupported field type: " + parameterizedType.getTypeName());
}

private SchemaAttribute handleMap(ParameterizedType parameterizedType, String name, QualifierInfo qualifierInfo, boolean optional) {
private SchemaAttribute handleMap(ParameterizedType parameterizedType,
String name,
Set<QualifierInfo> qualifiers,
boolean optional) {
final var keyType = parameterizedType.getActualTypeArguments()[0];
final var valueType = parameterizedType.getActualTypeArguments()[1];
return new MapAttribute(
name,
optional,
qualifierInfo,
qualifiers,
schemaAttribute(keyType, "key", getQualifierInfo(keyType), isOptional(keyType)),
schemaAttribute(valueType, "value", getQualifierInfo(valueType), isOptional(valueType))
);
}

private SchemaAttribute handleCollection(ParameterizedType parameterizedType, String name, QualifierInfo qualifierInfo, boolean optional) {
private SchemaAttribute handleCollection(ParameterizedType parameterizedType,
String name,
Set<QualifierInfo> qualifiers, boolean optional) {
final var elementType = parameterizedType.getActualTypeArguments()[0];
return new ArrayAttribute(
name,
optional,
qualifierInfo,
qualifiers,
schemaAttribute(elementType, "element", getQualifierInfo(elementType), isOptional(elementType))
);
}

private SchemaAttribute schemaAttribute(final GenericArrayType genericArrayType,
final String name,
final QualifierInfo qualifierInfo,
final Set<QualifierInfo> qualifiers,
final boolean optional) {
final var componentType = genericArrayType.getGenericComponentType();
return new ArrayAttribute(
name,
optional,
qualifierInfo,
qualifiers,
schemaAttribute(componentType, "element", getQualifierInfo(componentType), isOptional(componentType))
);
}


private SchemaAttribute schemaAttribute(final Class<?> klass,
final String name,
QualifierInfo qualifierInfo,
Set<QualifierInfo> qualifiers,
final boolean optional) {
if (klass == String.class) {
return new StringAttribute(name, optional, qualifierInfo);
return new StringAttribute(name, optional, qualifiers);
}

if (klass.isEnum()) {
return new EnumAttribute(name, optional, qualifierInfo, getEnumValues(klass));
return new EnumAttribute(name, optional, qualifiers, getEnumValues(klass));
}

if (klass.isPrimitive()) {
return handlePrimitive(klass, name, qualifierInfo, optional);
return handlePrimitive(klass, name, qualifiers, optional);
}

// Handle String[], Object[] etc.
Expand All @@ -144,35 +156,34 @@ private SchemaAttribute schemaAttribute(final Class<?> klass,
return new ArrayAttribute(
name,
optional,
qualifierInfo,
qualifiers,
schemaAttribute(componentType, "element", getQualifierInfo(componentType), isOptional(componentType))
);
}


// Handling custom defined POJO's
final var schemaAttributes = buildSchemaAttributes(klass);
return new ObjectAttribute(name, optional, qualifierInfo, schemaAttributes);
return new ObjectAttribute(name, optional, qualifiers, schemaAttributes);
}

private SchemaAttribute handlePrimitive(final Class<?> klass,
final String name,
final QualifierInfo qualifierInfo,
final Set<QualifierInfo> qualifiers,
final boolean optional) {
if (klass == Integer.class || klass == int.class) {
return new IntegerAttribute(name, optional, qualifierInfo);
return new IntegerAttribute(name, optional, qualifiers);
}
if (klass == Boolean.class || klass == boolean.class) {
return new BooleanAttribute(name, optional, qualifierInfo);
return new BooleanAttribute(name, optional, qualifiers);
}
if (klass == Double.class || klass == double.class) {
return new DoubleAttribute(name, optional, qualifierInfo);
return new DoubleAttribute(name, optional, qualifiers);
}
if (klass == Long.class || klass == long.class) {
return new LongAttribute(name, optional, qualifierInfo);
return new LongAttribute(name, optional, qualifiers);
}
if (klass == Float.class || klass == float.class) {
return new FloatAttribute(name, optional, qualifierInfo);
return new FloatAttribute(name, optional, qualifiers);
}

throw new UnsupportedOperationException("Unsupported primitive class type: " + klass.getName());
Expand All @@ -193,20 +204,47 @@ private Set<String> getEnumValues(Class<?> klass) {
.collect(Collectors.toSet());
}

private QualifierInfo getQualifierInfo(Field field) {
Qualifier qualifier = field.getAnnotation(Qualifier.class);
return QualifierInfo.toQualifierInfo(qualifier);
private Set<QualifierInfo> getQualifierInfo(Field field) {
Set<QualifierInfo> qualifierInfos = new HashSet<>();
if (field.isAnnotationPresent(Encrypted.class)) {
qualifierInfos.add(new EncryptedQualifier());
}
if (field.isAnnotationPresent(Standard.class)) {
qualifierInfos.add(new StandardQualifier());
}
if (field.isAnnotationPresent(PII.class)) {
qualifierInfos.add(new PIIQualifier());
}
if (field.isAnnotationPresent(ShortLived.class)) {
final var shortLived = field.getAnnotation(ShortLived.class);
qualifierInfos.add(new ShortLivedQualifier(shortLived.ttlSeconds()));
}
return qualifierInfos;
}

private QualifierInfo getQualifierInfo(Type type) {
private Set<QualifierInfo> getQualifierInfo(Type type) {
if (type instanceof Class<?> klass) {
return getQualifierInfo(klass);
}
return null;
return new HashSet<>();
}

private QualifierInfo getQualifierInfo(Class<?> klass) {
return QualifierInfo.toQualifierInfo(klass.getAnnotation(Qualifier.class));
private Set<QualifierInfo> getQualifierInfo(Class<?> klass) {
Set<QualifierInfo> qualifierInfos = new HashSet<>();
if (klass.isAnnotationPresent(Encrypted.class)) {
qualifierInfos.add(new EncryptedQualifier());
}
if (klass.isAnnotationPresent(Standard.class)) {
qualifierInfos.add(new StandardQualifier());
}
if (klass.isAnnotationPresent(PII.class)) {
qualifierInfos.add(new PIIQualifier());
}
if (klass.isAnnotationPresent(ShortLived.class)) {
final var shortLived = klass.getAnnotation(ShortLived.class);
qualifierInfos.add(new ShortLivedQualifier(shortLived.ttlSeconds()));
}
return qualifierInfos;
}

private boolean isOptional(Type type) {
Expand All @@ -217,11 +255,10 @@ private boolean isOptional(Type type) {
}

private boolean isOptional(Class<?> klass) {
return !klass.isAnnotationPresent(NotNull.class) && !klass.isAnnotationPresent(NotEmpty.class);
return klass.isAnnotationPresent(Optional.class);
}

private boolean isOptional(Field field) {
// Check for @NotNull and @NotEmpty annotations
return !field.isAnnotationPresent(NotNull.class) && !field.isAnnotationPresent(NotEmpty.class);// Default to true if no such annotations are present
return field.isAnnotationPresent(Optional.class);
}
}
Loading

0 comments on commit ae6eeff

Please sign in to comment.