Skip to content

Commit

Permalink
Merged 1.7.0 into master.
Browse files Browse the repository at this point in the history
  • Loading branch information
01es committed Dec 13, 2024
2 parents ec59175 + 19f0269 commit 169e7ef
Show file tree
Hide file tree
Showing 164 changed files with 4,674 additions and 1,680 deletions.
2 changes: 1 addition & 1 deletion platform-annotation-processors/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>fielden</groupId>
<artifactId>platform-parent</artifactId>
<version>1.6.0</version>
<version>1.7.0</version>
</parent>

<artifactId>platform-annotation-processors</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,10 @@ public static List<? extends AnnotationMirror> getFieldAnnotationsExcept(final V
.collect(toList());
}

public static boolean hasAnnotation(final AnnotatedConstruct element, final Class<? extends Annotation> annotType) {
return element.getAnnotation(annotType) != null;
}

public boolean hasAnyPresentAnnotation(final Element element, final Collection<? extends Class<? extends Annotation>> annotTypes) {
return elements.getAllAnnotationMirrors(element).stream()
.anyMatch(am -> annotTypes.stream().anyMatch(at -> isSameType(am.getAnnotationType(), at)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ public Pair<String, String> getEntityTitleAndDesc(final EntityElement entityElem
* @return
*/
public TypeMirror getKeyType(final KeyType atKeyType) {
return getAnnotationElementValueOfClassType(atKeyType, a -> a.value());
return getAnnotationElementValueOfClassType(atKeyType, KeyType::value);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ua.com.fielden.platform.processors.utils;

import com.squareup.javapoet.AnnotationSpec;
import ua.com.fielden.platform.entity.annotation.CompositeKeyMember;

import javax.annotation.processing.Generated;

Expand Down Expand Up @@ -29,4 +30,13 @@ public static AnnotationSpec buildAnnotationGenerated(final String generator, fi
.build();
}

/**
* Builds a {@link CompositeKeyMember} annotation.
*
* @param order the value for {@link CompositeKeyMember#value()}
*/
public static AnnotationSpec buildAtCompositeKeyMember(final int order) {
return AnnotationSpec.builder(CompositeKeyMember.class).addMember("value", "$L", order).build();
}

}
Original file line number Diff line number Diff line change
@@ -1,32 +1,7 @@
package ua.com.fielden.platform.processors.verify.verifiers.entity;

import static java.util.Optional.of;
import static ua.com.fielden.platform.processors.metamodel.utils.ElementFinder.asDeclaredType;
import static ua.com.fielden.platform.processors.metamodel.utils.ElementFinder.asTypeElementOfTypeMirror;
import static ua.com.fielden.platform.processors.metamodel.utils.ElementFinder.getSimpleName;
import static ua.com.fielden.platform.processors.metamodel.utils.ElementFinder.isRawType;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ErrorType;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic.Kind;

import ua.com.fielden.platform.domain.PlatformDomainTypes;
import ua.com.fielden.platform.entity.annotation.CompositeKeyMember;
import ua.com.fielden.platform.entity.annotation.Observable;
import ua.com.fielden.platform.entity.meta.PropertyDescriptor;
import ua.com.fielden.platform.processors.appdomain.RegisteredEntitiesCollector;
Expand All @@ -39,6 +14,23 @@
import ua.com.fielden.platform.types.Hyperlink;
import ua.com.fielden.platform.types.Money;

import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ErrorType;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic.Kind;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Optional.empty;
import static java.util.Optional.of;
import static ua.com.fielden.platform.processors.metamodel.utils.ElementFinder.*;

/**
* Composable verifier for entity properties, responsible for the most essential verification, which includes:
* <ol>
Expand All @@ -63,7 +55,8 @@ protected List<AbstractEntityVerifier> createComponents(final ProcessingEnvironm
new PropertyAccessorVerifier(procEnv),
new PropertySetterVerifier(procEnv),
new CollectionalPropertyVerifier(procEnv),
new PropertyTypeVerifier(procEnv));
new PropertyTypeVerifier(procEnv),
new UnionEntityTypedKeyVerifier(procEnv));
}

/**
Expand Down Expand Up @@ -105,7 +98,7 @@ public PropertyVerifier(final EntityFinder entityFinder) {
@Override
public Optional<ViolatingElement> verifyProperty(final EntityElement entity, final PropertyElement property) {
if (hasErrorType(property)) {
return Optional.empty();
return empty();
}

// accessor must be declared
Expand Down Expand Up @@ -135,7 +128,7 @@ public Optional<ViolatingElement> verifyProperty(final EntityElement entity, fin
}
}

return Optional.empty();
return empty();
}
}

Expand Down Expand Up @@ -181,35 +174,35 @@ public PropertyVerifier(final EntityFinder entityFinder) {
@Override
public Optional<ViolatingElement> verifyProperty(final EntityElement entity, final PropertyElement property) {
if (hasErrorType(property)) {
return Optional.empty();
return empty();
}

// setter should be declared
final Optional<ExecutableElement> maybeSetter = entityFinder.findDeclaredPropertySetter(entity, getSimpleName(property.element()));
if (maybeSetter.isEmpty()) {
return Optional.of(new ViolatingElement(
return of(new ViolatingElement(
property.element(), Kind.ERROR, errMissingSetter(getSimpleName(property.element()))));
}

final ExecutableElement setter = maybeSetter.get();
// should be annotated with @Observable
if (setter.getAnnotation(AT_OBSERVABLE_CLASS) == null) {
return Optional.of(new ViolatingElement(setter, Kind.ERROR, errMissingObservable(getSimpleName(setter))));
return of(new ViolatingElement(setter, Kind.ERROR, errMissingObservable(getSimpleName(setter))));
}

// should be public or protected
if (!ElementFinder.isPublic(setter) && !ElementFinder.isProtected(setter)) {
return Optional.of(new ViolatingElement(setter, Kind.ERROR, errNotPublicNorProtected(getSimpleName(setter))));
return of(new ViolatingElement(setter, Kind.ERROR, errNotPublicNorProtected(getSimpleName(setter))));
}

// should accept single argument of the property type
final List<? extends VariableElement> params = setter.getParameters();
if (params.size() != 1 || !elementFinder.types.isSameType(params.get(0).asType(), property.getType())) {
return Optional.of(new ViolatingElement(
return of(new ViolatingElement(
setter, Kind.ERROR, errIncorrectParameters(getSimpleName(setter), property.getType().toString())));
}

return Optional.empty();
return empty();
}
}
}
Expand Down Expand Up @@ -239,16 +232,16 @@ public PropertyVerifier(final EntityFinder entityFinder) {
@Override
public Optional<ViolatingElement> verifyProperty(final EntityElement entity, final PropertyElement property) {
if (hasErrorType(property)) {
return Optional.empty();
return empty();
}
if (!entityFinder.isCollectionalProperty(property)) {
return Optional.empty();
return empty();
}
if (!EntityFinder.isFinal(property.element())) {
return Optional.of(new ViolatingElement(
return of(new ViolatingElement(
property.element(), Kind.ERROR, errMustBeFinal(getSimpleName(property.element()))));
}
return Optional.empty();
return empty();
}
}
}
Expand Down Expand Up @@ -332,31 +325,31 @@ public PropertyVerifier(final EntityFinder entityFinder, final RoundEnvironment
@Override
public Optional<ViolatingElement> verifyProperty(final EntityElement entity, final PropertyElement property) {
if (hasErrorType(property)) {
return Optional.empty();
return empty();
}

final TypeMirror propType = property.getType();

// 1. ordinary type
if (isAnyOf(propType, ORDINARY_TYPES)) return Optional.empty();
if (isAnyOf(propType, ORDINARY_TYPES)) return empty();
// 2. platform type
if (isAnyOf(propType, PLATFORM_TYPES)) return Optional.empty();
if (isAnyOf(propType, PLATFORM_TYPES)) return empty();
// 5. binary type
if (isAnyOf(propType, BINARY_TYPES)) return Optional.empty();
if (isAnyOf(propType, BINARY_TYPES)) return empty();
// 6. special case of collection-like types
if (isSpecialCollectionType(propType)) return Optional.empty();
if (isSpecialCollectionType(propType)) return empty();
// 3.2
if (isAnyOf(propType, SPECIAL_ENTITY_TYPES)) return Optional.empty();
if (isAnyOf(propType, SPECIAL_ENTITY_TYPES)) return empty();
// 3.3
if (isAnyOf(propType, PLATFORM_ENTITY_TYPES)) return Optional.empty();
if (isAnyOf(propType, PLATFORM_ENTITY_TYPES)) return empty();

if (entityFinder.isEntityType(propType)) {
final EntityElement propTypeEntityElt = entityFinder.newEntityElement(asTypeElementOfTypeMirror(propType));
// 3.1 all entity types, except some special ones, used as property types must be registered
if (propTypeEntityElt.isAbstract() || isEntityTypeRegistered(propTypeEntityElt)) {
return Optional.empty();
return empty();
} else {
return Optional.of(new ViolatingElement(
return of(new ViolatingElement(
property.element(), Kind.ERROR,
errEntityTypeMustBeRegistered(getSimpleName(property.element()), getSimpleName(propTypeEntityElt))));
}
Expand All @@ -374,28 +367,28 @@ public Optional<ViolatingElement> verifyProperty(final EntityElement entity, fin
|| isAnyOf(typeArg, PLATFORM_TYPES)
|| isAnyOf(typeArg, PLATFORM_ENTITY_TYPES)
|| isAnyOf(typeArg, SPECIAL_ENTITY_TYPES)) {
return Optional.empty();
return empty();
}

if (entityFinder.isEntityType(typeArg)) {
final EntityElement entityTypeElt = entityFinder.newEntityElement(asTypeElementOfTypeMirror(typeArg));
if (entityTypeElt.isAbstract() || isEntityTypeRegistered(entityTypeElt)) {
return Optional.empty();
return empty();
} else {
return Optional.of(new ViolatingElement(
return of(new ViolatingElement(
property.element(), Kind.ERROR,
errEntityTypeArgMustBeRegistered(getSimpleName(property.element()), getSimpleName(typeArg))));
}
}
// all valid type arguments were exhausted
return Optional.of(new ViolatingElement(
return of(new ViolatingElement(
property.element(), Kind.ERROR, errInvalidCollectionTypeArg(getSimpleName(property.element()))));
}
return Optional.empty(); // TODO process raw collection types
return empty(); // TODO process raw collection types
}

// all supported types were exhausted
return Optional.of(new ViolatingElement(property.element(), Kind.ERROR, errUnsupportedType(getSimpleName(property.element()))));
return of(new ViolatingElement(property.element(), Kind.ERROR, errUnsupportedType(getSimpleName(property.element()))));
}

/**
Expand All @@ -415,4 +408,49 @@ private boolean isEntityTypeRegistered(final EntityElement entityElement) {
}
}

/**
* Union entity types cannot be used for property {@code key} and composite key members.
*/
static final class UnionEntityTypedKeyVerifier extends AbstractEntityVerifier {
UnionEntityTypedKeyVerifier(final ProcessingEnvironment processingEnv) {
super(processingEnv);
}

public static final String ERR_UNION_ENTITY_TYPED_SIMPLE_KEY = "Union entity types are unsupported for property [key].";
public static final String ERR_UNSUPPORTED_TYPE_FOR_PROPERTY = "Unsupported type for property [%s]. Union entity types are unsupported for key members.";

public static String errUnionEntityTypedKeyMember(final CharSequence propName) {
return ERR_UNSUPPORTED_TYPE_FOR_PROPERTY.formatted(propName);
}

@Override
protected List<ViolatingElement> verify(final EntityRoundEnvironment roundEnv) {
return roundEnv.findViolatingDeclaredProperties(new PropertyVerifier(entityFinder));
}

private static class PropertyVerifier extends AbstractPropertyElementVerifier {
public PropertyVerifier(final EntityFinder entityFinder) {
super(entityFinder);
}

@Override
public Optional<ViolatingElement> verifyProperty(final EntityElement entity, final PropertyElement property) {
if (hasErrorType(property)) {
return empty();
}

if (entityFinder.isUnionEntityType(property.getType())) {
if (property.getSimpleName().contentEquals("key")) {
return of(new ViolatingElement(property.element(), Kind.ERROR, ERR_UNION_ENTITY_TYPED_SIMPLE_KEY));
}
else if (hasAnnotation(property.element(), CompositeKeyMember.class)) {
return of(new ViolatingElement(property.element(), Kind.ERROR, errUnionEntityTypedKeyMember(property.getSimpleName())));
}
}

return empty();
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import java.util.List;
import java.util.Optional;

import static java.util.Optional.of;

/**
* Performs verification of a domain model with respect to the {@link KeyType} annotation.
* <p>
Expand Down Expand Up @@ -64,8 +66,8 @@ protected List<AbstractEntityVerifier> createComponents(final ProcessingEnvironm
*/
static class KeyTypePresence extends AbstractEntityVerifier {

static final String ENTITY_DEFINITION_IS_MISSING_KEY_TYPE = "Entity definition is missing @%s.".formatted(
AT_KEY_TYPE_CLASS.getSimpleName());
static final String ERR_ENTITY_DEFINITION_IS_MISSING_KEY_TYPE = "Entity definition is missing @%s.".formatted(AT_KEY_TYPE_CLASS.getSimpleName());
static final String ERR_KEY_TYPE_DEFINITION_REFERENCES_UNION_ENTITY = "Union entity types are not supported for @%s.".formatted(AT_KEY_TYPE_CLASS.getSimpleName());

protected KeyTypePresence(ProcessingEnvironment processingEnv) {
super(processingEnv);
Expand All @@ -76,17 +78,34 @@ public List<ViolatingElement> verify(final EntityRoundEnvironment roundEnv) {
return roundEnv.findViolatingElements(new EntityVerifier(entityFinder));
}

private class EntityVerifier extends AbstractEntityElementVerifier {
private static class EntityVerifier extends AbstractEntityElementVerifier {

public EntityVerifier(final EntityFinder entityFinder) {
super(entityFinder);
}

@Override
public Optional<ViolatingElement> verify(final EntityElement entity) {
// Concrete entity types must have @KeyType
if (!ElementFinder.isAbstract(entity) && entityFinder.findAnnotation(entity, AT_KEY_TYPE_CLASS).isEmpty()) {
return Optional.of(new ViolatingElement(entity.element(), Kind.ERROR, ENTITY_DEFINITION_IS_MISSING_KEY_TYPE));
return Optional.of(new ViolatingElement(entity.element(), Kind.ERROR, ERR_ENTITY_DEFINITION_IS_MISSING_KEY_TYPE));
}

// If @KeyType is present, then we need to verify that it is not of a Union Entity type.
final Optional<TypeMirror> maybeKeyType = entityFinder.determineKeyType(entity);
if (maybeKeyType.isEmpty()) {
return Optional.empty();
}
final TypeMirror keyType = maybeKeyType.get();
if (keyType.getKind() == TypeKind.ERROR) {
return Optional.empty();
}

// If the declared key type is of a Union Entity type, then report an error.
if (entityFinder.isUnionEntityType(keyType)) {
return of(new ViolatingElement(entity.element(), Kind.ERROR, ERR_KEY_TYPE_DEFINITION_REFERENCES_UNION_ENTITY));
}

return Optional.empty();
}
}
Expand Down Expand Up @@ -163,7 +182,7 @@ public Optional<ViolatingElement> verify(final EntityElement entity) {
}
// abstract entities accept a single type argument
else {
final TypeMirror typeArg = parentTypeArgs.get(0);
final TypeMirror typeArg = parentTypeArgs.getFirst();
if (typeArg.getKind() == TypeKind.ERROR) {
return Optional.empty();
}
Expand Down Expand Up @@ -283,6 +302,7 @@ public Optional<ViolatingElement> verify(final EntityElement entity) {
if (keyType.getKind() == TypeKind.ERROR) {
return Optional.empty();
}

// keyProp might have an unresolved type but we still let this verifier run because declaration of property
// key along with @KeyType(NoKey.class) is incorrect regardless of its type
if (elementFinder.isSameType(keyType, NoKey.class)) {
Expand Down
Loading

0 comments on commit 169e7ef

Please sign in to comment.