This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/master by this push:
new 9149425dad CAUSEWAY-3767: refactor validation message to be a template
9149425dad is described below
commit 9149425dadb8690295ee8be059dfc0161115203a
Author: andi-huber <[email protected]>
AuthorDate: Mon Jun 10 08:51:48 2024 +0200
CAUSEWAY-3767: refactor validation message to be a template
- also implements skip on FixtureScript
---
.../progmodel/ProgrammingModelConstants.java | 8 +++
.../LogicalTypeFacetFromClassNameFactory.java | 78 ++++++++--------------
.../core/metamodel/object/MmSpecUtils.java | 26 ++++++++
3 files changed, 61 insertions(+), 51 deletions(-)
diff --git
a/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
b/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
index c323f8d40c..d2f50387d4 100644
---
a/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
+++
b/core/config/src/main/java/org/apache/causeway/core/config/progmodel/ProgrammingModelConstants.java
@@ -463,6 +463,14 @@ public final class ProgrammingModelConstants {
+ "Consider importing type ${type} with Spring's @Import
annotation. "
+ "Types of sort VALUE should instead register a
ValueSemanticsProvider with Spring, "
+ "to be properly understood by the framework."),
+ LOGICAL_TYPE_NAME_IS_NOT_EXPLICIT("The object type ${type} of sort
${beanSort} "
+ + "must be specified explicitly "
+ + "('${configProperty}' config property). "
+ + "Defaulting the object type from the package/class/package
name can lead "
+ + "to data migration issues for apps deployed to production
(if the class is "
+ + "subsequently refactored). "
+ + "Use @Discriminator, @Named or "
+ + "@PersistenceCapable(schema=...) to specify explicitly."),
NON_UNIQUE_LOGICAL_TYPE_NAME_OR_ALIAS("Logical type name (or alias)
${logicalTypeName} "
+ "mapped to multiple non-abstract classes:\n"
+ "${csv}"),
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/logicaltype/classname/LogicalTypeFacetFromClassNameFactory.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/logicaltype/classname/LogicalTypeFacetFromClassNameFactory.java
index 224cd3f242..2d4c46c72f 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/logicaltype/classname/LogicalTypeFacetFromClassNameFactory.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/facets/object/logicaltype/classname/LogicalTypeFacetFromClassNameFactory.java
@@ -21,11 +21,13 @@ package
org.apache.causeway.core.metamodel.facets.object.logicaltype.classname;
import javax.inject.Inject;
import javax.xml.bind.annotation.XmlType;
+import
org.apache.causeway.core.config.progmodel.ProgrammingModelConstants.MessageTemplate;
import org.apache.causeway.core.metamodel.context.MetaModelContext;
import org.apache.causeway.core.metamodel.facetapi.FeatureType;
import org.apache.causeway.core.metamodel.facetapi.MetaModelRefiner;
import org.apache.causeway.core.metamodel.facets.FacetFactoryAbstract;
import org.apache.causeway.core.metamodel.facets.ObjectTypeFacetFactory;
+import org.apache.causeway.core.metamodel.object.MmSpecUtils;
import org.apache.causeway.core.metamodel.progmodel.ProgrammingModel;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
@@ -62,75 +64,49 @@ implements
// no-op.
}
-
@Override
public void refineProgrammingModel(final ProgrammingModel
programmingModel) {
-
val shouldCheck =
getConfiguration().getCore().getMetaModel().getValidator().isExplicitLogicalTypeNames();
- if(!shouldCheck) {
- return;
- }
+ if(!shouldCheck) return;
programmingModel.addValidatorSkipManagedBeans(objectSpec-> {
-
- if(!check(objectSpec)) {
- return;
- }
+ if(skip(objectSpec)) return;
val logicalType = objectSpec.getLogicalType();
-
+
//XXX has a slight chance to be a false positive; would need to
check whether annotated with @Named
if(logicalType.getClassName().equals(logicalType.getLogicalTypeName())) {
- ValidationFailure.raiseFormatted(
- objectSpec,
- "%s: the object type must be specified explicitly
('%s' config property). "
- + "Defaulting the object type from the
package/class/package name can lead "
- + "to data migration issues for apps deployed
to production (if the class is "
- + "subsequently refactored). "
- + "Use @Discriminator, @Named or "
- + "@PersistenceCapable(schema=...) to specify
explicitly.",
- objectSpec.getFullIdentifier(),
-
"causeway.core.meta-model.validator.explicit-logical-type-names");
+ ValidationFailure.raise(objectSpec,
MessageTemplate.LOGICAL_TYPE_NAME_IS_NOT_EXPLICIT
+ .builder()
+ .addVariable("type", objectSpec.getFullIdentifier())
+ .addVariable("beanSort",
objectSpec.getBeanSort().name())
+ .addVariable("configProperty",
"causeway.core.meta-model.validator.explicit-logical-type-names")
+ .buildMessage());
}
-
- });
-
+ });
}
-
- public static boolean check(final ObjectSpecification objectSpec) {
- //TODO
- // as a special case, don't enforce this for fixture scripts...
- // we never invoke actions on fixture scripts anyway
-
- if(objectSpec.isAbstract()) {
- return false; //skip validation
- }
- if (objectSpec.isEntity()) {
- return true;
- }
+
+ // -- HELPER
+
+ private boolean skip(final ObjectSpecification objectSpec) {
+ if (objectSpec.isAbstract()
+ || objectSpec.isMixin()
+ || objectSpec.isValue()
+ || MmSpecUtils.isFixtureScript(objectSpec)) return true;
+ if (objectSpec.isEntity()) return false;
if (objectSpec.isViewModel()) {
- //final ViewModelFacet viewModelFacet =
objectSpec.getFacet(ViewModelFacet.class);
- // don't check JAXB DTOs
- final XmlType xmlType =
objectSpec.getCorrespondingClass().getAnnotation(XmlType.class);
- if(xmlType != null) {
- return false; //skip validation
- }
- return true;
- }
- if(objectSpec.isMixin()) {
- return false; //skip validation
+ // skip JAXB DTOs
+ return
objectSpec.getCorrespondingClass().getAnnotation(XmlType.class) != null;
}
if (objectSpec.isInjectable()) {
// only check if its a domain service (that is potentially
contributing to UI or Web-API(s).
- if(!objectSpec.isDomainService()) {
- return false; //skip validation
- }
+ if(!objectSpec.isDomainService()) return true;
- // don't check if domain service has only programmatic methods
- return
objectSpec.streamAnyActions(MixedIn.INCLUDED).findAny().isPresent();
+ // skip if domain service has only programmatic methods
+ return
objectSpec.streamAnyActions(MixedIn.INCLUDED).findAny().isEmpty();
}
- return false; //skip validation
+ return true; //skip validation
}
}
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmSpecUtils.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmSpecUtils.java
index 90e925594e..fd66476383 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmSpecUtils.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/object/MmSpecUtils.java
@@ -22,13 +22,19 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
+import org.springframework.lang.Nullable;
+
import org.apache.causeway.applib.id.LogicalType;
import org.apache.causeway.commons.collections.Can;
import org.apache.causeway.commons.internal.collections._Multimaps;
+import org.apache.causeway.commons.internal.context._Context;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
+import lombok.AccessLevel;
+import lombok.Getter;
import lombok.NonNull;
+import lombok.SneakyThrows;
import lombok.val;
import lombok.experimental.UtilityClass;
@@ -103,5 +109,25 @@ public final class MmSpecUtils {
return sb.toString();
}
+
+ /**
+ * Whether given {@link ObjectSpecification} represents a FixtureScript
(from testing.fixtures.applib).
+ */
+ public boolean isFixtureScript(final @Nullable ObjectSpecification spec) {
+ if(spec==null) return false;
+ return
getFixtureScriptClass().isAssignableFrom(spec.getCorrespondingClass());
+ }
+
+ // -- HELPER
+
+ @Getter(lazy = true, value = AccessLevel.PRIVATE)
+ private final Class<?> fixtureScriptClass = loadFixtureScriptClass();
+
+ @SneakyThrows
+ private Class<?> loadFixtureScriptClass() {
+ return _Context.loadClass(
+
"org.apache.causeway.testing.fixtures.applib.fixturescripts.FixtureScript");
+ }
+
}
\ No newline at end of file