diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-lineage/legend-engine-xt-analytics-lineage-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider b/legend-engine-xts-analytics/legend-engine-xts-analytics-lineage/legend-engine-xt-analytics-lineage-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider index 91ac69dcfc0..8ed7aa74ab8 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-lineage/legend-engine-xt-analytics-lineage-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-lineage/legend-engine-xt-analytics-lineage-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider @@ -14,52 +14,4 @@ # limitations under the License. # -# -# Copyright 2022 Goldman Sachs -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Copyright 2022 Goldman Sachs -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Copyright 2022 Goldman Sachs -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - org.finos.legend.pure.code.core.CoreExternalLineageAnalysisCodeRepositoryProvider \ No newline at end of file diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/pom.xml b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/pom.xml index 994a4f3d20b..5ed696a580a 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/pom.xml +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/pom.xml @@ -5,7 +5,7 @@ legend-engine org.finos.legend.engine - 4.37.4-SNAPSHOT + 4.39.1-SNAPSHOT ../../../pom.xml 4.0.0 @@ -17,36 +17,69 @@ swagger-annotations - io.swagger - swagger-annotations + com.fasterxml.jackson.core + jackson-annotations com.fasterxml.jackson.core jackson-databind + + org.pac4j.jax-rs + core + + + junit + junit + + + org.pac4j + pac4j-core + compile + + + org.eclipse.collections + eclipse-collections + + + org.eclipse.collections + eclipse-collections-api + + + javax.ws.rs + javax.ws.rs-api + + + org.finos.legend.pure - legend-pure-runtime-java-engine-interpreted + legend-pure-runtime-java-engine-compiled org.finos.legend.pure legend-pure-m3-core + + - javax.ws.rs - javax.ws.rs-api + org.finos.legend.engine + legend-engine-language-pure-modelManager - junit - junit + org.finos.legend.engine + legend-engine-shared-core org.finos.legend.engine - legend-engine-language-pure-compiler + legend-engine-language-pure-grammar org.finos.legend.engine - legend-engine-language-pure-modelManager + legend-engine-xt-analytics-quality-pure + + + org.finos.legend.engine + legend-engine-language-pure-compiler org.finos.legend.engine @@ -56,19 +89,38 @@ org.finos.legend.engine legend-engine-protocol-pure + + org.finos.legend.engine - legend-engine-shared-core + legend-engine-xt-data-space-grammar + test org.finos.legend.engine - legend-engine-xt-data-space-compiler + legend-engine-xt-data-space-pure-metamodel + test org.finos.legend.engine legend-engine-xt-data-space-protocol test + + org.finos.legend.engine + legend-engine-pure-platform-java + test + + + org.finos.legend.engine + legend-engine-xt-data-space-compiler + test + + + org.finos.legend.engine + legend-engine-pure-runtime-compiler + test + org.glassfish.jersey.core jersey-common diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalytics.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalytics.java index 14a34932886..71982d3ff45 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalytics.java +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalytics.java @@ -14,44 +14,33 @@ package org.finos.legend.engine.api.analytics; -import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.eclipse.collections.api.RichIterable; +import io.swagger.annotations.ApiParam; +import org.eclipse.collections.api.list.MutableList; import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; import org.finos.legend.engine.language.pure.modelManager.ModelManager; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement; -import org.finos.legend.engine.shared.core.ObjectMapperFactory; -import org.finos.legend.pure.generated.Root_meta_analytics_quality_model_CheckResult; -import org.finos.legend.pure.generated.Root_meta_pure_functions_collection_List_Impl; -import org.finos.legend.pure.generated.core_analytics_quality_associationChecks; -import org.finos.legend.pure.generated.core_analytics_quality_classChecks; -import org.finos.legend.pure.generated.core_analytics_quality_enumerationChecks; -import org.finos.legend.pure.generated.core_analytics_quality_functionChecks; -import org.finos.legend.pure.generated.core_analytics_quality_propertyChecks; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enum; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration; -import org.finos.legend.pure.runtime.java.compiled.execution.CompiledExecutionSupport; +import org.finos.legend.engine.shared.core.kerberos.ProfileManagerHelper; +import org.finos.legend.engine.shared.core.operational.http.InflateInterceptor; +import org.pac4j.core.profile.CommonProfile; +import org.pac4j.core.profile.ProfileManager; +import org.pac4j.jax.rs.annotations.Pac4JProfileManager; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; +import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; @Api(tags = "Analytics - Quality") @Path("pure/v1/analytics/quality") public class DataspaceQualityAnalytics { private final ModelManager modelManager; - private List messages; public DataspaceQualityAnalytics(ModelManager modelManager) { @@ -59,184 +48,17 @@ public DataspaceQualityAnalytics(ModelManager modelManager) } @POST - @Path("check") - @ApiOperation("Checks the quality of provided Data space") - @Consumes(MediaType.APPLICATION_JSON) - public Response checkDataSpaceConstraints(PureModelContextData pureModelContextData) + @Path("checkDataspaceQuality") + @ApiOperation("Checks the quality of provided Data space using PMCD") + @Consumes({MediaType.APPLICATION_JSON, InflateInterceptor.APPLICATION_ZLIB}) + @Produces(MediaType.APPLICATION_JSON) + public Response checkDataSpaceConstraints(DataspaceQualityCheckInput input, @ApiParam(hidden = true) + @Pac4JProfileManager ProfileManager pm) { - messages = new ArrayList<>(); - PureModel pureModel = this.modelManager.loadModel(pureModelContextData, null, null, null); - - List classes = pureModelContextData.getElements().stream().filter(e -> e instanceof org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class).collect(Collectors.toList()); - List associations = pureModelContextData.getElements().stream().filter(e -> e instanceof org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association).collect(Collectors.toList()); - List enumerations = pureModelContextData.getElements().stream().filter(e -> e instanceof org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration).collect(Collectors.toList()); - List functions = pureModelContextData.getElements().stream().filter(e -> e instanceof org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Function).collect(Collectors.toList()); - - CompiledExecutionSupport es = pureModel.getExecutionSupport(); - - if (classChecks(classes, pureModel, es) && associationChecks(associations, pureModel, es) && enumerationChecks(enumerations, pureModel, es) && functionChecks(functions, pureModel, es)) - { - return Response.ok().build(); - } - else - { - return Response.status(400).entity("Dataspace does not match the constraints - " + messages).build(); - } - } - - private boolean classChecks(List classes, PureModel pureModel, CompiledExecutionSupport es) - { - List classCheckResults = new ArrayList<>(); - boolean allPropertiesInClassAreValid = false; - for (PackageableElement pe : classes) - { - Class _class = pureModel.getContext().resolveClass(pe.getPath(), pe.sourceInformation); - allPropertiesInClassAreValid = propertyChecks(_class, es); - //create rules - core_analytics_quality_classChecks.Root_meta_analytics_quality_model_domain_classRules__Rule_MANY_(es); - - //run checks - RichIterable upperCase_class_1__checkResult_many_ = core_analytics_quality_classChecks.Root_meta_analytics_quality_model_domain_classNameShouldStartWithUpperCase_Class_1__CheckResult_MANY_(_class, es); - RichIterable entityNameShouldNotStartWithPackageName_class_1__checkResult_many_ = core_analytics_quality_classChecks.Root_meta_analytics_quality_model_domain_entityNameShouldNotStartWithPackageName_Class_1__CheckResult_MANY_(_class, es); - RichIterable classHasAtLeastOneMandatoryProperty_class_1__checkResult_many_ = core_analytics_quality_classChecks.Root_meta_analytics_quality_model_domain_classHasAtLeastOneMandatoryProperty_Class_1__CheckResult_MANY_(_class, es); - RichIterable allEntitiesAndPropertiesShouldHaveALongDescription_class_1__checkResult_many_ = core_analytics_quality_classChecks.Root_meta_analytics_quality_model_domain_allEntitiesAndPropertiesShouldHaveALongDescription_Class_1__CheckResult_MANY_(_class, es); - - upperCase_class_1__checkResult_many_.forEach(classCheckResults::add); - entityNameShouldNotStartWithPackageName_class_1__checkResult_many_.forEach(classCheckResults::add); - classHasAtLeastOneMandatoryProperty_class_1__checkResult_many_.forEach(classCheckResults::add); - allEntitiesAndPropertiesShouldHaveALongDescription_class_1__checkResult_many_.forEach(classCheckResults::add); - } - - return checkOverallResults(classCheckResults) && allPropertiesInClassAreValid; - } - - private boolean associationChecks(List associations, PureModel pureModel, CompiledExecutionSupport es) - { - List associationCheckResults = new ArrayList<>(); - for (PackageableElement pe : associations) - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association _association = pureModel.getContext().resolveAssociation(pe.getPath(), pe.sourceInformation); - - //create rules - core_analytics_quality_associationChecks.Root_meta_analytics_quality_model_domain_associationRules__Rule_MANY_(es); - - //run checks - RichIterable associationNameShouldStartWithUpperCase_association_1__checkResult_many_ = core_analytics_quality_associationChecks.Root_meta_analytics_quality_model_domain_associationNameShouldStartWithUpperCase_Association_1__CheckResult_MANY_(_association, es); - associationNameShouldStartWithUpperCase_association_1__checkResult_many_.forEach(associationCheckResults::add); - } - return checkOverallResults(associationCheckResults); - } - - private boolean enumerationChecks(List enumerations, PureModel pureModel, CompiledExecutionSupport es) - { - List enumerationCheckResults = new ArrayList<>(); - for (PackageableElement pe : enumerations) - { - Enumeration _enumeration = pureModel.getContext().resolveEnumeration(pe.getPath(), pe.sourceInformation); - - //create rules - core_analytics_quality_enumerationChecks.Root_meta_analytics_quality_model_domain_enumerationRules__Rule_MANY_(es); - - //run checks - RichIterable enumerationName_enumeration_1__checkResult_many_ = core_analytics_quality_enumerationChecks.Root_meta_analytics_quality_model_domain_enumerationName_Enumeration_1__CheckResult_MANY_(_enumeration, es); - RichIterable enumerationValue_enumeration_1__checkResult_many_ = core_analytics_quality_enumerationChecks.Root_meta_analytics_quality_model_domain_enumerationValue_Enumeration_1__CheckResult_MANY_(_enumeration, es); - - enumerationName_enumeration_1__checkResult_many_.forEach(enumerationCheckResults::add); - enumerationValue_enumeration_1__checkResult_many_.forEach(enumerationCheckResults::add); - } - return checkOverallResults(enumerationCheckResults); - } - - private boolean functionChecks(List functions, PureModel pureModel, CompiledExecutionSupport es) - { - List functionCheckResults = new ArrayList<>(); - - //create rules - core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_functionRules__Rule_MANY_(es); - - org.finos.legend.pure.m3.coreinstance.meta.pure.functions.collection.List> functionDefinitions = resolveConcreteFunctionDefinitions(functions, pureModel); - - //run checks - RichIterable> validEqualityComparisons_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_validEqualityComparisons_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> invalidContainsComparisons_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_invalidContainsComparisons_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> badInstanceOfChecks_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_badInstanceOfChecks_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> invalidMatchUsages_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_invalidMatchUsages_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> findUnnecessaryComparisonsToTrue_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findUnnecessaryComparisonsToTrue_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> findInvalidCastBugs_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findInvalidCastBugs_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable, ? extends org.finos.legend.pure.generated.Root_meta_analytics_quality_model_CheckResult>> findUnusedPrivateProtectedFunctionBugs_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findUnusedPrivateProtectedFunctionBugs_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> findUnnecessaryIfBugs_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findUnnecessaryIfBugs_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> findUnnecessaryIfBugs2_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findUnnecessaryIfBugs2_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> findUnnecessaryCasts_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findUnnecessaryCasts_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable, ? extends org.finos.legend.pure.generated.Root_meta_analytics_quality_model_CheckResult>> findUnnecessaryLetFunctionsCheck_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findUnnecessaryLetFunctionsCheck_List_1__Pair_MANY_(functionDefinitions, es); - RichIterable> findPotentiallyExpensiveAssertions_list_1__pair_many_ = core_analytics_quality_functionChecks.Root_meta_analytics_quality_model_domain_findPotentiallyExpensiveAssertions_List_1__Pair_MANY_(functionDefinitions, es); - - validEqualityComparisons_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - invalidContainsComparisons_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - badInstanceOfChecks_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - invalidMatchUsages_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findUnnecessaryComparisonsToTrue_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findInvalidCastBugs_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findUnusedPrivateProtectedFunctionBugs_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findUnnecessaryIfBugs_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findUnnecessaryIfBugs2_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findUnnecessaryCasts_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findUnnecessaryLetFunctionsCheck_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - findPotentiallyExpensiveAssertions_list_1__pair_many_.forEach(each -> functionCheckResults.add(each._second())); - - return checkOverallResults(functionCheckResults); - } - - private boolean propertyChecks(Class _class, CompiledExecutionSupport es) - { - ArrayList propertyCheckResults = new ArrayList<>(); - RichIterable> properties = _class._properties(); - for (Property property : properties) - { - //create rules - core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_propertyRules__Rule_MANY_(es); - - //run checks - RichIterable classPropertyShouldStartWithLowerLetter_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyShouldStartWithLowerLetter_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classPropertyShouldNotStartWithClassName_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyShouldNotStartWithClassName_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classBooleanPropertyShouldStartWithIsOrHasOrEndsWithFlag_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classBooleanPropertyShouldStartWithIsOrHasOrEndsWithFlag_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classPropertyStartingWithIsOrHasShouldBeBoolean_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyStartingWithIsOrHasShouldBeBoolean_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classPropertyEndingWithFlagShouldBeBoolean_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyEndingWithFlagShouldBeBoolean_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classPropertyWithToManyMultiplicityAreNamedCorrectly_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyWithToManyMultiplicityAreNamedCorrectly_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classPropertyWithToOneMultiplicityAreNamedCorrectly_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyWithToOneMultiplicityAreNamedCorrectly_AbstractProperty_1__CheckResult_MANY_(property, es); - RichIterable classPropertyIntegersWithToOneMultiplicityAreNamedCorrectly_abstractProperty_1__checkResult_many_ = core_analytics_quality_propertyChecks.Root_meta_analytics_quality_model_domain_classPropertyIntegersWithToOneMultiplicityAreNamedCorrectly_AbstractProperty_1__CheckResult_MANY_(property, es); - - classPropertyShouldStartWithLowerLetter_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classPropertyShouldNotStartWithClassName_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classBooleanPropertyShouldStartWithIsOrHasOrEndsWithFlag_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classPropertyStartingWithIsOrHasShouldBeBoolean_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classPropertyEndingWithFlagShouldBeBoolean_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classPropertyWithToManyMultiplicityAreNamedCorrectly_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classPropertyWithToOneMultiplicityAreNamedCorrectly_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - classPropertyIntegersWithToOneMultiplicityAreNamedCorrectly_abstractProperty_1__checkResult_many_.forEach(propertyCheckResults::add); - } - return checkOverallResults(propertyCheckResults); - } - - private boolean checkOverallResults(List results) - { - for (Root_meta_analytics_quality_model_CheckResult rs : results) - { - if (!rs._isValid()) - { - messages.add(rs._message()); - } - } - return messages.isEmpty(); - } - - private org.finos.legend.pure.m3.coreinstance.meta.pure.functions.collection.List> resolveConcreteFunctionDefinitions(List functions, PureModel pureModel) - { - - org.finos.legend.pure.m3.coreinstance.meta.pure.functions.collection.List> cfd = new Root_meta_pure_functions_collection_List_Impl<>(pureModel.getRoot()._name()); - for (PackageableElement pe : functions) - { - cfd._valuesAdd(pureModel.getConcreteFunctionDefinition(pe.getPath(), pe.sourceInformation)); - } - return cfd; + MutableList profiles = ProfileManagerHelper.extractProfiles(pm); + PureModelContextData pureModelContextData = this.modelManager.loadData(input.model, input.clientVersion, profiles); + PureModel pureModel = this.modelManager.loadModel(pureModelContextData, input.clientVersion, profiles, null); + List allElements = pureModelContextData.getElements(); + return DataspaceQualityAnalyticsHelper.getResponse(pureModel, allElements); } } diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsHelper.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsHelper.java new file mode 100644 index 00000000000..eaa22c885a6 --- /dev/null +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsHelper.java @@ -0,0 +1,71 @@ +// Copyright 2022 Goldman Sachs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.finos.legend.engine.api.analytics; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.impl.list.mutable.FastList; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; +import org.finos.legend.engine.protocol.pure.v1.PureProtocolObjectMapperFactory; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement; +import org.finos.legend.pure.generated.Root_meta_analytics_quality_model_ViolationInstance; +import org.finos.legend.pure.generated.core_analytics_quality_checksEngine; +import org.finos.legend.pure.runtime.java.compiled.execution.CompiledExecutionSupport; + +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.List; + + +public class DataspaceQualityAnalyticsHelper +{ + public static ObjectMapper getNewObjectMapper() + { + return PureProtocolObjectMapperFactory.getNewObjectMapper(); + } + + public static Response getResponse(PureModel pureModel, List allElements) + { + CompiledExecutionSupport es = pureModel.getExecutionSupport(); + + FastList _elements = FastList.newList(); + allElements.forEach(elem -> _elements.add(pureModel.getContext().resolvePackageableElement(elem.getPath(), elem.sourceInformation))); + RichIterable> result = core_analytics_quality_checksEngine.Root_meta_analytics_quality_model_domain_runQualityChecks_PackageableElement_MANY__ViolationInstance_MANY_(_elements, es); + + if (result.isEmpty()) + { + return Response.ok().build(); + } + ValidationResult validationResult = calculateValidationResult(result, allElements.size()); + return Response.ok().entity(validationResult).build(); + } + + private static ValidationResult calculateValidationResult(RichIterable> result, int elements) + { + List totalErrors = new ArrayList<>(); + for (Root_meta_analytics_quality_model_ViolationInstance violationInstance : result) + { + ValidationRuleResult validationRuleResult = new ValidationRuleResult( + violationInstance._detail()._isValid(), + violationInstance._source().toString(), + violationInstance._rule()._id(), + violationInstance._detail()._message(), + violationInstance._rule()._description()); + totalErrors.add(validationRuleResult); + } + int healthScore = ValidationResult.calculateHealthScore(result.size(), elements); + return new ValidationResult(totalErrors, healthScore); + } +} diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityCheckInput.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityCheckInput.java new file mode 100644 index 00000000000..d7689369b3b --- /dev/null +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/DataspaceQualityCheckInput.java @@ -0,0 +1,42 @@ +// Copyright 2022 Goldman Sachs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.finos.legend.engine.api.analytics; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContext; + +public class DataspaceQualityCheckInput +{ + @JsonProperty + public String clientVersion; + + @JsonProperty(required = true) + public String dataspace; + + @JsonProperty(required = true) + public PureModelContext model; + + @JsonCreator + public DataspaceQualityCheckInput( + @JsonProperty("clientVersion") String clientVersion, + @JsonProperty("dataSpace") String dataspace, + @JsonProperty("model") PureModelContext model) + { + this.clientVersion = clientVersion; + this.dataspace = dataspace; + this.model = model; + } +} diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/ValidationResult.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/ValidationResult.java new file mode 100644 index 00000000000..daf00f4be95 --- /dev/null +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/ValidationResult.java @@ -0,0 +1,49 @@ +// Copyright 2022 Goldman Sachs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.finos.legend.engine.api.analytics; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ValidationResult +{ + private List validationRuleResults; + private int healthScore; + + public ValidationResult(List validationRuleResults, int healthScore) + { + this.validationRuleResults = validationRuleResults; + this.healthScore = healthScore; + } + + public static int calculateHealthScore(int violations, int totalElements) + { + //TODO - weighted values to different constraints + int diff = totalElements - violations; + return (int) (Math.round((diff * 100.0 / totalElements)) / 10); + } + + public int getHealthScore() + { + return this.healthScore; + } + + public List getValidationRuleResultsList() + { + return this.validationRuleResults; + } +} diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/ValidationRuleResult.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/ValidationRuleResult.java new file mode 100644 index 00000000000..9e44428a94b --- /dev/null +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/main/java/org/finos/legend/engine/api/analytics/ValidationRuleResult.java @@ -0,0 +1,84 @@ +// Copyright 2022 Goldman Sachs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package org.finos.legend.engine.api.analytics; + +public class ValidationRuleResult +{ + private boolean ruleResult; + private String packageableElementName; + private String violationType; + private String errorMessage; + private String ruleDescription; + + public ValidationRuleResult(boolean ruleResult, String packageableElementName, String violationType, String errorMessage, String ruleDescription) + { + this.ruleResult = ruleResult; + this.packageableElementName = packageableElementName; + this.violationType = violationType; + this.errorMessage = errorMessage; + this.ruleDescription = ruleDescription; + } + + public void setRuleResult(boolean ruleResult) + { + this.ruleResult = ruleResult; + } + + public void setPackageableElementName(String packageableElementName) + { + this.packageableElementName = packageableElementName; + } + + public void setViolationType(String violationType) + { + this.violationType = violationType; + } + + public void setErrorMessage(String errorMessage) + { + this.errorMessage = errorMessage; + } + + public void setRuleDescription(String ruleDescription) + { + this.ruleDescription = ruleDescription; + } + + public boolean getRuleResult() + { + return this.ruleResult; + } + + public String getPackageableElementName() + { + return this.packageableElementName; + } + + public String getViolationType() + { + return this.violationType; + } + + public String getErrorMessage() + { + return this.errorMessage; + } + + public String getRuleDescription() + { + return this.ruleDescription; + } + +} diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/test/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsTest.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/test/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsTest.java index e97d681cd8c..36f550ab0d7 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/test/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsTest.java +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-api/src/test/java/org/finos/legend/engine/api/analytics/DataspaceQualityAnalyticsTest.java @@ -14,84 +14,730 @@ package org.finos.legend.engine.api.analytics; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.finos.legend.engine.language.pure.grammar.from.PureGrammarParser; import org.finos.legend.engine.language.pure.modelManager.ModelManager; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.dataSpace.DataSpace; -import org.finos.legend.engine.shared.core.ObjectMapperFactory; import org.finos.legend.engine.shared.core.deployment.DeploymentMode; import org.junit.Assert; import org.junit.Test; import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.Objects; +import java.util.ArrayList; +import java.util.List; public class DataspaceQualityAnalyticsTest { private final DataspaceQualityAnalytics api = new DataspaceQualityAnalytics(new ModelManager(DeploymentMode.TEST)); - private static final ObjectMapper objectMapper = ObjectMapperFactory.getNewStandardObjectMapperWithPureProtocolExtensionSupports(); + private static final String minimumPureClientVersion = "v1_20_0"; @Test - public void testValidCheckDataSpaceConstraints() throws IOException + public void testValidCheckDataSpaceConstraints() { - objectMapper.registerSubtypes(DataSpace.class); - PureModelContextData modelContextData = objectMapper.readValue(Objects.requireNonNull(getClass().getClassLoader().getResource("ValidDataspaceTestPMCD.json")), PureModelContextData.class); - Assert.assertEquals(Response.Status.OK.getStatusCode(), api.checkDataSpaceConstraints(modelContextData).getStatus()); + PureModelContextData modelData = PureGrammarParser.newInstance().parseModel(validDataspace); + Response response = api.checkDataSpaceConstraints(new DataspaceQualityCheckInput(minimumPureClientVersion, "model::NewDataSpace", modelData), null); + Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); } @Test - public void testDataspaceWithBadClasses() throws IOException + public void testDataspaceWithBadClasses() { - objectMapper.registerSubtypes(DataSpace.class); - PureModelContextData modelContextData = objectMapper.readValue(Objects.requireNonNull(getClass().getClassLoader().getResource("InvalidClassesPMCD.json")), PureModelContextData.class); - Response response = api.checkDataSpaceConstraints(modelContextData); - Assert.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); - String message = "Dataspace does not match the constraints - [Class name (targetCompany) does not match required standards: should start with upper case, Provide documentation for class and its properties targetCompany]"; - Assert.assertEquals(message, response.getEntity()); + PureModelContextData modelData = PureGrammarParser.newInstance().parseModel(dataSpaceWithBadClasses); + Response response = api.checkDataSpaceConstraints(new DataspaceQualityCheckInput(minimumPureClientVersion, "model::NewDataSpace", modelData), null); + Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + ValidationRuleResult targetCompany = new ValidationRuleResult( + false, + "targetCompany", + "Invalid Class Names", + "Class name (targetCompany) does not match required standards: should start with upper case", + "Class name should start with Upper case" + ); + ValidationRuleResult targetPerson = new ValidationRuleResult( + false, + "TargetPerson", + "Documentation not provided for entity and/or its properties", + "Provide documentation for class TargetPerson and its properties", + "All entities and properties must have a long description." + ); + List message = new ArrayList<>(); + message.add(targetCompany); + message.add(targetPerson); + ValidationResult expectedValidationResult = new ValidationResult(message, 8); + ValidationResult actualValidationResult = (ValidationResult) response.getEntity(); + Assert.assertEquals(expectedValidationResult.getHealthScore(), actualValidationResult.getHealthScore()); } @Test - public void testDataspaceWithBadAssociations() throws IOException + public void testDataspaceWithBadAssociations() { - objectMapper.registerSubtypes(DataSpace.class); - PureModelContextData modelContextData = objectMapper.readValue(Objects.requireNonNull(getClass().getClassLoader().getResource("InvalidAssociationsPMCD.json")), PureModelContextData.class); - Response response = api.checkDataSpaceConstraints(modelContextData); - Assert.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); - String message = "Dataspace does not match the constraints - [Check name of association targetCompany_TargetPerson]"; - Assert.assertEquals(message, response.getEntity()); + PureModelContextData modelData = PureGrammarParser.newInstance().parseModel(dataspaceWithBadAssociation); + Response response = api.checkDataSpaceConstraints(new DataspaceQualityCheckInput(minimumPureClientVersion, "model::NewDataSpace", modelData), null); + Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + List message = new ArrayList<>(); + ValidationRuleResult targetCompany = new ValidationRuleResult( + false, + "targetCompany_TargetPerson", + "Invalid Association Name", + "Association (targetCompany_TargetPerson) does not match required standards: Camel case must be used Association name and should be upper camel case, with an underscore between both sides of the join", + "Camel case must be used Association name and should be upper camel case, with an underscore between both sides of the join." + ); + + message.add(targetCompany); + ValidationResult expectedValidationResult = new ValidationResult(message, 9); + ValidationResult actualValidationResult = (ValidationResult) response.getEntity(); + Assert.assertEquals(expectedValidationResult.getHealthScore(), actualValidationResult.getHealthScore()); } @Test - public void testDataspaceWithBadEnumerations() throws IOException + public void testDataspaceWithBadEnumerations() { - objectMapper.registerSubtypes(DataSpace.class); - PureModelContextData modelContextData = objectMapper.readValue(Objects.requireNonNull(getClass().getClassLoader().getResource("InvalidEnumerationsPMCD.json")), PureModelContextData.class); - Response response = api.checkDataSpaceConstraints(modelContextData); - Assert.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); - String message = "Dataspace does not match the constraints - [Enumeration name (enum_TestForMyDataspace) does not match required standards: should start with upper case;should not contain '_', Enumeration name (enum_TestForMyDataspace) does not match required standards: should not contain '_';should start with upper case]"; - Assert.assertEquals(message, response.getEntity()); + PureModelContextData modelData = PureGrammarParser.newInstance().parseModel(dataspaceWithBadEnum); + Response response = api.checkDataSpaceConstraints(new DataspaceQualityCheckInput(minimumPureClientVersion, "model::NewDataSpace", modelData), null); + Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + List message = new ArrayList<>(); + + ValidationRuleResult e = new ValidationRuleResult( + false, + "testEnum_ForMyDataspace", + "Invalid Enumeration Names", + "Enumeration name (testEnum_ForMyDataspace) does not match required standards: should start with upper case;should not contain '_';should not contain 'Enum'", + "Enum name should start with Upper case, not contain underscores or the word Enum" + ); + message.add(e); + ValidationResult expectedValidationResult = new ValidationResult(message, 9); + ValidationResult actualValidationResult = (ValidationResult) response.getEntity(); + Assert.assertEquals(expectedValidationResult.getHealthScore(), actualValidationResult.getHealthScore()); } @Test - public void testDataspaceWithBadFunctions() throws IOException + public void testDataspaceWithBadFunctions() { - objectMapper.registerSubtypes(DataSpace.class); - PureModelContextData modelContextData = objectMapper.readValue(Objects.requireNonNull(getClass().getClassLoader().getResource("InvalidFunctionsPMCD.json")), PureModelContextData.class); - Response response = api.checkDataSpaceConstraints(modelContextData); - Assert.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); - String message = "Dataspace does not match the constraints - [Possible invalid equal check (type mismatch, String vs Integer)]"; - Assert.assertEquals(message, response.getEntity()); + PureModelContextData modelData = PureGrammarParser.newInstance().parseModel(dataspaceWithBadFunction); + Response response = api.checkDataSpaceConstraints(new DataspaceQualityCheckInput(minimumPureClientVersion, "model::NewDataSpace", modelData), null); + Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + List message = new ArrayList<>(); + ValidationRuleResult fn = new ValidationRuleResult( + false, + "", + "Invalid Equality", + "Function (equal) does not match required standards: Possible invalid equal check (type mismatch, Integer vs String)", + "Check for equality checks that will always result in false due to type mismatches (e.g. \\'abc\\' == 123)" + ); + message.add(fn); + + ValidationRuleResult fn2 = new ValidationRuleResult( + false, + "", + "Invalid Contains", + "Possible invalid contains check (type mismatch, Integer vs String)", + "Check for contains / containsAll / containsAny checks that will always result in false due to type mismatches (e.g. [\\'abc\\']->contains(123))" + ); + message.add(fn2); + ValidationResult expectedValidationResult = new ValidationResult(message, 8); + ValidationResult actualValidationResult = (ValidationResult) response.getEntity(); + Assert.assertEquals(expectedValidationResult.getHealthScore(), actualValidationResult.getHealthScore()); } @Test - public void testDataspaceWithBadClassProperties() throws IOException + public void testDataspaceWithBadClassProperties() { - objectMapper.registerSubtypes(DataSpace.class); - PureModelContextData modelContextData = objectMapper.readValue(Objects.requireNonNull(getClass().getClassLoader().getResource("InvalidClassPropertiesPMCD.json")), PureModelContextData.class); - Response response = api.checkDataSpaceConstraints(modelContextData); - Assert.assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus()); - String message = "Dataspace does not match the constraints - [Property name (TargetCompanyObject) does not match required standards: should start with lower case, Property name (id_TargetCompany) does not match required standards: should not contain '_']"; - Assert.assertEquals(message, response.getEntity()); + PureModelContextData modelData = PureGrammarParser.newInstance().parseModel(dataspaceWithBadClassProperties); + Response response = api.checkDataSpaceConstraints(new DataspaceQualityCheckInput(minimumPureClientVersion, "model::NewDataSpace", modelData), null); + Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + + List message = new ArrayList<>(); + ValidationRuleResult prop = new ValidationRuleResult( + false, + "id_TargetCompany", + "Invalid Property Names", + "Property name (id_TargetCompany) does not match required standards: should not contain '_'", + "Property name should start with lower letter and in camelCase" + ); + + ValidationRuleResult prop2 = new ValidationRuleResult( + false, + "Name", + "Invalid Property Names", + "Property name (Name) does not match required standards: should start with lower case", + "Property name should start with lower letter and in camelCase" + ); + + message.add(prop); + message.add(prop2); + ValidationResult expectedValidationResult = new ValidationResult(message, 8); + ValidationResult actualValidationResult = (ValidationResult) response.getEntity(); + Assert.assertEquals(expectedValidationResult.getHealthScore(), actualValidationResult.getHealthScore()); } + + private final String validDataspace = "###DataSpace\n" + + "DataSpace model::NewDataSpace\n" + + "{\n" + + " executionContexts:\n" + + " [\n" + + " {\n" + + " name: 'Some Context';\n" + + " title: 'New Execution Context';\n" + + " description: 'some information about the execution context';\n" + + " mapping: model::dummyMapping;\n" + + " defaultRuntime: model::dummyRuntime;\n" + + " }\n" + + " ];\n" + + " defaultExecutionContext: 'Some Context';\n" + + " elements:\n" + + " [\n" + + " model::Doc,\n" + + " model::TargetCompany,\n" + + " model::TargetPerson,\n" + + " pure::TargetCompany_TargetPerson,\n" + + " pure::TestForMyDataspace\n" + + " ];\n" + + "}\n" + + "\n" + + "\n" + + "###Pure\n" + + "Enum {meta::pure::profiles::doc.doc = 'test enum for my dataspace'} pure::TestForMyDataspace\n" + + "{\n" + + " Value1,\n" + + " Value2\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'documentation for this class'} model::Doc\n" + + "{\n" + + " {meta::pure::profiles::doc.doc = 'target company object'} targetCompanyObject: model::TargetCompany[1];\n" + + " {meta::pure::profiles::doc.doc = 'target person object'} targetPersonObject: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'company object'} model::TargetCompany\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'company id'} id: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'company name'} name: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'company address'} addressId: Integer[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'person object'} model::TargetPerson\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'legal name'} legalName: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s age'} age: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s address'} addressId: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'decimal value'} dec: Decimal[0..1];\n" + + "}\n" + + "\n" + + "Association pure::TargetCompany_TargetPerson\n" + + "{\n" + + " prop1: model::TargetCompany[1];\n" + + " prop2: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "function pure::ThisIsMyFunction(): String[1]\n" + + "{\n" + + " 'test'\n" + + "}\n" + + "\n" + + "function pure::EqualityFunction(): Boolean[1]\n" + + "{\n" + + " 'abc' == 'abc'\n" + + "}\n" + + "\n" + + "function pure::ComparisonFunction(): Boolean[1]\n" + + "{\n" + + " 'a'->in(\n" + + " [\n" + + " 'a',\n" + + " 'c',\n" + + " 'c'\n" + + " ]\n" + + " )\n" + + "}\n" + + "\n" + + "\n" + + "###Mapping\n" + + "Mapping model::dummyMapping\n" + + "(\n" + + ")\n" + + "\n" + + "\n" + + "###Runtime\n" + + "Runtime model::dummyRuntime\n" + + "{\n" + + " mappings:\n" + + " [\n" + + " model::dummyMapping\n" + + " ];\n" + + "}\n"; + + private final String dataSpaceWithBadClasses = "###DataSpace\n" + + "DataSpace model::NewDataSpace\n" + + "{\n" + + " executionContexts:\n" + + " [\n" + + " {\n" + + " name: 'Some Context';\n" + + " title: 'New Execution Context';\n" + + " description: 'some information about the execution context';\n" + + " mapping: model::dummyMapping;\n" + + " defaultRuntime: model::dummyRuntime;\n" + + " }\n" + + " ];\n" + + " defaultExecutionContext: 'Some Context';\n" + + " elements:\n" + + " [\n" + + " model::Doc,\n" + + " model::targetCompany,\n" + + " model::TargetPerson,\n" + + " model::TargetCompany_TargetPerson,\n" + + " model::TestForMyDataspace\n" + + " ];\n" + + "}\n" + + "\n" + + "\n" + + "###Pure\n" + + "Enum {meta::pure::profiles::doc.doc = 'test enum for my dataspace'} model::TestForMyDataspace\n" + + "{\n" + + " Value1,\n" + + " Value2\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'documentation for this class'} model::Doc\n" + + "{\n" + + " {meta::pure::profiles::doc.doc = 'target company object'} targetCompanyObject: model::targetCompany[1];\n" + + " {meta::pure::profiles::doc.doc = 'target person object'} targetPersonObject: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'company object'} model::targetCompany\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'company id'} id: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'company name'} name: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'company address'} addressId: Integer[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'person object'} model::TargetPerson\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'legal name'} legalName: String[1];\n" + + " age: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s address'} addressId: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'decimal value'} dec: Decimal[0..1];\n" + + "}\n" + + "\n" + + "Association model::TargetCompany_TargetPerson\n" + + "{\n" + + " prop1: model::targetCompany[1];\n" + + " prop2: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "function pure::ThisIsMyFunction(): String[1]\n" + + "{\n" + + " 'test'\n" + + "}\n" + + "\n" + + "function pure::EqualityFunction(): Boolean[1]\n" + + "{\n" + + " 'abc' == 'abc'\n" + + "}\n" + + "\n" + + "function pure::ComparisonFunction(): Boolean[1]\n" + + "{\n" + + " 'a'->in(\n" + + " [\n" + + " 'a',\n" + + " 'c',\n" + + " 'c'\n" + + " ]\n" + + " )\n" + + "}\n" + + "\n" + + "\n" + + "###Mapping\n" + + "Mapping model::dummyMapping\n" + + "(\n" + + ")\n" + + "\n" + + "\n" + + "###Runtime\n" + + "Runtime model::dummyRuntime\n" + + "{\n" + + " mappings:\n" + + " [\n" + + " model::dummyMapping\n" + + " ];\n" + + "}\n"; + + private final String dataspaceWithBadAssociation = "###DataSpace\n" + + "DataSpace model::NewDataSpace\n" + + "{\n" + + " executionContexts:\n" + + " [\n" + + " {\n" + + " name: 'Some Context';\n" + + " title: 'New Execution Context';\n" + + " description: 'some information about the execution context';\n" + + " mapping: model::dummyMapping;\n" + + " defaultRuntime: model::dummyRuntime;\n" + + " }\n" + + " ];\n" + + " defaultExecutionContext: 'Some Context';\n" + + " elements:\n" + + " [\n" + + " model::Doc,\n" + + " model::TargetCompany,\n" + + " model::TargetPerson,\n" + + " pure::targetCompany_TargetPerson,\n" + + " pure::TestForMyDataspace\n" + + " ];\n" + + "}\n" + + "\n" + + "\n" + + "###Pure\n" + + "Enum {meta::pure::profiles::doc.doc = 'test enum for my dataspace'} pure::TestForMyDataspace\n" + + "{\n" + + " Value1,\n" + + " Value2\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'documentation for this class'} model::Doc\n" + + "{\n" + + " {meta::pure::profiles::doc.doc = 'target company object'} targetCompanyObject: model::TargetCompany[1];\n" + + " {meta::pure::profiles::doc.doc = 'target person object'} targetPersonObject: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'company object'} model::TargetCompany\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'company id'} id: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'company name'} name: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'company address'} addressId: Integer[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'person object'} model::TargetPerson\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'legal name'} legalName: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s age'} age: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s address'} addressId: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'decimal value'} dec: Decimal[0..1];\n" + + "}\n" + + "\n" + + "Association pure::targetCompany_TargetPerson\n" + + "{\n" + + " prop1: model::TargetCompany[1];\n" + + " prop2: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "function pure::ThisIsMyFunction(): String[1]\n" + + "{\n" + + " 'test'\n" + + "}\n" + + "\n" + + "function pure::EqualityFunction(): Boolean[1]\n" + + "{\n" + + " 'abc' == 'abc'\n" + + "}\n" + + "\n" + + "function pure::ComparisonFunction(): Boolean[1]\n" + + "{\n" + + " 'a'->in(\n" + + " [\n" + + " 'a',\n" + + " 'c',\n" + + " 'c'\n" + + " ]\n" + + " )\n" + + "}\n" + + "\n" + + "\n" + + "###Mapping\n" + + "Mapping model::dummyMapping\n" + + "(\n" + + ")\n" + + "\n" + + "\n" + + "###Runtime\n" + + "Runtime model::dummyRuntime\n" + + "{\n" + + " mappings:\n" + + " [\n" + + " model::dummyMapping\n" + + " ];\n" + + "}\n"; + + private final String dataspaceWithBadEnum = "###DataSpace\n" + + "DataSpace model::NewDataSpace\n" + + "{\n" + + " executionContexts:\n" + + " [\n" + + " {\n" + + " name: 'Some Context';\n" + + " title: 'New Execution Context';\n" + + " description: 'some information about the execution context';\n" + + " mapping: model::dummyMapping;\n" + + " defaultRuntime: model::dummyRuntime;\n" + + " }\n" + + " ];\n" + + " defaultExecutionContext: 'Some Context';\n" + + " elements:\n" + + " [\n" + + " model::Doc,\n" + + " model::TargetCompany,\n" + + " model::TargetPerson,\n" + + " pure::TargetCompany_TargetPerson,\n" + + " pure::testEnum_ForMyDataspace\n" + + " ];\n" + + "}\n" + + "\n" + + "\n" + + "###Pure\n" + + "Enum {meta::pure::profiles::doc.doc = 'test enum for my dataspace'} pure::testEnum_ForMyDataspace\n" + + "{\n" + + " Value1,\n" + + " Value2\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'documentation for this class'} model::Doc\n" + + "{\n" + + " {meta::pure::profiles::doc.doc = 'target company object'} targetCompanyObject: model::TargetCompany[1];\n" + + " {meta::pure::profiles::doc.doc = 'target person object'} targetPersonObject: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'company object'} model::TargetCompany\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'company id'} id: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'company name'} name: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'company address'} addressId: Integer[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'person object'} model::TargetPerson\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'legal name'} legalName: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s age'} age: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s address'} addressId: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'decimal value'} dec: Decimal[0..1];\n" + + "}\n" + + "\n" + + "Association pure::TargetCompany_TargetPerson\n" + + "{\n" + + " prop1: model::TargetCompany[1];\n" + + " prop2: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "function pure::ThisIsMyFunction(): String[1]\n" + + "{\n" + + " 'test'\n" + + "}\n" + + "\n" + + "function pure::EqualityFunction(): Boolean[1]\n" + + "{\n" + + " 'abc' == 'abc'\n" + + "}\n" + + "\n" + + "function pure::ComparisonFunction(): Boolean[1]\n" + + "{\n" + + " 'a'->in(\n" + + " [\n" + + " 'a',\n" + + " 'c',\n" + + " 'c'\n" + + " ]\n" + + " )\n" + + "}\n" + + "\n" + + "\n" + + "###Mapping\n" + + "Mapping model::dummyMapping\n" + + "(\n" + + ")\n" + + "\n" + + "\n" + + "###Runtime\n" + + "Runtime model::dummyRuntime\n" + + "{\n" + + " mappings:\n" + + " [\n" + + " model::dummyMapping\n" + + " ];\n" + + "}\n"; + + private final String dataspaceWithBadFunction = "###DataSpace\n" + + "DataSpace model::NewDataSpace\n" + + "{\n" + + " executionContexts:\n" + + " [\n" + + " {\n" + + " name: 'Some Context';\n" + + " title: 'New Execution Context';\n" + + " description: 'some information about the execution context';\n" + + " mapping: model::dummyMapping;\n" + + " defaultRuntime: model::dummyRuntime;\n" + + " }\n" + + " ];\n" + + " defaultExecutionContext: 'Some Context';\n" + + " elements:\n" + + " [\n" + + " model::Doc,\n" + + " model::TargetCompany,\n" + + " model::TargetPerson,\n" + + " pure::TargetCompany_TargetPerson,\n" + + " pure::TestForMyDataspace\n" + + " ];\n" + + "}\n" + + "\n" + + "\n" + + "###Pure\n" + + "Enum {meta::pure::profiles::doc.doc = 'test enum for my dataspace'} pure::TestForMyDataspace\n" + + "{\n" + + " Value1,\n" + + " Value2\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'documentation for this class'} model::Doc\n" + + "{\n" + + " {meta::pure::profiles::doc.doc = 'target company object'} targetCompanyObject: model::TargetCompany[1];\n" + + " {meta::pure::profiles::doc.doc = 'target person object'} targetPersonObject: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'company object'} model::TargetCompany\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'company id'} id: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'company name'} name: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'company address'} addressId: Integer[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'person object'} model::TargetPerson\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'legal name'} legalName: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s age'} age: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s address'} addressId: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'decimal value'} dec: Decimal[0..1];\n" + + "}\n" + + "\n" + + "Association pure::TargetCompany_TargetPerson\n" + + "{\n" + + " prop1: model::TargetCompany[1];\n" + + " prop2: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "function pure::ThisIsMyFunction(): String[1]\n" + + "{\n" + + " 'test'\n" + + "}\n" + + "\n" + + "function pure::EqualityFunction(): Boolean[1]\n" + + "{\n" + + " 123 == 'abc'\n" + + "}\n" + + "\n" + + "function pure::InvalidContainsFunction(): Boolean[1]\n" + + "{\n" + + " [1,2,3,4]->contains('hello');\n" + + "}\n" + + "\n" + + "###Mapping\n" + + "Mapping model::dummyMapping\n" + + "(\n" + + ")\n" + + "\n" + + "\n" + + "###Runtime\n" + + "Runtime model::dummyRuntime\n" + + "{\n" + + " mappings:\n" + + " [\n" + + " model::dummyMapping\n" + + " ];\n" + + "}\n"; + + private final String dataspaceWithBadClassProperties = "###DataSpace\n" + + "DataSpace model::NewDataSpace\n" + + "{\n" + + " executionContexts:\n" + + " [\n" + + " {\n" + + " name: 'Some Context';\n" + + " title: 'New Execution Context';\n" + + " description: 'some information about the execution context';\n" + + " mapping: model::dummyMapping;\n" + + " defaultRuntime: model::dummyRuntime;\n" + + " }\n" + + " ];\n" + + " defaultExecutionContext: 'Some Context';\n" + + " elements:\n" + + " [\n" + + " model::Doc,\n" + + " model::TargetCompany,\n" + + " model::TargetPerson,\n" + + " pure::TargetCompany_TargetPerson,\n" + + " pure::TestForMyDataspace\n" + + " ];\n" + + "}\n" + + "\n" + + "\n" + + "###Pure\n" + + "Enum {meta::pure::profiles::doc.doc = 'test enum for my dataspace'} pure::TestForMyDataspace\n" + + "{\n" + + " Value1,\n" + + " Value2\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'documentation for this class'} model::Doc\n" + + "{\n" + + " {meta::pure::profiles::doc.doc = 'target company object'} targetCompanyObject: model::TargetCompany[1];\n" + + " {meta::pure::profiles::doc.doc = 'target person object'} targetPersonObject: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'company object'} model::TargetCompany\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'company id'} id_TargetCompany: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'company name'} Name: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'company address'} addressId: Integer[1];\n" + + "}\n" + + "\n" + + "Class {meta::pure::profiles::doc.doc = 'person object'} model::TargetPerson\n" + + "{\n" + + " <> {meta::pure::profiles::doc.doc = 'legal name'} legalName: String[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s age'} age: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'person\\'s address'} addressId: Integer[1];\n" + + " {meta::pure::profiles::doc.doc = 'decimal value'} dec: Decimal[0..1];\n" + + "}\n" + + "\n" + + "Association pure::TargetCompany_TargetPerson\n" + + "{\n" + + " prop1: model::TargetCompany[1];\n" + + " prop2: model::TargetPerson[1];\n" + + "}\n" + + "\n" + + "function pure::ThisIsMyFunction(): String[1]\n" + + "{\n" + + " 'test'\n" + + "}\n" + + "\n" + + "function pure::EqualityFunction(): Boolean[1]\n" + + "{\n" + + " 'abc' == 'abc'\n" + + "}\n" + + "\n" + + "function pure::ComparisonFunction(): Boolean[1]\n" + + "{\n" + + " 'a'->in(\n" + + " [\n" + + " 'a',\n" + + " 'c',\n" + + " 'c'\n" + + " ]\n" + + " )\n" + + "}\n" + + "\n" + + "\n" + + "###Mapping\n" + + "Mapping model::dummyMapping\n" + + "(\n" + + ")\n" + + "\n" + + "\n" + + "###Runtime\n" + + "Runtime model::dummyRuntime\n" + + "{\n" + + " mappings:\n" + + " [\n" + + " model::dummyMapping\n" + + " ];\n" + + "}\n"; } diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/pom.xml b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/pom.xml index 87f812f9a5c..1de89e7836b 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/pom.xml +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/pom.xml @@ -29,6 +29,8 @@ core core_relational core_analytics_quality + core_external_compiler + core_data_space_metamodel ${project.basedir}/src/main/resources/core_analytics_quality.definition.json @@ -36,7 +38,7 @@ - compile + generate-sources build-pure-jar @@ -68,7 +70,11 @@ legend-pure-m2-store-relational-grammar ${legend.pure.version} - + + org.finos.legend.pure + legend-pure-m3-core + ${legend.pure.version} + org.finos.legend.engine legend-engine-pure-code-compiled-core @@ -79,6 +85,11 @@ legend-engine-xt-relationalStore-pure ${project.version} + + org.finos.legend.engine + legend-engine-pure-runtime-compiler + ${project.version} + @@ -116,6 +127,16 @@ legend-pure-m2-dsl-graph-grammar ${legend.pure.version} + + org.finos.legend.pure + legend-pure-m3-core + ${legend.pure.version} + + + org.finos.legend.pure + legend-pure-m3-core + ${legend.pure.version} + org.finos.legend.pure legend-pure-m2-dsl-path-grammar @@ -131,7 +152,11 @@ legend-pure-m2-store-relational-grammar ${legend.pure.version} - + + org.finos.legend.pure + legend-pure-m3-core + ${legend.pure.version} + org.finos.legend.engine legend-engine-pure-code-compiled-core @@ -142,6 +167,11 @@ legend-engine-xt-relationalStore-pure ${project.version} + + org.finos.legend.engine + legend-engine-pure-runtime-compiler + ${project.version} + diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/java/org/finos/legend/pure/code/core/CoreExternalLineageAnalysisCodeRepositoryProvider.java b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/java/org/finos/legend/pure/code/core/CoreQualityAnalysisCodeRepositoryProvider.java similarity index 91% rename from legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/java/org/finos/legend/pure/code/core/CoreExternalLineageAnalysisCodeRepositoryProvider.java rename to legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/java/org/finos/legend/pure/code/core/CoreQualityAnalysisCodeRepositoryProvider.java index 06fcb194e3b..5a9e7e82143 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/java/org/finos/legend/pure/code/core/CoreExternalLineageAnalysisCodeRepositoryProvider.java +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/java/org/finos/legend/pure/code/core/CoreQualityAnalysisCodeRepositoryProvider.java @@ -20,7 +20,7 @@ import org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider; import org.finos.legend.pure.m3.serialization.filesystem.repository.GenericCodeRepository; -public class CoreExternalLineageAnalysisCodeRepositoryProvider implements CodeRepositoryProvider +public class CoreQualityAnalysisCodeRepositoryProvider implements CodeRepositoryProvider { @Override public CodeRepository repository() diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider index 91ac69dcfc0..1c8274f3cde 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/META-INF/services/org.finos.legend.pure.m3.serialization.filesystem.repository.CodeRepositoryProvider @@ -14,52 +14,4 @@ # limitations under the License. # -# -# Copyright 2022 Goldman Sachs -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Copyright 2022 Goldman Sachs -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# Copyright 2022 Goldman Sachs -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -org.finos.legend.pure.code.core.CoreExternalLineageAnalysisCodeRepositoryProvider \ No newline at end of file +org.finos.legend.pure.code.core.CoreQualityAnalysisCodeRepositoryProvider \ No newline at end of file diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality.definition.json b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality.definition.json index bf56d08f3f2..14ca97c654c 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality.definition.json +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality.definition.json @@ -9,6 +9,8 @@ "platform_store_relational", "platform_functions_json", "core_functions", - "core" + "core", + "core_external_compiler", + "core_data_space_metamodel" ] } \ No newline at end of file diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/associationChecks.pure b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/associationChecks.pure index a1fed8f7937..fad78feb547 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/associationChecks.pure +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/associationChecks.pure @@ -25,7 +25,6 @@ meta::analytics::quality::model::domain::associationNameShouldStartWithUpperCase let passed = size($tokens) == 2 && $tokens->at(0)->meta::pure::functions::string::substring(0,1) ->isUpperCase() && $tokens->at(1)->meta::pure::functions::string::substring(0,1) ->isUpperCase(); - let message ='Check name of association ' + $a.name->toOne() ; - + let message ='Association (' + $a.name->toOne() + ') does not match required standards: Camel case must be used Association name and should be upper camel case, with an underscore between both sides of the join'; ^CheckResult(isValid=$passed, message=$message); } \ No newline at end of file diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/checksEngine.pure b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/checksEngine.pure index 3b3de6f561e..0aedabd1ff6 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/checksEngine.pure +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/checksEngine.pure @@ -1,6 +1,9 @@ import meta::analytics::quality::model::*; import meta::analytics::quality::model::domain::*; import meta::relational::tests::*; +import meta::pure::runtime::*; + + Enum meta::analytics::quality::model::Severity { High, Medium, Low diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/classChecks.pure b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/classChecks.pure index ab1caba18c2..178e4ebe667 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/classChecks.pure +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/classChecks.pure @@ -77,8 +77,7 @@ meta::analytics::quality::model::domain::allEntitiesAndPropertiesShouldHaveALong { let passed = ($cl.taggedValues->size() != 0 && $cl.taggedValues->filter(t | $t.tag.profile == doc)->size() != 0) && $cl.properties->size() == $cl.properties->map(p|$p.taggedValues)-> filter(t | $t.tag.profile == doc)->size(); - - let message ='Provide documentation for class and its properties ' + $cl.name->toOne() ; + let message ='Provide documentation for class ' + + $cl.name->toOne() + ' and its properties'; ^CheckResult(isValid=$passed, message=$message); } \ No newline at end of file diff --git a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/functionChecks.pure b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/functionChecks.pure index aabd6f182df..512e37ed39b 100644 --- a/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/functionChecks.pure +++ b/legend-engine-xts-analytics/legend-engine-xts-analytics-quality/legend-engine-xt-analytics-quality-pure/src/main/resources/core_analytics_quality/functionChecks.pure @@ -58,7 +58,7 @@ function <> meta::analytics::quality::model::domain::getLocalFunc } function {rule.rule = 'Invalid Contains', - rule.description ='Check for contains / containsAll / containsAny checks that will always result in false due to type miss matches (e.g. [\'abc\']->contains(123))', + rule.description ='Check for contains / containsAll / containsAny checks that will always result in false due to type mismatches (e.g. [\'abc\']->contains(123))', rule.severity = 'High', rule.category = 'Correctness'} meta::analytics::quality::model::domain::invalidContainsComparisons(fns:List>[1]) : Pair[*] @@ -69,7 +69,7 @@ meta::analytics::quality::model::domain::invalidContainsComparisons(fns:Listmap(ie| let t1 = $ie->meta::analytics::quality::model::domain::resolveParameterType(0); let t2 = $ie->meta::analytics::quality::model::domain::resolveParameterType(1); - let message = ('Possible invalid ' + $ie.functionName->makeString() + ' check (type miss match, ' + $t1->elementToPath() + ' vs ' + $t2->elementToPath() + ')'); + let message = ('Possible invalid ' + $ie.functionName->makeString() + ' check (type mismatch, ' + $t1->elementToPath() + ' vs ' + $t2->elementToPath() + ')'); let result = ^CheckResult(isValid=false,message=$message); pair($ie,$result); ); @@ -77,7 +77,7 @@ meta::analytics::quality::model::domain::invalidContainsComparisons(fns:List>[1]) : Pair[*] @@ -98,7 +98,7 @@ meta::analytics::quality::model::domain::validEqualityComparisons(fns:ListtoOne() + ' check (' + $t1->elementToPath() + ' vs ' + $t2->elementToPath() + ')', - |'Possible invalid ' + $ie.functionName->toOne() + ' check (type mismatch, ' + $t1->elementToPath() + ' vs ' + $t2->elementToPath() + ')'); + | 'Function (' + $ie.functionName->toOne() + ') does not match required standards: Possible invalid ' + $ie.functionName->toOne() + ' check (type mismatch, ' + $t1->elementToPath() + ' vs ' + $t2->elementToPath() + ')'); let result = ^CheckResult(isValid=$valid, message=$message); pair($ie, $result); );