Skip to content
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

Issue #2210 - Allow Collections in addition to Arrays in the EQL fluent API #2211

Merged
merged 17 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
Expand Up @@ -47,7 +47,7 @@ public EntityFinder(final ProcessingEnvironment procEnv) {

/**
* Returns the element representing the given entity type.
*
*
* @see ElementFinder#getTypeElement(Class)
* @throws ElementFinderException if no corresponding type element was found
*/
Expand All @@ -57,7 +57,7 @@ public EntityElement findEntity(final Class<? extends AbstractEntity> clazz) {

/**
* Returns the element representing the entity type with the specified canonical name.
*
*
* @see ElementFinder#getTypeElement(Class)
* @throws ElementFinderException if no corresponding type element was found
*/
Expand Down Expand Up @@ -87,26 +87,19 @@ public List<PropertyElement> findDeclaredProperties(final EntityElement entityEl
}

/**
* Returns an optional describing a property element that represents a property of {@code entityElement} named {@code propName}.
* Returns an optional describing a property element with the given name that belongs to the given entity.
*
* @param propName simple property path (limited by a single level of depth)
*/
public Optional<PropertyElement> findDeclaredProperty(final EntityElement entityElement, final String propName) {
public Optional<PropertyElement> findDeclaredProperty(final EntityElement entityElement, final CharSequence propName) {
return streamDeclaredProperties(entityElement)
.filter(elt -> elt.getSimpleName().toString().equals(propName))
.filter(elt -> elt.getSimpleName().contentEquals(propName))
.findFirst();
}

/**
* Returns an optional describing a property element that represents a property of {@code entityElement} at {@code propPath}.
* <p>
* The property path must be of length 1 at most.
*/
public Optional<PropertyElement> findDeclaredProperty(final EntityElement entity, final IConvertableToPath propPath) {
return findDeclaredProperty(entity, propPath.toPath());
}

/**
* Returns a stream of all inherited properties with no guarantees on element uniqueness.
*
*
* @see PropertyElement#equals(Object)
* @param entityElement
* @return
Expand Down Expand Up @@ -139,10 +132,10 @@ public Set<PropertyElement> findInheritedProperties(final EntityElement entity)
* The following properties are processed:
* <ul>
* <li>{@code id} – included if this or any of the entities represented by supertypes, is persistent.
* <li>{@code desc} – included if this or any of the entities represented by supertypes, declares {@code desc} or is annotated
* <li>{@code desc} – included if this or any of the entities represented by supertypes, declares {@code desc} or is annotated
* with {@code @DescTitle}, excluded otherwise.
* </ul>
*
*
* @param properties
* @param entity
*/
Expand Down Expand Up @@ -204,37 +197,21 @@ public Set<PropertyElement> findProperties(final EntityElement entityElement) {
}

/**
* Returns an optional describing a property of {@code entityElement} named {@code name}.
* Returns an optional describing a property of {@code entityElement} named {@code name}.
* <p>
* Entity type hiearchy is traversed in natural order and the first matching property is returned.
*
* @param entityElement
* @param name
* @return
*
* @param name simple property path
*/
public Optional<PropertyElement> findProperty(final EntityElement entityElement, final String name) {
public Optional<PropertyElement> findProperty(final EntityElement entityElement, final CharSequence name) {
return streamProperties(entityElement)
.filter(elt -> elt.getSimpleName().toString().equals(name))
.filter(elt -> elt.getSimpleName().contentEquals(name))
.findFirst();
}

/**
* Returns an optional describing a property of {@code entityElement} at {@code path}.
* The property path must be of length 1 at most.
* <p>
* Entity type hiearchy is traversed in natural order and the first matching property is returned.
*
* @param entity
* @param path
* @return
*/
public Optional<PropertyElement> findProperty(final EntityElement entity, final IConvertableToPath path) {
return findProperty(entity, path.toPath());
}

/**
* Finds a property of an entity by traversing it and its hierarchy below {@code rootType}, which is not searched.
*
*
* @param entity
* @param name
* @param rootType the type at which traversal stops
Expand All @@ -255,121 +232,69 @@ public Optional<PropertyElement> findPropertyBelow(final EntityElement entity, f

/**
* Attempts to find an accessor method for the given property by name. The whole entity type hierarchy is searched.
*
* @param entity the entity element to be analysed
* @param propertyName
*
* @param entity the entity element to be analysed
* @param propertyName simple property name
* @return
*/
public Optional<ExecutableElement> findPropertyAccessor(final EntityElement entity, final String propertyName) {
public Optional<ExecutableElement> findPropertyAccessor(final EntityElement entity, final CharSequence propertyName) {
return doFindPropertyAccessor(streamMethods(entity.element()), propertyName);
}

/**
* Attempts to find an accessor method for the given property by path. The whole entity type hierarchy is searched.
* <p>
* The property path must be of length 1 at most.
*
* @param entity the entity element to be analysed
* @param propertyPath
* @return
*/
public Optional<ExecutableElement> findPropertyAccessor(final EntityElement entity, final IConvertableToPath propertyPath) {
return doFindPropertyAccessor(streamMethods(entity.element()), propertyPath.toPath());
}

/**
* Attempts to find a declared accessor method for the given property by name.
*
* @param entity the entity element to be analysed
* @param propertyName
*
* @param entity the entity element to be analysed
* @param propertyName simple property name
* @return
*/
public Optional<ExecutableElement> findDeclaredPropertyAccessor(final EntityElement entity, final String propertyName) {
public Optional<ExecutableElement> findDeclaredPropertyAccessor(final EntityElement entity, final CharSequence propertyName) {
return doFindPropertyAccessor(streamDeclaredMethods(entity.element()), propertyName);
}

/**
* Attempts to find a declared accessor method for the given property by path.
* <p>
* The property path must be of length 1 at most.
*
* @param entity the entity element to be analysed
* @param propertyPath
* @return
*/
public Optional<ExecutableElement> findDeclaredPropertyAccessor(final EntityElement entity, final IConvertableToPath propertyPath) {
return doFindPropertyAccessor(streamDeclaredMethods(entity.element()), propertyPath.toPath());
}

private Optional<ExecutableElement> doFindPropertyAccessor(final Stream<ExecutableElement> methods, final String propertyName) {
final String getName = Accessor.GET.getName(propertyName);
final String isName = Accessor.IS.getName(propertyName);
private Optional<ExecutableElement> doFindPropertyAccessor(final Stream<ExecutableElement> methods, final CharSequence propertyName) {
final String getName = Accessor.GET.getName(propertyName);
final String isName = Accessor.IS.getName(propertyName);

return methods.filter(m -> {
final String methodName = m.getSimpleName().toString();
return methodName.equals(getName) || methodName.equals(isName);
final Name methodName = m.getSimpleName();
return methodName.contentEquals(getName) || methodName.contentEquals(isName);
}).findAny();
}

/**
* Attempts to find a setter method for the given property by name. The whole entity type hierarchy is searched.
*
* @param entity the entity element to be analysed
* @param propertyName
*
* @param entity the entity element to be analysed
* @param propertyName simple property name
* @return
*/
public Optional<ExecutableElement> findPropertySetter(final EntityElement entity, final String propertyName) {
public Optional<ExecutableElement> findPropertySetter(final EntityElement entity, final CharSequence propertyName) {
return doFindPropertySetter(streamMethods(entity.element()), propertyName);
}

/**
* Attempts to find a setter method for the given property by path. The whole entity type hierarchy is searched.
* <p>
* The property path must be of length 1 at most.
*
* @param entity the entity element to be analysed
* @param propertyPath
* @return
*/
public Optional<ExecutableElement> findPropertySetter(final EntityElement entity, final IConvertableToPath propertyPath) {
return doFindPropertySetter(streamMethods(entity.element()), propertyPath.toPath());
}

/**
* Attempts to find a declared setter method for the given property by name.
*
* @param entity the entity element to be analysed
* @param propertyName
*
* @param entity the entity element to be analysed
* @param propertyName simple property name
* @return
*/
public Optional<ExecutableElement> findDeclaredPropertySetter(final EntityElement entity, final String propertyName) {
public Optional<ExecutableElement> findDeclaredPropertySetter(final EntityElement entity, final CharSequence propertyName) {
return doFindPropertySetter(streamDeclaredMethods(entity.element()), propertyName);
}

/**
* Attempts to find a declared setter method for the given property by name.
* <p>
* The property path must be of length 1 at most.
*
* @param entity the entity element to be analysed
* @param propertyPath
* @return
*/
public Optional<ExecutableElement> findDeclaredPropertySetter(final EntityElement entity, final IConvertableToPath propertyPath) {
return doFindPropertySetter(streamDeclaredMethods(entity.element()), propertyPath.toPath());
}

private Optional<ExecutableElement> doFindPropertySetter(final Stream<ExecutableElement> methods, final String propertyName) {
private Optional<ExecutableElement> doFindPropertySetter(final Stream<ExecutableElement> methods, final CharSequence propertyName) {
final String setterName = Mutator.SETTER.getName(propertyName);
return methods.filter(m -> m.getSimpleName().toString().equals(setterName)).findAny();
return methods.filter(m -> m.getSimpleName().contentEquals(setterName)).findAny();
}

/**
* Returns a pair of property title and description as specified by the annotation {@link Title}.
*
*
* @param propElement
* @return
* @throws ElementFinderException if {@link Title} does not have element {@code desc}
* @throws ElementFinderException if {@link Title} does not have element {@code desc}
* or values of elements {@code value} and {@code desc} cannot be type casted to String
*/
public Pair<String, String> getPropTitleAndDesc(final PropertyElement propElement) {
Expand All @@ -380,7 +305,7 @@ public Pair<String, String> getPropTitleAndDesc(final PropertyElement propElemen

/**
* Returns a pair of entity title and description as specified by the annotation {@link EntityTitle}.
*
*
* @throws ElementFinderException if {@link EntityTitle} does not have element {@code desc}
* or values of elements {@code value} and {@code desc} cannot be type casted to String
*/
Expand All @@ -395,7 +320,7 @@ public Pair<String, String> getEntityTitleAndDesc(final EntityElement entityElem

/**
* Returns the actual key type specified by the {@link KeyType} annotation's value.
*
*
* @param atKeyType
* @return
*/
Expand Down Expand Up @@ -538,7 +463,7 @@ public boolean isEntityThatNeedsMetaModel(final EntityElement element) {

/**
* Returns a stream of entity elements, which are superclasses of the given entity element, up to and including {@link AbstractEntity}.
*
*
* @param element
* @return
*/
Expand All @@ -547,14 +472,14 @@ public Stream<EntityElement> streamParents(final EntityElement element) {
}

/**
* Returns the immediate parent entity type of the entity element.
* Returns the immediate parent entity type of the entity element.
* Empty optional is returned if {@code element} represents {@link AbstractEntity} or the element's superclass could
* not be resolved.
*/
public Optional<EntityElement> getParent(final EntityElement element) {
return streamParents(element).findFirst();
}

/**
* Looks for annotation of type {@code annotationClass}, declared for entity {@code element} or any of the supertypes for this entity.
*
Expand Down Expand Up @@ -588,7 +513,7 @@ public Optional<EntityElement> findEntityForMetaModel(final MetaModelElement mme

/**
* Returns a new instance of {@link EntityElement} that is composed of the specified type element.
*
*
* @param typeElement
* @return
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,31 +131,24 @@ private Map<String, Integer> emptyPresence() {
}

@SafeVarargs
public final void addViewBinding(final String binding, final Class<? extends AbstractEntity<?>> type, final String propertyName, final T2<String, String>... paramConfig) {
public final void addViewBinding(final String binding, final Class<? extends AbstractEntity<?>> type, final CharSequence propertyName, final T2<String, ? extends CharSequence>... paramConfig) {
addViewBinding(binding, type, (where, value) -> enhanceEmbededCentreQuery(where, propertyName, value), paramConfig);
}

@SafeVarargs
public final void addViewBinding(final String binding, final Class<? extends AbstractEntity<?>> type, final IConvertableToPath propertyPath, final T2<String, IConvertableToPath>... paramConfig) {
addViewBinding(binding, type, (where, value) -> enhanceEmbededCentreQuery(where, propertyPath, value), paramConfig);
}

@SafeVarargs
public final void addViewBinding(final String binding, final Class<? extends AbstractEntity<?>> type, final String propertyName, final String relativeValueProperty, final T2<String, String>... paramConfig) {
public final void addViewBinding(
final String binding, final Class<? extends AbstractEntity<?>> type,
final CharSequence propertyName, final CharSequence relativeValueProperty,
final T2<String, ? extends CharSequence>... paramConfig) {
addViewBinding(binding, type, (where, value) -> enhanceEmbededCentreQuery(where, propertyName, value, relativeValueProperty), paramConfig);
}

@SafeVarargs
public final void addViewBinding(final String binding, final Class<? extends AbstractEntity<?>> type, final IConvertableToPath propertyPath, final IConvertableToPath relativeValueProperty, final T2<String, IConvertableToPath>... paramConfig) {
addViewBinding(binding, type, (where, value) -> enhanceEmbededCentreQuery(where, propertyPath, value, relativeValueProperty), paramConfig);
}

@SafeVarargs
public final <P> void addViewBinding(
public final void addViewBinding(
final String binding,
final Class<? extends AbstractEntity<?>> type,
final BiFunction<IWhere0<? extends AbstractEntity<?>>, Object, ICompleted<? extends AbstractEntity<?>>> queryEnhnacer,
final T2<String, P>... paramConfig) {
final T2<String, ?>... paramConfig) {
compoundMasterConfig.add(t3(binding, type, queryEnhnacer));
additionalParameters.putAll(Arrays.stream(paramConfig).collect(toMap(entry -> entry._1, entry -> value -> getValue(value, entry._2))));
}
Expand All @@ -165,19 +158,11 @@ public final <P> void addViewBinding(final String binding, final Class<? extends
this.parameters.add(t3(binding, type, Arrays.stream(parameters).collect(toMap(parameter -> parameter._1, parameter -> value -> getValue(value, parameter._2)))));
}

public static <K extends AbstractEntity<?>> ICompleted<K> enhanceEmbededCentreQuery(final IWhere0<K> where, final String prop, final Object value, final String relativeValuePropertyName) {
return where.prop(prop).eq().val(((AbstractEntity<?>) value).get(relativeValuePropertyName));
public static <K extends AbstractEntity<?>> ICompleted<K> enhanceEmbededCentreQuery(final IWhere0<K> where, final CharSequence prop, final Object value, final CharSequence relativeValuePropertyName) {
return where.prop(prop).eq().val(((AbstractEntity<?>) value).get(relativeValuePropertyName.toString()));
}

public static <K extends AbstractEntity<?>> ICompleted<K> enhanceEmbededCentreQuery(final IWhere0<K> where, final IConvertableToPath prop, final Object value, final IConvertableToPath relativeValuePropertyName) {
return where.prop(prop).eq().val(((AbstractEntity<?>) value).get(relativeValuePropertyName));
}

public static <K extends AbstractEntity<?>> ICompleted<K> enhanceEmbededCentreQuery(final IWhere0<K> where, final String prop, final Object value) {
return where.prop(prop).eq().val(value);
}

public static <K extends AbstractEntity<?>> ICompleted<K> enhanceEmbededCentreQuery(final IWhere0<K> where, final IConvertableToPath prop, final Object value) {
public static <K extends AbstractEntity<?>> ICompleted<K> enhanceEmbededCentreQuery(final IWhere0<K> where, final CharSequence prop, final Object value) {
return where.prop(prop).eq().val(value);
}

Expand All @@ -195,12 +180,8 @@ public static <K extends AbstractEntity<?>> Map<String, Object> enhanceParameter
}

private static <P> Object getValue(final Object value, final P propName) {
if (propName instanceof final String strProp) {
return THIS.equals(strProp) ? value : ((AbstractEntity<?>) value).get(strProp);
}

if (propName instanceof final IConvertableToPath pathProp) {
return THIS.equals(pathProp.toPath()) ? value : ((AbstractEntity<?>) value).get(pathProp);
if (propName instanceof final CharSequence cs) {
return THIS.contentEquals(cs) ? value : ((AbstractEntity<?>) value).get(cs.toString());
}

throw new CompoundMasterException("Unexpected value [%s] of type [%s].".formatted(propName, propName.getClass().getSimpleName()));
Expand Down
Loading