Skip to content

fix: support uppercase attribute names introspection #173

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 45 commits into from
Sep 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ced4b40
fix: support uppercase attribute names introspection
igdianov Aug 28, 2019
82e9430
fix: make getFieldName private
igdianov Aug 28, 2019
a5d11de
fix: polish
igdianov Aug 28, 2019
739bdca
Add duplicated property test case (#178)
anotender Aug 30, 2019
ed7a85e
fix: add test case for private getter (#175)
igdianov Aug 30, 2019
5b4b722
fix: refactor IntrospectionUtils
igdianov Aug 31, 2019
64f8cfa
fix: remove redundant code
igdianov Aug 31, 2019
276f257
fix: polish IntrospectionUtils
igdianov Aug 31, 2019
f6c9616
polish IntrospectionUtils
igdianov Aug 31, 2019
7421b2b
fix: use JPA's ManagedType for entity introspection
igdianov Aug 31, 2019
44f9240
fix: cannot find symbol compile error
igdianov Aug 31, 2019
a304c2d
fix: cannot find symbol symbol: method isEmpty()
igdianov Aug 31, 2019
a74f925
fix: add protected getter test case
igdianov Aug 31, 2019
da0d06b
fix: add ignored attribute property descriptor tests
igdianov Aug 31, 2019
c9d7875
fix: polish IntrospectionUtils
igdianov Aug 31, 2019
d2799b9
fix: add protectedGetter to CalculatedEntityTests
igdianov Aug 31, 2019
ed429a5
fix: refactor ObjectValue conversion
igdianov Sep 1, 2019
d9c7fcc
fix: refactor persistent attribute detection
igdianov Sep 1, 2019
502b4ab
fix: remove redundant code persistent detection logic
igdianov Sep 1, 2019
d88953c
fix: add introspection support for protected getter methods
igdianov Sep 3, 2019
10de6d6
feat: refactor class introspection utils
igdianov Sep 5, 2019
7fd94dd
Add custom metamodel test case
Sep 4, 2019
f2790c4
fix: refactor IntrospectionUtils to EntityIntrospector
igdianov Sep 5, 2019
3ff4473
fix: add ArrayUtil test coverage
igdianov Sep 6, 2019
141b889
fix: add ReflectionUtil tests
igdianov Sep 6, 2019
bc6ec06
fix: add ClassIntrospector tests
igdianov Sep 6, 2019
50ac0c5
fix: add ClassUtil tests
igdianov Sep 6, 2019
97c723b
fix: filter static methods
igdianov Sep 6, 2019
e255267
fix: failing test methods
igdianov Sep 6, 2019
ac1eccf
fix: add ObjectUtil tests
igdianov Sep 6, 2019
a06fcff
feat: add scanStatics option to ClassIntrospector
igdianov Sep 7, 2019
379219e
fix: add test coverage for annotation descriptors
igdianov Sep 7, 2019
9f623dd
fix: add constructor and property descriptor tests
igdianov Sep 7, 2019
685628e
fix: polish ClassIntrospectorTest format
igdianov Sep 7, 2019
dfe897c
fix: add PropertyDescriptor tests
igdianov Sep 7, 2019
bd6ccb1
fix: add PropertyDescriptor equals and hashCode
igdianov Sep 7, 2019
40e85b2
fix: add ConstructorDescriptor tests
igdianov Sep 7, 2019
c47b9de
fix: add PropertyDescriptor equals and hashCode tests
igdianov Sep 7, 2019
35bfb38
fix: add AnnotationDescriptor tests
igdianov Sep 7, 2019
036a21c
fix: add FieldDescriptor tests
igdianov Sep 7, 2019
f46ec64
fix: add MethodDescriptor tests
igdianov Sep 8, 2019
545ce02
fix: add BeanUtil test coverage
igdianov Sep 8, 2019
3512a8a
fix: add missing PropertyDescriptorTest coverage
igdianov Sep 8, 2019
a6fc0a3
fix: PropertyDecriptor NPE check
igdianov Sep 8, 2019
5a51ccf
fix: add basic introspection tests
igdianov Sep 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.introproventures.graphql.jpa.query.introspection;


import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Arrays;
import java.util.Objects;

public class AnnotationDescriptor {

private final Annotation annotation;

private final Class<? extends Annotation> annotationType;

private final ElementType[] elementTypes;

private final RetentionPolicy policy;

private final boolean isDocumented;

private final boolean isInherited;

public <A extends Annotation> AnnotationDescriptor(A annotation) {
this.annotation = annotation;
annotationType = annotation.annotationType();

Target target = annotationType.getAnnotation(Target.class);
elementTypes = (target == null) ? ElementType.values() : target.value();

Retention retention = annotationType.getAnnotation(Retention.class);
policy = (retention == null) ? RetentionPolicy.CLASS : retention.value();

Documented documented = annotationType.getAnnotation(Documented.class);
isDocumented = (documented != null);

Inherited inherited = annotationType.getAnnotation(Inherited.class);
isInherited = (inherited != null);
}

@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation() {
return (A) annotation;
}

public Class<? extends Annotation> getAnnotationType() {
return annotationType;
}

public ElementType[] getElementTypes() {
return elementTypes;
}

public RetentionPolicy getPolicy() {
return policy;
}

public boolean isDocumented() {
return isDocumented;
}

public boolean isInherited() {
return isInherited;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("AnnotationDescriptor [annotation=")
.append(annotation)
.append(", annotationType=")
.append(annotationType)
.append(", elementTypes=")
.append(Arrays.toString(elementTypes))
.append(", policy=")
.append(policy)
.append(", isDocumented=")
.append(isDocumented)
.append(", isInherited=")
.append(isInherited)
.append("]");
return builder.toString();
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(elementTypes);
result = prime * result + Objects.hash(annotation, annotationType, isDocumented, isInherited, policy);
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AnnotationDescriptor other = (AnnotationDescriptor) obj;
return Objects.equals(annotation, other.annotation)
&& Objects.equals(annotationType, other.annotationType)
&& Arrays.equals(elementTypes, other.elementTypes)
&& isDocumented == other.isDocumented
&& isInherited == other.isInherited
&& policy == other.policy;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package com.introproventures.graphql.jpa.query.introspection;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

public class Annotations {

protected final AnnotatedElement annotatedElement;

protected final Map<Class<? extends Annotation>, AnnotationDescriptor> annotationsMap;

// cache
private AnnotationDescriptor[] allAnnotations;

public Annotations(AnnotatedElement annotatedElement) {
this.annotatedElement = annotatedElement;
this.annotationsMap = inspectAnnotations();
}

private Map<Class<? extends Annotation>, AnnotationDescriptor> inspectAnnotations() {

Annotation[] annotations = ReflectionUtil.getAnnotation(annotatedElement);
if (ArrayUtil.isEmpty(annotations)) {
return null;
}

Map<Class<? extends Annotation>, AnnotationDescriptor> map = new LinkedHashMap<>(annotations.length);

for (Annotation annotation : annotations) {
map.put(annotation.annotationType(), new AnnotationDescriptor(annotation));
}

return map;
}

public AnnotationDescriptor getAnnotationDescriptor(Class<? extends Annotation> clazz) {
if (annotationsMap == null) {
return null;
}

return annotationsMap.get(clazz);
}

public AnnotationDescriptor[] getAllAnnotationDescriptors() {
if (annotationsMap == null) {
return null;
}

if (allAnnotations == null) {
AnnotationDescriptor[] allAnnotations = new AnnotationDescriptor[annotationsMap.size()];

int index = 0;
for (AnnotationDescriptor annotationDescriptor : annotationsMap.values()) {
allAnnotations[index] = annotationDescriptor;
index++;
}

Arrays.sort(allAnnotations, new Comparator<AnnotationDescriptor>() {
@Override
public int compare(AnnotationDescriptor ad1, AnnotationDescriptor ad2) {
return ad1.getClass().getName().compareTo(ad2.getClass().getName());
}
});

this.allAnnotations = allAnnotations;
}

return allAnnotations;
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Annotations [annotatedElement=").append(annotatedElement).append("]");
return builder.toString();
}

@Override
public int hashCode() {
return Objects.hash(annotatedElement);
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Annotations other = (Annotations) obj;
return Objects.equals(annotatedElement, other.annotatedElement);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.introproventures.graphql.jpa.query.introspection;

import java.lang.reflect.Array;

public class ArrayUtil {

private static final int INDEX_NOT_FOUND = -1;

public static boolean isEmpty(Object array) {
if(array == null) {
return true;
}

// not an array
if(!array.getClass().isArray()) {
return false;
}

// check array length
return Array.getLength(array) == 0;
}

public static boolean isNotEmpty(Object array) {
return !isEmpty(array);
}

public static int indexOf(Object[] array, Object objectToFind) {
return indexOf(array, objectToFind, 0);
}

public static int indexOf(Object[] array, Object objectToFind, int startIndex) {
if (array == null) {
return INDEX_NOT_FOUND;
}

if (startIndex < 0) {
startIndex = 0;
}

if (objectToFind == null) {
for (int i = startIndex; i < array.length; i++) {
if (array[i] == null) {
return i;
}
}
} else {
for (int i = startIndex; i < array.length; i++) {
if (objectToFind.equals(array[i])) {
return i;
}
}
}

return INDEX_NOT_FOUND;
}

public static <T> T[] addAll(T[] array1, T[] array2) {
if (array1 == null) {
return (T[]) clone(array2);
} else if (array2 == null) {
return (T[]) clone(array1);
}
@SuppressWarnings("unchecked")
T[] joinedArray = (T[]) Array.newInstance(array1.getClass().getComponentType(), array1.length + array2.length);
System.arraycopy(array1, 0, joinedArray, 0, array1.length);
try {
System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
} catch (ArrayStoreException ase) {
// Check if problem was due to incompatible types
/*
* We do this here, rather than before the copy because: - it would be a wasted check most of the time -
* safer, in case check turns out to be too strict
*/
final Class<?> type1 = array1.getClass().getComponentType();
final Class<?> type2 = array2.getClass().getComponentType();
if (!type1.isAssignableFrom(type2)) {
throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
+ type1.getName());
}
throw ase; // No, so rethrow original
}
return joinedArray;
}

public static <T> T[] clone(T[] array) {
if (array == null) {
return null;
}

return (T[]) array.clone();
}

}
Loading