From 3d09b5a9cb8007cc71ed0a4796b7b5de4732d422 Mon Sep 17 00:00:00 2001 From: "Kim, Jake" Date: Thu, 24 Oct 2024 14:30:12 -0400 Subject: [PATCH 1/3] Introduce compiler extensions for core metamodels --- docs/compiler/compiler-extension-processor.md | 76 ++++++++ .../collection/generation/TestExtensions.java | 11 ++ .../AssociationCompilerExtension.java | 140 ++++++++++++++ .../toPureGraph/ClassCompilerExtension.java | 173 ++++++++++++++++++ .../DataElementCompilerExtension.java | 76 ++++++++ .../EnumerationCompilerExtension.java | 79 ++++++++ .../FunctionCompilerExtension.java | 135 ++++++++++++++ .../toPureGraph/HelperCoreBuilder.java | 63 +++++++ .../toPureGraph/HelperMappingBuilder.java | 6 +- .../toPureGraph/MappingCompilerExtension.java | 142 ++++++++++++++ .../toPureGraph/MeasureCompilerExtension.java | 74 ++++++++ ...ackageableConnectionCompilerExtension.java | 62 +++++++ .../PackageableElementFirstPassBuilder.java | 2 - .../PackageableElementPrerequisiteFinder.java | 115 ------------ .../PackageableRuntimeCompilerExtension.java | 71 +++++++ .../toPureGraph/ProfileCompilerExtension.java | 73 ++++++++ .../pure/compiler/toPureGraph/PureModel.java | 60 ++++-- .../SectionIndexCompilerExtension.java | 49 +++++ .../extension/CompilerExtensions.java | 9 - ...er.toPureGraph.extension.CompilerExtension | 13 +- ...erRelationalDatabaseConnectionBuilder.java | 2 +- ...TestLegendServicePostValidationRunner.java | 9 +- .../execution/service/ServiceModeling.java | 6 +- 23 files changed, 1286 insertions(+), 160 deletions(-) create mode 100644 docs/compiler/compiler-extension-processor.md create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java delete mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementPrerequisiteFinder.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java create mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java diff --git a/docs/compiler/compiler-extension-processor.md b/docs/compiler/compiler-extension-processor.md new file mode 100644 index 00000000000..cd0e787d7c7 --- /dev/null +++ b/docs/compiler/compiler-extension-processor.md @@ -0,0 +1,76 @@ +# Defining Compiler Extension Processor + +``` JAVA +public static Processor newProcessor( + Class elementClass, + Collection> prerequisiteClasses, + BiFunction firstPass, + BiConsumer secondPass, + BiConsumer thirdPass, + BiFunction> prerequisiteElementsPass) +``` + +## Element Class +Provide subclass of `PackageableElement` which is being compiled (e.g. `Database.class`). + +## Prerequisite Classes +Provide a set of prerequisite classes which your element class depends on (e.g. `[Mapping.class, PackageableConnection.class]`). +The compiler sorts the dependencies based on these prerequisite classes and guarantees all elements in those classes are compiled before the elements in your class. + +## First Pass +Define a function that performs the following operations: +* Create `Pure (M3)` objects and register them in Pure graph +* Set primitive values in the `Pure (M3)` objects +* **MUST NOT** reference other elements in the Pure graph + +## Second Pass +Define a function that performs the following operations: +* Resolve content of its own element and references to other elements +* **MUST NOT** introspect content of other elements or check validity/correctness + +## Third Pass +Define a function that performs the following operations: +* Resolve cross-dependencies +* Introspect other elements + +## Prerequisite Elements Pass +Define a function that returns the prerequisite elements under the same element class that your element depends on. +The compiler sorts the dependencies based on these prerequisite elements and guarantees that those elements are compiled before your element. +For instance, `MappingA` depends on `MappingB` and `MappingC`, and therefore, `MappingB` and `MappingC` must be compiled first. + +The compiler throws an `EngineException` if it finds circular dependencies in these elements. The following Pure grammar demonstrates an example of circular dependencies: + +``` pure +###Relational +Database store::CovidDataStoreA +( + include store::CovidDataStoreB +) + +Database store::CovidDataStoreB +( + include store::CovidDataStoreC +) + +Database store::CovidDataStoreC +( + include store::CovidDataStoreA + + Table DEMOGRAPHICS + ( + FIPS VARCHAR(200), + STATE VARCHAR(200) + ) + Table COVID_DATA + ( + ID INTEGER PRIMARY KEY, + FIPS VARCHAR(200), + DATE DATE, + CASE_TYPE VARCHAR(200), + CASES INTEGER, + LAST_REPORTED_FLAG BIT + ) + + Join CovidDataDemographicsJoin(DEMOGRAPHICS.FIPS = COVID_DATA.FIPS) +) +``` \ No newline at end of file diff --git a/legend-engine-config/legend-engine-extensions-collection-generation/src/test/java/org/finos/legend/engine/extensions/collection/generation/TestExtensions.java b/legend-engine-config/legend-engine-extensions-collection-generation/src/test/java/org/finos/legend/engine/extensions/collection/generation/TestExtensions.java index f7d70e917e9..49631d0fd7f 100644 --- a/legend-engine-config/legend-engine-extensions-collection-generation/src/test/java/org/finos/legend/engine/extensions/collection/generation/TestExtensions.java +++ b/legend-engine-config/legend-engine-extensions-collection-generation/src/test/java/org/finos/legend/engine/extensions/collection/generation/TestExtensions.java @@ -418,6 +418,17 @@ protected Iterable> getExpectedComp .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.DataSpaceCompilerExtension.class) .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.TextCompilerExtension.class) .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.CoreCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.ProfileCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.EnumerationCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.ClassCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.MeasureCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.AssociationCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.FunctionCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.MappingCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableRuntimeCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableConnectionCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.SectionIndexCompilerExtension.class) + .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.DataElementCompilerExtension.class) .with(org.finos.legend.engine.language.pure.dsl.generation.compiler.toPureGraph.GenerationCompilerExtensionImpl.class) .with(org.finos.legend.engine.language.pure.dsl.service.compiler.toPureGraph.ServiceCompilerExtensionImpl.class) .with(org.finos.legend.engine.language.pure.compiler.toPureGraph.ExternalFormatCompilerExtension.class) diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java new file mode 100644 index 00000000000..30c3bc9fa80 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java @@ -0,0 +1,140 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.ListIterable; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; +import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_relationship_Association_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; + +public class AssociationCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Association"); + } + + @Override + public CompilerExtension build() + { + return new AssociationCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Association.class, + Lists.fixedSize.with(Class.class), + (Association srcAssociation, CompileContext context) -> + { + String packageString = context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = new Root_meta_pure_metamodel_relationship_Association_Impl(srcAssociation.name, null, context.pureModel.getClass("meta::pure::metamodel::relationship::Association")); + + if (srcAssociation.properties.size() != 2) + { + throw new EngineException("Expected 2 properties for an association '" + packageString + "'", srcAssociation.sourceInformation, EngineErrorType.COMPILATION); + } + return association._stereotypes(ListIterate.collect(srcAssociation.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) + ._taggedValues(ListIterate.collect(srcAssociation.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); + }, + (Association srcAssociation, CompileContext context) -> + { + String packageString = context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = context.pureModel.getAssociation(packageString, srcAssociation.sourceInformation); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class source = context.resolveClass(srcAssociation.properties.get(0).type, srcAssociation.properties.get(0).sourceInformation); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class target = context.resolveClass(srcAssociation.properties.get(1).type, srcAssociation.properties.get(1).sourceInformation); + + String property0Ref = context.pureModel.addPrefixToTypeReference(HelperModelBuilder.getElementFullPath(source, context.pureModel.getExecutionSupport())); + String property1Ref = context.pureModel.addPrefixToTypeReference(HelperModelBuilder.getElementFullPath(target, context.pureModel.getExecutionSupport())); + + // TODO generalize this validation to all platform/core types + if ("meta::pure::metamodel::type::Any".equals(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(source)) || + "meta::pure::metamodel::type::Any".equals(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(target))) + { + throw new EngineException("Associations to Any are not allowed. Found in '" + packageString + "'", srcAssociation.sourceInformation, EngineErrorType.COMPILATION); + } + + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property property1 = HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(property1Ref), association).valueOf(srcAssociation.properties.get(0)); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property property2 = HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(property0Ref), association).valueOf(srcAssociation.properties.get(1)); + + synchronized (source) + { + source._propertiesFromAssociationsAdd(property2); + } + synchronized (target) + { + target._propertiesFromAssociationsAdd(property1); + } + + ProcessingContext ctx = new ProcessingContext("Association " + packageString + " (second pass)"); + + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, property1Ref); + ctx.addInferredVariables("this", thisVariable); + + ListIterable> qualifiedProperties = ListIterate.collect(srcAssociation.qualifiedProperties, p -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class cl = context.resolveGenericType(p.returnType, p.sourceInformation)._rawType() == source ? target : source; + return HelperModelBuilder.processQualifiedPropertyFirstPass(context, association, org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(cl), ctx).valueOf(p); + }); + qualifiedProperties.forEach(q -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class _class = q._genericType()._rawType() == source ? target : source; + synchronized (_class) + { + _class._qualifiedPropertiesFromAssociationsAdd(q); + } + }); + ctx.flushVariable("this"); + association._originalMilestonedProperties(ListIterate.collect(srcAssociation.originalMilestonedProperties, HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(srcAssociation.properties.get(0).type), association))) + ._properties(Lists.mutable.with(property1, property2)) + ._qualifiedProperties(qualifiedProperties); + }, + (Association srcAssociation, CompileContext context) -> + { + String property0Ref = context.pureModel.addPrefixToTypeReference(srcAssociation.properties.get(0).type); + String property1Ref = context.pureModel.addPrefixToTypeReference(srcAssociation.properties.get(1).type); + + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = context.pureModel.getAssociation(context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name), srcAssociation.sourceInformation); + ProcessingContext ctx = new ProcessingContext("Association " + context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name) + " (third pass)"); + + ListIterate.collect(srcAssociation.qualifiedProperties, property -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, srcAssociation.properties.get(0).type.equals(property.returnType) ? property1Ref : property0Ref); + ctx.addInferredVariables("this", thisVariable); + ctx.push("Qualified Property " + property.name); + ListIterate.collect(property.parameters, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + MutableList body = ListIterate.collect(property.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty prop = association._qualifiedProperties().detect(o -> o._name().equals(property.name)); + ctx.pop(); + ctx.flushVariable("this"); + return prop._expressionSequence(body); + }); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java new file mode 100644 index 00000000000..f7751d9915b --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java @@ -0,0 +1,173 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.factory.Sets; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure; +import org.finos.legend.engine.shared.core.identity.Identity; +import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; +import org.finos.legend.engine.shared.core.operational.logs.LogInfo; +import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_relationship_Generalization_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Class_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Generalization; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; +import org.slf4j.Logger; + +import java.util.Set; + +public class ClassCompilerExtension implements CompilerExtension +{ + private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(ClassCompilerExtension.class); + + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Class"); + } + + @Override + public CompilerExtension build() + { + return new ClassCompilerExtension(); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Class.class, + Lists.fixedSize.with(Measure.class), + (Class srcClass, CompileContext context) -> + { + String fullPath = context.pureModel.buildPackageString(srcClass._package, srcClass.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class targetClass = new Root_meta_pure_metamodel_type_Class_Impl<>(srcClass.name, SourceInformationHelper.toM3SourceInformation(srcClass.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::type::Class")); + context.pureModel.typesIndex.put(fullPath, targetClass); + GenericType genericType = HelperCoreBuilder.newGenericType(targetClass, context); + context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); + return targetClass._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::metamodel::type::Class"), genericType, context)) + ._stereotypes(ListIterate.collect(srcClass.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) + ._taggedValues(ListIterate.collect(srcClass.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); + }, + (Class srcClass, CompileContext context) -> + { + String fullPath = context.pureModel.buildPackageString(srcClass._package, srcClass.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class _class = context.pureModel.getClass(fullPath, srcClass.sourceInformation); + GenericType _classGenericType = context.resolveGenericType(fullPath, srcClass.sourceInformation); + Set uniqueSuperTypes = Sets.mutable.empty(); + MutableList generalization = ListIterate.collect(srcClass.superTypes, superTypePtr -> + { + String superType = superTypePtr.path; + // validate no duplicated class supertype + if (!uniqueSuperTypes.add(superType)) + { + throw new EngineException("Duplicated super type '" + superType + "' in class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "'", srcClass.sourceInformation, EngineErrorType.COMPILATION); + } + Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", SourceInformationHelper.toM3SourceInformation(superTypePtr.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization"))._general(context.resolveGenericType(superType, superTypePtr.sourceInformation))._specific(_class); + if (!context.pureModel.isImmutable(superType)) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class superTypeClass; + Type type = context.resolveType(superType, superTypePtr.sourceInformation); + try + { + superTypeClass = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class) type; + } + catch (ClassCastException e) + { + throw new EngineException("Invalid supertype: '" + srcClass.name + "' cannot extend '" + superType + "' as it is not a class.", srcClass.sourceInformation, EngineErrorType.COMPILATION); + } + synchronized (superTypeClass) + { + superTypeClass._specializationsAdd(g); + } + } + return g; + }); + + MutableList> properties = ListIterate.collect(srcClass.properties, HelperModelBuilder.processProperty(context, _classGenericType, _class)); + MutableList> restrictedMilestoningProperties = Milestoning.restrictedMilestoningProperties(_class, srcClass, properties, context.pureModel); + MutableList> withMilestoningProperties = properties.select(p -> !restrictedMilestoningProperties.contains(p)).withAll(Milestoning.generateMilestoningProperties(_class, context)); + + ProcessingContext ctx = new ProcessingContext("Class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' Second Pass"); + ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, context.pureModel.buildPackageString(srcClass._package, srcClass.name)); + ctx.addInferredVariables("this", thisVariable); + + RichIterable> qualifiedProperties = ListIterate.collect(srcClass.qualifiedProperties, HelperModelBuilder.processQualifiedPropertyFirstPass(context, _class, context.pureModel.buildPackageString(srcClass._package, srcClass.name), ctx)); + _class._originalMilestonedProperties(ListIterate.collect(srcClass.originalMilestonedProperties, HelperModelBuilder.processProperty(context, _classGenericType, _class))) + ._generalizations(generalization) + ._qualifiedProperties(qualifiedProperties) + ._properties(withMilestoningProperties); + if (_class._generalizations().isEmpty()) + { + Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization")) + ._general(context.pureModel.getGenericType("meta::pure::metamodel::type::Any")) + ._specific(_class); + _class._generalizationsAdd(g); + } + ctx.flushVariable("this"); + }, + (Class srcClass, CompileContext context) -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class targetClass = context.pureModel.getClass(context.pureModel.buildPackageString(srcClass._package, srcClass.name), srcClass.sourceInformation); + + ProcessingContext ctx = new ProcessingContext("Class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' Third Pass"); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, context.pureModel.buildPackageString(srcClass._package, srcClass.name)); + + ListIterate.collect(srcClass.qualifiedProperties, property -> + { + ctx.push("Qualified Property " + property.name); + ctx.addInferredVariables("this", thisVariable); + MutableList body; + try + { + property.parameters.forEach(p -> p.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + body = ListIterate.collect(property.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + } + catch (Exception e) + { + LOGGER.warn(new LogInfo(Identity.getAnonymousIdentity().getName(), LoggingEventType.GRAPH_EXPRESSION_ERROR, "Can't build derived property '" + property.name + " of class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' - stack: " + ctx.getStack()).toString()); + if (e instanceof EngineException) + { + throw e; + } + e.printStackTrace(); + throw new EngineException(e.getMessage(), property.sourceInformation, EngineErrorType.COMPILATION); + } + ctx.flushVariable("this"); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty prop = targetClass._qualifiedProperties().detect(o -> HelperModelBuilder.isCompatibleDerivedProperty(o, property)); + HelperModelBuilder.checkCompatibility(context, body.getLast()._genericType()._rawType(), body.getLast()._multiplicity(), prop._genericType()._rawType(), prop._multiplicity(), "Error in derived property '" + srcClass.name + "." + property.name + "'", property.body.get(property.body.size() - 1).sourceInformation); + ctx.pop(); + return prop._expressionSequence(body); + }); + + HelperModelBuilder.processClassConstraints(srcClass, context, targetClass, ctx, thisVariable); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java new file mode 100644 index 00000000000..83ac65bc0f4 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java @@ -0,0 +1,76 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.data.EmbeddedDataFirstPassBuilder; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.data.DataElement; +import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; +import org.finos.legend.pure.generated.Root_meta_pure_data_DataElement; +import org.finos.legend.pure.generated.Root_meta_pure_data_DataElementReference; +import org.finos.legend.pure.generated.Root_meta_pure_data_DataElement_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_data_EmbeddedData; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; + +public class DataElementCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "DataElement"); + } + + @Override + public CompilerExtension build() + { + return new DataElementCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + DataElement.class, + (DataElement dataElement, CompileContext context) -> + { + Root_meta_pure_data_DataElement compiled = new Root_meta_pure_data_DataElement_Impl(dataElement.name, SourceInformationHelper.toM3SourceInformation(dataElement.sourceInformation), null); + GenericType mappingGenericType = HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::data::DataElement"), context); + return compiled._classifierGenericType(mappingGenericType) + ._stereotypes(ListIterate.collect(dataElement.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) + ._taggedValues(ListIterate.collect(dataElement.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); + }, + (DataElement dataElement, CompileContext context) -> + { + String fullPath = context.pureModel.buildPackageString(dataElement._package, dataElement.name); + Root_meta_pure_data_DataElement compiled = (Root_meta_pure_data_DataElement) context.pureModel.getPackageableElement(fullPath); + + ProcessingContext processingContext = new ProcessingContext("Data '" + fullPath + "' Second Pass"); + Root_meta_pure_data_EmbeddedData compiledData = dataElement.data.accept(new EmbeddedDataFirstPassBuilder(context, processingContext)); + if (compiledData instanceof Root_meta_pure_data_DataElementReference) + { + throw new EngineException("Cannot use Data element reference in a Data element", dataElement.data.sourceInformation, EngineErrorType.COMPILATION); + } + compiled._data(compiledData); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java new file mode 100644 index 00000000000..47a8d6b7e64 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java @@ -0,0 +1,79 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_relationship_Generalization_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Enum_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Enumeration_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Generalization; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; + +public class EnumerationCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Enumeration"); + } + + @Override + public CompilerExtension build() + { + return new EnumerationCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Enumeration.class, + (Enumeration enumeration, CompileContext context) -> + { + String fullPath = context.pureModel.buildPackageString(enumeration._package, enumeration.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration en = new Root_meta_pure_metamodel_type_Enumeration_Impl<>(enumeration.name, SourceInformationHelper.toM3SourceInformation(enumeration.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::type::Enumeration")); + context.pureModel.typesIndex.put(fullPath, en); + GenericType genericType = HelperCoreBuilder.newGenericType(en, context); + context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); + return en._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getClass("meta::pure::metamodel::type::Enumeration"), genericType, context)) + ._stereotypes(ListIterate.collect(enumeration.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) + ._taggedValues(ListIterate.collect(enumeration.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))) + ._values(ListIterate.collect(enumeration.values, v -> new Root_meta_pure_metamodel_type_Enum_Impl(v.value, SourceInformationHelper.toM3SourceInformation(v.sourceInformation), null) + ._classifierGenericType(genericType) + ._stereotypes(ListIterate.collect(v.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) + ._taggedValues(ListIterate.collect(v.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))) + ._name(v.value))); + }, + (Enumeration enumeration, CompileContext context) -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration targetEnum = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration) context.pureModel.getType(context.pureModel.buildPackageString(enumeration._package, enumeration.name), enumeration.sourceInformation); + if (targetEnum._generalizations().isEmpty()) + { + Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization")) + ._general(context.pureModel.getGenericType("meta::pure::metamodel::type::Any")) + ._specific(targetEnum); + targetEnum._generalizationsAdd(g); + } + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java new file mode 100644 index 00000000000..ce31240fae0 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java @@ -0,0 +1,135 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.handlers.UserDefinedFunctionHandler; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.handlers.inference.TypeAndMultiplicity; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.data.DataElement; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Function; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.Binding; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping; +import org.finos.legend.engine.shared.core.identity.Identity; +import org.finos.legend.engine.shared.core.operational.logs.LogInfo; +import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_function_ConcreteFunctionDefinition_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.VariableExpression; +import org.slf4j.Logger; + +import java.util.List; + +public class FunctionCompilerExtension implements CompilerExtension +{ + private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(FunctionCompilerExtension.class); + + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Function"); + } + + @Override + public CompilerExtension build() + { + return new FunctionCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Function.class, + Lists.fixedSize.with(DataElement.class, Class.class, Association.class, Mapping.class, Binding.class), + (Function function, CompileContext context) -> + { + // NOTE: in the protocol, we still store the function name as is, but in the function index, we will store the function based on its function signature + String functionSignature = HelperModelBuilder.getSignature(function); + String functionFullName = context.pureModel.buildPackageString(function._package, functionSignature); + String functionName = context.pureModel.buildPackageString(function._package, HelperModelBuilder.getFunctionNameWithoutSignature(function)); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition targetFunc = new Root_meta_pure_metamodel_function_ConcreteFunctionDefinition_Impl<>(functionSignature, SourceInformationHelper.toM3SourceInformation(function.sourceInformation), null); + + ProcessingContext ctx = new ProcessingContext("Function '" + functionFullName + "' First Pass"); + + context.pureModel.setNameAndPackage(targetFunc, functionSignature, function._package, function.sourceInformation) + ._functionName(functionName) // function name to be used in the handler map -> meta::pure::functions::date::isAfterDay + ._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::metamodel::function::ConcreteFunctionDefinition"), PureModel.buildFunctionType(ListIterate.collect(function.parameters, p -> (VariableExpression) p.accept(new ValueSpecificationBuilder(context, Lists.mutable.empty(), ctx))), context.resolveGenericType(function.returnType, function.sourceInformation), context.pureModel.getMultiplicity(function.returnMultiplicity), context.pureModel), context)) + ._stereotypes(ListIterate.collect(function.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) + ._taggedValues(ListIterate.collect(function.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); + HelperModelBuilder.processFunctionConstraints(function, context, targetFunc, ctx); + + context.pureModel.handlers.register(new UserDefinedFunctionHandler(context.pureModel, functionFullName, targetFunc, + ps -> new TypeAndMultiplicity(context.resolveGenericType(function.returnType, function.sourceInformation), context.pureModel.getMultiplicity(function.returnMultiplicity)), + ps -> + { + List vs = ListIterate.collect(function.parameters, p -> p.accept(new ValueSpecificationBuilder(context, Lists.mutable.empty(), ctx))); + if (ps.size() == function.parameters.size()) + { + int size = ps.size(); + // TODO clean up the check.... + try + { + for (int i = 0; i < size; i++) + { + HelperModelBuilder.checkCompatibility(context, ps.get(i)._genericType()._rawType(), ps.get(i)._multiplicity(), vs.get(i)._genericType()._rawType(), vs.get(i)._multiplicity(), "Error in function '" + functionFullName + "'", function.body.get(function.body.size() - 1).sourceInformation); + } + } + catch (Exception e) + { + return false; + } + return true; + } + return false; + })); + return targetFunc; + }, + (Function function, CompileContext context) -> + { + }, + (Function function, CompileContext context) -> + { + String packageString = context.pureModel.buildPackageString(function._package, HelperModelBuilder.getSignature(function)); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition targetFunc = context.pureModel.getConcreteFunctionDefinition(packageString, function.sourceInformation); + ProcessingContext ctx = new ProcessingContext("Function '" + packageString + "' Third Pass"); + MutableList body; + try + { + function.parameters.forEach(p -> p.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + body = ListIterate.collect(function.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + } + catch (Exception e) + { + LOGGER.warn(new LogInfo(Identity.getAnonymousIdentity().getName(), LoggingEventType.GRAPH_EXPRESSION_ERROR, "Can't build function '" + packageString + "' - stack: " + ctx.getStack()).toString()); + throw e; + } + FunctionType fType = ((FunctionType) targetFunc._classifierGenericType()._typeArguments().getFirst()._rawType()); + HelperModelBuilder.checkCompatibility(context, body.getLast()._genericType()._rawType(), body.getLast()._multiplicity(), fType._returnType()._rawType(), fType._returnMultiplicity(), "Error in function '" + packageString + "'", function.body.get(function.body.size() - 1).sourceInformation); + ctx.pop(); + targetFunc._expressionSequence(body); + HelperFunctionBuilder.processFunctionSuites(function, targetFunc, context, ctx); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java new file mode 100644 index 00000000000..e4191387a3a --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java @@ -0,0 +1,63 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.api.factory.Lists; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.StereotypePtr; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.TagPtr; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_TaggedValue_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_generics_GenericType_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.TaggedValue; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; + +public class HelperCoreBuilder +{ + protected static GenericType newGenericType(Type rawType, CompileContext context) + { + return new Root_meta_pure_metamodel_type_generics_GenericType_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::type::generics::GenericType")) + ._rawType(rawType); + } + + protected static GenericType newGenericType(Type rawType, GenericType typeArgument, CompileContext context) + { + return newGenericType(rawType, Lists.fixedSize.with(typeArgument), context); + } + + private static GenericType newGenericType(Type rawType, RichIterable typeArguments, CompileContext context) + { + return newGenericType(rawType, context)._typeArguments(typeArguments); + } + + protected static TaggedValue newTaggedValue(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.TaggedValue taggedValue, CompileContext context) + { + return new Root_meta_pure_metamodel_extension_TaggedValue_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::extension::TaggedValue")) + ._tag(resolveTag(taggedValue.tag, context)) + ._value(taggedValue.value); + } + + private static Tag resolveTag(TagPtr tagPointer, CompileContext context) + { + return context.resolveTag(tagPointer.profile, tagPointer.value, tagPointer.profileSourceInformation, tagPointer.sourceInformation); + } + + protected static Stereotype resolveStereotype(StereotypePtr stereotypePointer, CompileContext context) + { + return context.resolveStereotype(stereotypePointer.profile, stereotypePointer.value, stereotypePointer.profileSourceInformation, stereotypePointer.sourceInformation); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java index 2efe317da26..072c2817b0e 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java @@ -375,9 +375,11 @@ public static Root_meta_pure_mapping_MappingClass_Impl processMappingClass(org.f { mappingClass._setImplementation(mappingclass.setImplementation.accept(new ClassMappingFirstPassBuilder(context, parent)).getOne()); } - if (mappingclass.rootClass != null) + org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class rootClass = mappingclass.rootClass; + if (rootClass != null) { - mappingClass._class((org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class) mappingclass.rootClass.accept(new PackageableElementThirdPassBuilder(context))); + context.pureModel.processThirdPass(rootClass); + mappingClass._class(context.pureModel.getClass(context.pureModel.buildPackageString(rootClass._package, rootClass.name), rootClass.sourceInformation)); } return mappingClass; } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java new file mode 100644 index 00000000000..45acd924bf5 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java @@ -0,0 +1,142 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.factory.Sets; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.api.tuple.Pair; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtensions; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.handlers.IncludedMappingHandler; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.test.TestBuilderHelper; +import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.Binding; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.store.Store; +import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; +import org.finos.legend.pure.generated.Root_meta_pure_mapping_Mapping_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.AssociationImplementation; +import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.EmbeddedSetImplementation; +import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.EnumerationMapping; +import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.MappingIncludeAccessor; +import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.SetImplementation; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; + +import java.util.Set; + +public class MappingCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Mapping"); + } + + @Override + public CompilerExtension build() + { + return new MappingCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Mapping.class, + Lists.fixedSize.with(Enumeration.class, Class.class, Association.class, Binding.class, Store.class), + (Mapping mapping, CompileContext context) -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = new Root_meta_pure_mapping_Mapping_Impl(mapping.name, SourceInformationHelper.toM3SourceInformation(mapping.sourceInformation), context.pureModel.getClass("meta::pure::mapping::Mapping")); + GenericType mappingGenericType = HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::mapping::Mapping"), context); + return pureMapping._classifierGenericType(mappingGenericType); + }, + (Mapping mapping, CompileContext context) -> + { + final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); + RichIterable> enumerationMappings = ListIterate.collect(mapping.enumerationMappings, em -> HelperMappingBuilder.processEnumMapping(em, pureMapping, context)); + if (!mapping.includedMappings.isEmpty()) + { + CompilerExtensions extensions = context.pureModel.extensions; + RichIterable mappingIncludes = + ListIterate.collect(mapping.includedMappings, i -> + { + IncludedMappingHandler handler = extensions.getExtraIncludedMappingHandlers(i.getClass().getName()); + return handler.processMappingInclude(i, context, pureMapping, + handler.resolveMapping(i, context)); + }); + pureMapping._includesAddAll(mappingIncludes); + // validate no duplicated included mappings + Set uniqueMappingIncludes = Sets.mutable.empty(); + mappingIncludes.forEach(includedMapping -> + { + String mappingName = IncludedMappingHandler.parseIncludedMappingNameRecursively(includedMapping); + if (!uniqueMappingIncludes.add(mappingName)) + { + throw new EngineException("Duplicated mapping include '" + mappingName + + "' in " + "mapping " + + "'" + context.pureModel.buildPackageString(mapping._package, mapping.name) + "'", mapping.sourceInformation, EngineErrorType.COMPILATION); + } + }); + } + if (!enumerationMappings.isEmpty()) + { + pureMapping._enumerationMappings(enumerationMappings); + } + }, + (Mapping mapping, CompileContext context) -> + { + final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); + if (mapping.classMappings != null && pureMapping._classMappings().isEmpty()) + { + RichIterable>> setImplementations = ListIterate.collect(mapping.classMappings, cm -> cm.accept(new ClassMappingFirstPassBuilder(context, pureMapping))); + pureMapping._classMappingsAddAll(setImplementations.flatCollect(p -> org.eclipse.collections.impl.factory.Lists.mutable.with(p.getOne()).withAll(p.getTwo()))); + } + if (!mapping.tests.isEmpty()) + { + mapping.tests.forEach(t -> HelperMappingBuilder.processMappingTest(t, context)); + } + if (mapping.testSuites != null) + { + TestBuilderHelper.validateTestSuiteIdsList(mapping.testSuites, mapping.sourceInformation); + pureMapping._tests(ListIterate.collect(mapping.testSuites, suite -> HelperMappingBuilder.processMappingTestAndTestSuite(suite, pureMapping, context))); + } + if (mapping.associationMappings != null) + { + RichIterable associationImplementations = ListIterate.collect(mapping.associationMappings, cm -> HelperMappingBuilder.processAssociationImplementation(cm, context, pureMapping)); + pureMapping._associationMappings(associationImplementations); + } + if (mapping.classMappings != null) + { + mapping.classMappings.forEach(cm -> cm.accept(new ClassMappingSecondPassBuilder(context, pureMapping))); + mapping.classMappings.forEach(cm -> cm.accept(new ClassMappingThirdPassBuilder(context, pureMapping))); + } + }, + (Mapping mapping, CompileContext context) -> + { + final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); + return pureMapping._includes().collect(MappingIncludeAccessor::_included); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java new file mode 100644 index 00000000000..ae9466cee8a --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java @@ -0,0 +1,74 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Measure_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; +import org.finos.legend.pure.m3.navigation.M3Paths; + +public class MeasureCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Measure"); + } + + @Override + public CompilerExtension build() + { + return new MeasureCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Measure.class, + (Measure measure, CompileContext context) -> + { + String fullPath = context.pureModel.buildPackageString(measure._package, measure.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Measure targetMeasure = new Root_meta_pure_metamodel_type_Measure_Impl(measure.name, SourceInformationHelper.toM3SourceInformation(measure.sourceInformation), null); + context.pureModel.typesIndex.put(fullPath, targetMeasure); + GenericType genericType = HelperCoreBuilder.newGenericType(targetMeasure, context); + context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); + targetMeasure._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getType(M3Paths.Measure), context)); + if (measure.canonicalUnit != null) + { + HelperMeasureBuilder.processUnitPackageableElementFirstPass(measure.canonicalUnit, context); + } + measure.nonCanonicalUnits.forEach(ncu -> HelperMeasureBuilder.processUnitPackageableElementFirstPass(ncu, context)); + return targetMeasure; + }, + (Measure measure, CompileContext context) -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Measure targetMeasure = context.pureModel.getMeasure(context.pureModel.buildPackageString(measure._package, measure.name), measure.sourceInformation); + if (measure.canonicalUnit != null) + { + targetMeasure._canonicalUnit(HelperMeasureBuilder.processUnitPackageableElementSecondPass(measure.canonicalUnit, context)); + } + targetMeasure._nonCanonicalUnits(ListIterate.collect(measure.nonCanonicalUnits, ncu -> HelperMeasureBuilder.processUnitPackageableElementSecondPass(ncu, context))); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java new file mode 100644 index 00000000000..7e883f531b9 --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java @@ -0,0 +1,62 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.connection.PackageableConnection; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping; +import org.finos.legend.pure.generated.Root_meta_core_runtime_Connection; +import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableConnection; +import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableConnection_Impl; + +public class PackageableConnectionCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "PackageableConnection"); + } + + @Override + public CompilerExtension build() + { + return new PackageableConnectionCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + PackageableConnection.class, + Lists.fixedSize.with(Mapping.class), + (PackageableConnection packageableConnection, CompileContext context) -> + { + Root_meta_pure_runtime_PackageableConnection metamodel = new Root_meta_pure_runtime_PackageableConnection_Impl(packageableConnection.name, SourceInformationHelper.toM3SourceInformation(packageableConnection.sourceInformation), context.pureModel.getClass("meta::pure::runtime::PackageableConnection")); + Root_meta_core_runtime_Connection connection = packageableConnection.connectionValue.accept(new ConnectionFirstPassBuilder(context)); + return metamodel._connectionValue(connection); + }, + (PackageableConnection packageableConnection, CompileContext context) -> + { + final Root_meta_core_runtime_Connection pureConnection = context.pureModel.getConnection(context.pureModel.buildPackageString(packageableConnection._package, packageableConnection.name), packageableConnection.sourceInformation); + packageableConnection.connectionValue.accept(new ConnectionSecondPassBuilder(context, pureConnection)); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementFirstPassBuilder.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementFirstPassBuilder.java index 8b4a3bf2480..8ed24e2c1fe 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementFirstPassBuilder.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementFirstPassBuilder.java @@ -59,8 +59,6 @@ import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableConnection_Impl; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime_Impl; -import org.finos.legend.pure.generated.Root_meta_core_runtime_Runtime; -import org.finos.legend.pure.generated.Root_meta_core_runtime_Runtime_Impl; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag; diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementPrerequisiteFinder.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementPrerequisiteFinder.java deleted file mode 100644 index dec5fda8c70..00000000000 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableElementPrerequisiteFinder.java +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2024 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.language.pure.compiler.toPureGraph; - -import org.eclipse.collections.api.RichIterable; -import org.eclipse.collections.api.factory.Lists; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElementVisitor; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.connection.PackageableConnection; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.data.DataElement; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Function; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Profile; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.PackageableRuntime; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.SectionIndex; -import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.MappingIncludeAccessor; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; - -public class PackageableElementPrerequisiteFinder implements PackageableElementVisitor> -{ - private final CompileContext context; - - public PackageableElementPrerequisiteFinder(CompileContext context) - { - this.context = context; - } - - @Override - public RichIterable visit(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) - { - return this.context.getExtraProcessorOrThrow(element).getPrerequisiteElements(element, this.context); - } - - @Override - public RichIterable visit(Profile profile) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(Enumeration _enum) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(Class _class) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(Association association) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(Function function) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(Measure measure) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(SectionIndex sectionIndex) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(Mapping mapping) - { - final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = this.context.pureModel.getMapping(this.context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); - return pureMapping._includes().collect(MappingIncludeAccessor::_included); - } - - @Override - public RichIterable visit(PackageableRuntime packageableRuntime) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(PackageableConnection packageableConnection) - { - return Lists.fixedSize.empty(); - } - - @Override - public RichIterable visit(DataElement dataElement) - { - return Lists.fixedSize.empty(); - } -} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java new file mode 100644 index 00000000000..d7f358e4e0a --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java @@ -0,0 +1,71 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.connection.PackageableConnection; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.PackageableRuntime; +import org.finos.legend.pure.generated.Root_meta_core_runtime_EngineRuntime; +import org.finos.legend.pure.generated.Root_meta_core_runtime_EngineRuntime_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime; +import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; + +public class PackageableRuntimeCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "PackageableRuntime"); + } + + @Override + public CompilerExtension build() + { + return new PackageableRuntimeCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + PackageableRuntime.class, + Lists.fixedSize.with(Mapping.class, PackageableConnection.class), + (PackageableRuntime packageableRuntime, CompileContext context) -> + { + Root_meta_pure_runtime_PackageableRuntime metamodel = new Root_meta_pure_runtime_PackageableRuntime_Impl(packageableRuntime.name, SourceInformationHelper.toM3SourceInformation(packageableRuntime.sourceInformation), context.pureModel.getClass("meta::pure::runtime::PackageableRuntime")); + GenericType packageableRuntimeGenericType = HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::runtime::PackageableRuntime"), context); + metamodel._classifierGenericType(packageableRuntimeGenericType); + Root_meta_core_runtime_EngineRuntime pureRuntime = new Root_meta_core_runtime_EngineRuntime_Impl("Root::meta::core::runtime::Runtime", SourceInformationHelper.toM3SourceInformation(packageableRuntime.sourceInformation), context.pureModel.getClass("meta::core::runtime::Runtime")); + return metamodel._runtimeValue(pureRuntime); + }, + (PackageableRuntime packageableRuntime, CompileContext context) -> + { + }, + (PackageableRuntime packageableRuntime, CompileContext context) -> + { + String fullPath = context.pureModel.buildPackageString(packageableRuntime._package, packageableRuntime.name); + Root_meta_pure_runtime_PackageableRuntime metamodel = context.pureModel.getPackageableRuntime(fullPath, packageableRuntime.sourceInformation); + HelperRuntimeBuilder.buildEngineRuntime(packageableRuntime.runtimeValue, metamodel._runtimeValue(), context); + } + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java new file mode 100644 index 00000000000..4e2978ebdac --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java @@ -0,0 +1,73 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.eclipse.collections.impl.utility.ListIterate; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.SourceInformation; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Profile; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_Profile_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_Stereotype_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_Tag_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag; + +public class ProfileCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "Profile"); + } + + @Override + public CompilerExtension build() + { + return new ProfileCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + Profile.class, + (Profile profile, CompileContext context) -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile targetProfile = new Root_meta_pure_metamodel_extension_Profile_Impl(profile.name, SourceInformationHelper.toM3SourceInformation(profile.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::extension::Profile")); + return targetProfile._p_stereotypes(ListIterate.collect(profile.stereotypes, st -> newStereotype(targetProfile, st.value, st.sourceInformation, context))) + ._p_tags(ListIterate.collect(profile.tags, t -> newTag(targetProfile, t.value, t.sourceInformation, context))); + } + ) + ); + } + + private Stereotype newStereotype(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile profile, String name, SourceInformation sourceInformation, CompileContext context) + { + return new Root_meta_pure_metamodel_extension_Stereotype_Impl(name, SourceInformationHelper.toM3SourceInformation(sourceInformation), context.pureModel.getClass("meta::pure::metamodel::extension::Stereotype")) + ._value(name) + ._profile(profile); + } + + private Tag newTag(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile profile, String name, SourceInformation sourceInformation, CompileContext context) + { + return new Root_meta_pure_metamodel_extension_Tag_Impl(name, SourceInformationHelper.toM3SourceInformation(sourceInformation), context.pureModel.getClass("meta::pure::metamodel::extension::Tag")) + ._value(name) + ._profile(profile); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java index 0fe6826cd15..d505bbd15dc 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java @@ -48,15 +48,12 @@ import org.finos.legend.engine.protocol.pure.v1.model.SourceInformation; import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; import org.finos.legend.engine.protocol.pure.v1.model.context.PureModelContextData; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElementVisitor; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.connection.PackageableConnection; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.data.DataElement; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Function; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Profile; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.externalFormat.Binding; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.PackageableRuntime; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.Section; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.SectionIndex; import org.finos.legend.engine.shared.core.deployment.DeploymentMode; @@ -120,6 +117,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.ConcurrentLinkedQueue; @@ -299,12 +297,6 @@ public PureModel(PureModelContextData pureModelContextData, CompilerExtensions e .forEach(handleEngineExceptions(this::processFirstPass)); MutableMap, Collection>> dependencyGraph = Maps.mutable.empty(); - dependencyGraph.put(Class.class, Lists.fixedSize.with(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure.class)); - dependencyGraph.put(Association.class, Lists.fixedSize.with(Class.class)); - dependencyGraph.put(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping.class, Lists.fixedSize.with(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration.class, Class.class, Association.class, Binding.class, org.finos.legend.engine.protocol.pure.v1.model.packageableElement.store.Store.class)); - dependencyGraph.put(PackageableConnection.class, Lists.fixedSize.with(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping.class)); - dependencyGraph.put(PackageableRuntime.class, Lists.fixedSize.with(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping.class, PackageableConnection.class)); - dependencyGraph.put(Function.class, Lists.fixedSize.with(DataElement.class, Class.class, Association.class, org.finos.legend.engine.protocol.pure.v1.model.packageableElement.mapping.Mapping.class, Binding.class)); this.extensions.getExtraProcessors().forEach(x -> dependencyGraph.put(x.getElementClass(), (Collection>) x.getPrerequisiteClasses())); dependencyManagement.processDependencyGraph(dependencyGraph); @@ -322,7 +314,7 @@ public PureModel(PureModelContextData pureModelContextData, CompilerExtensions e { java.lang.Class elementClass = element.getClass(); String elementFullPath = buildPackageString(element._package, element.name); - RichIterable prerequisiteElements = visitWithErrorHandling(element, new PackageableElementPrerequisiteFinder(getContext(element))); + RichIterable prerequisiteElements = processPrerequisiteElementsPass(element); MutableSet prerequisiteElementFullPaths = Sets.fixedSize.withAll(prerequisiteElements.collect(prerequisiteElement -> platform_pure_essential_meta_graph_elementToPath.Root_meta_pure_functions_meta_elementToPath_PackageableElement_1__String_1_(prerequisiteElement, getExecutionSupport()))); elementPrerequisitesByClass.putIfAbsent(elementClass, forkJoinPool == null ? Maps.mutable.empty() : new ConcurrentHashMap<>()); @@ -614,31 +606,59 @@ else if (cause instanceof RuntimeException) } } - private org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - return visitWithErrorHandling(element, new PackageableElementFirstPassBuilder(getContext(element))); + return visitWithErrorHandling(element, () -> + { + CompileContext context = getContext(element); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement pureElement = context.getExtraProcessorOrThrow(element).processFirstPass(element, context); + if (pureElement instanceof ConcreteFunctionDefinition) + { + return pureElement; + } + return setNameAndPackage(pureElement, element.name, element._package, element.sourceInformation); + }); + } + + public void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + { + visitWithErrorHandling(element, () -> + { + CompileContext context = getContext(element); + context.getExtraProcessorOrThrow(element).processSecondPass(element, context); + return null; + }); } - private void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + private RichIterable processPrerequisiteElementsPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - visitWithErrorHandling(element, new PackageableElementSecondPassBuilder(getContext(element))); + return visitWithErrorHandling(element, () -> + { + CompileContext context = getContext(element); + return context.getExtraProcessorOrThrow(element).getPrerequisiteElements(element, context); + }); } private void processMilestoningPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - visitWithErrorHandling(element, new PackageableElementMilestoningPassBuilder(getContext(element))); + visitWithErrorHandling(element, () -> element.accept(new PackageableElementMilestoningPassBuilder(getContext(element)))); } - private void processThirdPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + public void processThirdPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - visitWithErrorHandling(element, new PackageableElementThirdPassBuilder(getContext(element))); + visitWithErrorHandling(element, () -> + { + CompileContext context = getContext(element); + context.getExtraProcessorOrThrow(element).processThirdPass(element, context); + return null; + }); } - private T visitWithErrorHandling(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element, PackageableElementVisitor visitor) + private T visitWithErrorHandling(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element, Callable callable) { try { - return element.accept(visitor); + return callable.call(); } catch (Exception e) { @@ -647,7 +667,7 @@ private T visitWithErrorHandling(org.finos.legend.engine.protocol.pure.v1.mo SourceInformation sourceInformation = ((EngineException) e).getSourceInformation(); if ((sourceInformation != null) && (sourceInformation != SourceInformation.getUnknownSourceInformation())) { - throw e; + throw (EngineException) e; } } StringBuilder builder = new StringBuilder("Error in '").append(element.getPath()).append("'"); diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java new file mode 100644 index 00000000000..03aacb9eb1e --- /dev/null +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java @@ -0,0 +1,49 @@ +// Copyright 2024 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.language.pure.compiler.toPureGraph; + +import org.eclipse.collections.api.factory.Lists; +import org.eclipse.collections.api.list.MutableList; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension; +import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.SectionIndex; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_section_SectionIndex_Impl; + +public class SectionIndexCompilerExtension implements CompilerExtension +{ + @Override + public MutableList group() + { + return org.eclipse.collections.impl.factory.Lists.mutable.with("PackageableElement", "SectionIndex"); + } + + @Override + public CompilerExtension build() + { + return new SectionIndexCompilerExtension(); + } + + @Override + public Iterable> getExtraProcessors() + { + return Lists.fixedSize.of( + Processor.newProcessor( + SectionIndex.class, + (SectionIndex sectionIndex, CompileContext context) -> + new Root_meta_pure_metamodel_section_SectionIndex_Impl(sectionIndex.name, SourceInformationHelper.toM3SourceInformation(sectionIndex.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::section::SectionIndex")) + ) + ); + } +} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/extension/CompilerExtensions.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/extension/CompilerExtensions.java index 5f481244ff6..1218016058d 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/extension/CompilerExtensions.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/extension/CompilerExtensions.java @@ -88,15 +88,6 @@ public class CompilerExtensions @SuppressWarnings("unchecked") private static final ImmutableSet> FORBIDDEN_PROCESSOR_CLASSES = Sets.immutable.with( PackageableElement.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.connection.PackageableConnection.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Association.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Enumeration.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Function.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Profile.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.runtime.PackageableRuntime.class, - org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.SectionIndex.class, org.finos.legend.engine.protocol.pure.v1.model.packageableElement.store.Store.class ); diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/resources/META-INF/services/org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/resources/META-INF/services/org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension index 526218db8fe..befdfd77628 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/resources/META-INF/services/org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/resources/META-INF/services/org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.CompilerExtension @@ -1 +1,12 @@ -org.finos.legend.engine.language.pure.compiler.toPureGraph.CoreCompilerExtension \ No newline at end of file +org.finos.legend.engine.language.pure.compiler.toPureGraph.CoreCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.ProfileCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.EnumerationCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.ClassCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.MeasureCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.AssociationCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.FunctionCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.MappingCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableRuntimeCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableConnectionCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.SectionIndexCompilerExtension +org.finos.legend.engine.language.pure.compiler.toPureGraph.DataElementCompilerExtension \ No newline at end of file diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java index 76c03b32b89..1ca53a2d58e 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java @@ -58,7 +58,7 @@ public static void addDatabaseConnectionProperties(Root_meta_external_store_rela Database db = new Database(); db.name = element; db._package = ""; - new PackageableElementFirstPassBuilder(context).visit(db); + context.pureModel.processFirstPass(db); } } } diff --git a/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java b/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java index 9c08800229d..b9aa9aba6e8 100644 --- a/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java +++ b/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java @@ -20,9 +20,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import org.eclipse.collections.impl.utility.LazyIterate; import org.finos.legend.engine.language.pure.compiler.toPureGraph.CompileContext; -import org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableElementFirstPassBuilder; -import org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableElementSecondPassBuilder; -import org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableElementThirdPassBuilder; import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; import org.finos.legend.engine.plan.execution.PlanExecutor; import org.finos.legend.engine.plan.execution.result.serialization.SerializationFormat; @@ -105,9 +102,9 @@ public Root_meta_legend_service_metamodel_Service compileService(Service service pkg._childrenRemove(existing); } - Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) service.accept(new PackageableElementFirstPassBuilder(compileContext)); - service.accept(new PackageableElementSecondPassBuilder(compileContext)); - service.accept(new PackageableElementThirdPassBuilder(compileContext)); + Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) compileContext.pureModel.processFirstPass(service); + compileContext.pureModel.processSecondPass(service); + compileContext.pureModel.processThirdPass(service); return compiledService; } diff --git a/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java b/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java index 10a47659ce1..a9bba6aace9 100644 --- a/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java +++ b/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java @@ -24,8 +24,6 @@ import org.eclipse.collections.impl.utility.Iterate; import org.eclipse.collections.impl.utility.LazyIterate; import org.finos.legend.engine.language.pure.compiler.toPureGraph.CompileContext; -import org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableElementFirstPassBuilder; -import org.finos.legend.engine.language.pure.compiler.toPureGraph.PackageableElementSecondPassBuilder; import org.finos.legend.engine.language.pure.compiler.toPureGraph.PureModel; import org.finos.legend.engine.language.pure.modelManager.ModelManager; import org.finos.legend.engine.plan.execution.PlanExecutor; @@ -93,8 +91,8 @@ public Root_meta_legend_service_metamodel_Service compileService(Service service pkg._childrenRemove(existing); } - Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) service.accept(new PackageableElementFirstPassBuilder(compileContext)); - service.accept(new PackageableElementSecondPassBuilder(compileContext)); + Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) compileContext.pureModel.processFirstPass(service); + compileContext.pureModel.processSecondPass(service); return compiledService; } From 258ba604d5321f1ef2b0c4fdb385b697567f3340 Mon Sep 17 00:00:00 2001 From: "Kim, Jake" Date: Thu, 24 Oct 2024 17:09:47 -0400 Subject: [PATCH 2/3] Refactor helper functions --- .../AssociationCompilerExtension.java | 177 +++++++------- .../toPureGraph/ClassCompilerExtension.java | 217 +++++++++--------- .../compiler/toPureGraph/CompileContext.java | 60 ++++- .../DataElementCompilerExtension.java | 47 ++-- .../EnumerationCompilerExtension.java | 59 ++--- .../FunctionCompilerExtension.java | 127 +++++----- .../toPureGraph/HelperCoreBuilder.java | 63 ----- .../toPureGraph/HelperMappingBuilder.java | 2 +- .../toPureGraph/MappingCompilerExtension.java | 153 ++++++------ .../toPureGraph/MeasureCompilerExtension.java | 53 +++-- ...ackageableConnectionCompilerExtension.java | 27 ++- .../PackageableRuntimeCompilerExtension.java | 33 +-- .../toPureGraph/ProfileCompilerExtension.java | 15 +- .../pure/compiler/toPureGraph/PureModel.java | 15 +- .../SectionIndexCompilerExtension.java | 9 +- ...erRelationalDatabaseConnectionBuilder.java | 2 +- ...TestLegendServicePostValidationRunner.java | 6 +- .../execution/service/ServiceModeling.java | 4 +- 18 files changed, 561 insertions(+), 508 deletions(-) delete mode 100644 legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java index 30c3bc9fa80..6dfd98921fd 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/AssociationCompilerExtension.java @@ -25,6 +25,7 @@ import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class; import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_relationship_Association_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; @@ -49,92 +50,98 @@ public Iterable> getExtraProcessors() Processor.newProcessor( Association.class, Lists.fixedSize.with(Class.class), - (Association srcAssociation, CompileContext context) -> - { - String packageString = context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = new Root_meta_pure_metamodel_relationship_Association_Impl(srcAssociation.name, null, context.pureModel.getClass("meta::pure::metamodel::relationship::Association")); - - if (srcAssociation.properties.size() != 2) - { - throw new EngineException("Expected 2 properties for an association '" + packageString + "'", srcAssociation.sourceInformation, EngineErrorType.COMPILATION); - } - return association._stereotypes(ListIterate.collect(srcAssociation.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) - ._taggedValues(ListIterate.collect(srcAssociation.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); - }, - (Association srcAssociation, CompileContext context) -> - { - String packageString = context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = context.pureModel.getAssociation(packageString, srcAssociation.sourceInformation); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class source = context.resolveClass(srcAssociation.properties.get(0).type, srcAssociation.properties.get(0).sourceInformation); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class target = context.resolveClass(srcAssociation.properties.get(1).type, srcAssociation.properties.get(1).sourceInformation); - - String property0Ref = context.pureModel.addPrefixToTypeReference(HelperModelBuilder.getElementFullPath(source, context.pureModel.getExecutionSupport())); - String property1Ref = context.pureModel.addPrefixToTypeReference(HelperModelBuilder.getElementFullPath(target, context.pureModel.getExecutionSupport())); - - // TODO generalize this validation to all platform/core types - if ("meta::pure::metamodel::type::Any".equals(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(source)) || - "meta::pure::metamodel::type::Any".equals(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(target))) - { - throw new EngineException("Associations to Any are not allowed. Found in '" + packageString + "'", srcAssociation.sourceInformation, EngineErrorType.COMPILATION); - } - - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property property1 = HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(property1Ref), association).valueOf(srcAssociation.properties.get(0)); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property property2 = HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(property0Ref), association).valueOf(srcAssociation.properties.get(1)); - - synchronized (source) - { - source._propertiesFromAssociationsAdd(property2); - } - synchronized (target) - { - target._propertiesFromAssociationsAdd(property1); - } - - ProcessingContext ctx = new ProcessingContext("Association " + packageString + " (second pass)"); - - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, property1Ref); - ctx.addInferredVariables("this", thisVariable); - - ListIterable> qualifiedProperties = ListIterate.collect(srcAssociation.qualifiedProperties, p -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class cl = context.resolveGenericType(p.returnType, p.sourceInformation)._rawType() == source ? target : source; - return HelperModelBuilder.processQualifiedPropertyFirstPass(context, association, org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(cl), ctx).valueOf(p); - }); - qualifiedProperties.forEach(q -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class _class = q._genericType()._rawType() == source ? target : source; - synchronized (_class) - { - _class._qualifiedPropertiesFromAssociationsAdd(q); - } - }); - ctx.flushVariable("this"); - association._originalMilestonedProperties(ListIterate.collect(srcAssociation.originalMilestonedProperties, HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(srcAssociation.properties.get(0).type), association))) - ._properties(Lists.mutable.with(property1, property2)) - ._qualifiedProperties(qualifiedProperties); - }, - (Association srcAssociation, CompileContext context) -> - { - String property0Ref = context.pureModel.addPrefixToTypeReference(srcAssociation.properties.get(0).type); - String property1Ref = context.pureModel.addPrefixToTypeReference(srcAssociation.properties.get(1).type); - - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = context.pureModel.getAssociation(context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name), srcAssociation.sourceInformation); - ProcessingContext ctx = new ProcessingContext("Association " + context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name) + " (third pass)"); - - ListIterate.collect(srcAssociation.qualifiedProperties, property -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, srcAssociation.properties.get(0).type.equals(property.returnType) ? property1Ref : property0Ref); - ctx.addInferredVariables("this", thisVariable); - ctx.push("Qualified Property " + property.name); - ListIterate.collect(property.parameters, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); - MutableList body = ListIterate.collect(property.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty prop = association._qualifiedProperties().detect(o -> o._name().equals(property.name)); - ctx.pop(); - ctx.flushVariable("this"); - return prop._expressionSequence(body); - }); - } + this::associationFirstPass, + this::associationSecondPass, + this::associationThirdPass ) ); } + + private PackageableElement associationFirstPass(Association srcAssociation, CompileContext context) + { + String packageString = context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = new Root_meta_pure_metamodel_relationship_Association_Impl(srcAssociation.name, null, context.pureModel.getClass("meta::pure::metamodel::relationship::Association")); + + if (srcAssociation.properties.size() != 2) + { + throw new EngineException("Expected 2 properties for an association '" + packageString + "'", srcAssociation.sourceInformation, EngineErrorType.COMPILATION); + } + return association._stereotypes(ListIterate.collect(srcAssociation.stereotypes, context::resolveStereotype)) + ._taggedValues(ListIterate.collect(srcAssociation.taggedValues, context::newTaggedValue)); + } + + private void associationSecondPass(Association srcAssociation, CompileContext context) + { + String packageString = context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = context.pureModel.getAssociation(packageString, srcAssociation.sourceInformation); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class source = context.resolveClass(srcAssociation.properties.get(0).type, srcAssociation.properties.get(0).sourceInformation); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class target = context.resolveClass(srcAssociation.properties.get(1).type, srcAssociation.properties.get(1).sourceInformation); + + String property0Ref = context.pureModel.addPrefixToTypeReference(HelperModelBuilder.getElementFullPath(source, context.pureModel.getExecutionSupport())); + String property1Ref = context.pureModel.addPrefixToTypeReference(HelperModelBuilder.getElementFullPath(target, context.pureModel.getExecutionSupport())); + + // TODO generalize this validation to all platform/core types + if ("meta::pure::metamodel::type::Any".equals(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(source)) || + "meta::pure::metamodel::type::Any".equals(org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(target))) + { + throw new EngineException("Associations to Any are not allowed. Found in '" + packageString + "'", srcAssociation.sourceInformation, EngineErrorType.COMPILATION); + } + + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property property1 = HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(property1Ref), association).valueOf(srcAssociation.properties.get(0)); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.Property property2 = HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(property0Ref), association).valueOf(srcAssociation.properties.get(1)); + + synchronized (source) + { + source._propertiesFromAssociationsAdd(property2); + } + synchronized (target) + { + target._propertiesFromAssociationsAdd(property1); + } + + ProcessingContext ctx = new ProcessingContext("Association " + packageString + " (second pass)"); + + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, property1Ref); + ctx.addInferredVariables("this", thisVariable); + + ListIterable> qualifiedProperties = ListIterate.collect(srcAssociation.qualifiedProperties, p -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class cl = context.resolveGenericType(p.returnType, p.sourceInformation)._rawType() == source ? target : source; + return HelperModelBuilder.processQualifiedPropertyFirstPass(context, association, org.finos.legend.pure.m3.navigation.PackageableElement.PackageableElement.getUserPathForPackageableElement(cl), ctx).valueOf(p); + }); + qualifiedProperties.forEach(q -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class _class = q._genericType()._rawType() == source ? target : source; + synchronized (_class) + { + _class._qualifiedPropertiesFromAssociationsAdd(q); + } + }); + ctx.flushVariable("this"); + association._originalMilestonedProperties(ListIterate.collect(srcAssociation.originalMilestonedProperties, HelperModelBuilder.processProperty(context, context.pureModel.getGenericTypeFromIndex(srcAssociation.properties.get(0).type), association))) + ._properties(Lists.mutable.with(property1, property2)) + ._qualifiedProperties(qualifiedProperties); + } + + private void associationThirdPass(Association srcAssociation, CompileContext context) + { + String property0Ref = context.pureModel.addPrefixToTypeReference(srcAssociation.properties.get(0).type); + String property1Ref = context.pureModel.addPrefixToTypeReference(srcAssociation.properties.get(1).type); + + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Association association = context.pureModel.getAssociation(context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name), srcAssociation.sourceInformation); + ProcessingContext ctx = new ProcessingContext("Association " + context.pureModel.buildPackageString(srcAssociation._package, srcAssociation.name) + " (third pass)"); + + ListIterate.collect(srcAssociation.qualifiedProperties, property -> + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, srcAssociation.properties.get(0).type.equals(property.returnType) ? property1Ref : property0Ref); + ctx.addInferredVariables("this", thisVariable); + ctx.push("Qualified Property " + property.name); + ListIterate.collect(property.parameters, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + MutableList body = ListIterate.collect(property.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty prop = association._qualifiedProperties().detect(o -> o._name().equals(property.name)); + ctx.pop(); + ctx.flushVariable("this"); + return prop._expressionSequence(body); + }); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java index f7751d9915b..3acd87d53eb 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ClassCompilerExtension.java @@ -30,6 +30,7 @@ import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_relationship_Generalization_Impl; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Class_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Generalization; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; @@ -55,7 +56,6 @@ public CompilerExtension build() return new ClassCompilerExtension(); } - @SuppressWarnings({"unchecked", "rawtypes"}) @Override public Iterable> getExtraProcessors() { @@ -63,111 +63,118 @@ public Iterable> getExtraProcessors() Processor.newProcessor( Class.class, Lists.fixedSize.with(Measure.class), - (Class srcClass, CompileContext context) -> - { - String fullPath = context.pureModel.buildPackageString(srcClass._package, srcClass.name); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class targetClass = new Root_meta_pure_metamodel_type_Class_Impl<>(srcClass.name, SourceInformationHelper.toM3SourceInformation(srcClass.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::type::Class")); - context.pureModel.typesIndex.put(fullPath, targetClass); - GenericType genericType = HelperCoreBuilder.newGenericType(targetClass, context); - context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); - return targetClass._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::metamodel::type::Class"), genericType, context)) - ._stereotypes(ListIterate.collect(srcClass.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) - ._taggedValues(ListIterate.collect(srcClass.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); - }, - (Class srcClass, CompileContext context) -> - { - String fullPath = context.pureModel.buildPackageString(srcClass._package, srcClass.name); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class _class = context.pureModel.getClass(fullPath, srcClass.sourceInformation); - GenericType _classGenericType = context.resolveGenericType(fullPath, srcClass.sourceInformation); - Set uniqueSuperTypes = Sets.mutable.empty(); - MutableList generalization = ListIterate.collect(srcClass.superTypes, superTypePtr -> - { - String superType = superTypePtr.path; - // validate no duplicated class supertype - if (!uniqueSuperTypes.add(superType)) - { - throw new EngineException("Duplicated super type '" + superType + "' in class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "'", srcClass.sourceInformation, EngineErrorType.COMPILATION); - } - Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", SourceInformationHelper.toM3SourceInformation(superTypePtr.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization"))._general(context.resolveGenericType(superType, superTypePtr.sourceInformation))._specific(_class); - if (!context.pureModel.isImmutable(superType)) - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class superTypeClass; - Type type = context.resolveType(superType, superTypePtr.sourceInformation); - try - { - superTypeClass = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class) type; - } - catch (ClassCastException e) - { - throw new EngineException("Invalid supertype: '" + srcClass.name + "' cannot extend '" + superType + "' as it is not a class.", srcClass.sourceInformation, EngineErrorType.COMPILATION); - } - synchronized (superTypeClass) - { - superTypeClass._specializationsAdd(g); - } - } - return g; - }); - - MutableList> properties = ListIterate.collect(srcClass.properties, HelperModelBuilder.processProperty(context, _classGenericType, _class)); - MutableList> restrictedMilestoningProperties = Milestoning.restrictedMilestoningProperties(_class, srcClass, properties, context.pureModel); - MutableList> withMilestoningProperties = properties.select(p -> !restrictedMilestoningProperties.contains(p)).withAll(Milestoning.generateMilestoningProperties(_class, context)); - - ProcessingContext ctx = new ProcessingContext("Class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' Second Pass"); - ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, context.pureModel.buildPackageString(srcClass._package, srcClass.name)); - ctx.addInferredVariables("this", thisVariable); - - RichIterable> qualifiedProperties = ListIterate.collect(srcClass.qualifiedProperties, HelperModelBuilder.processQualifiedPropertyFirstPass(context, _class, context.pureModel.buildPackageString(srcClass._package, srcClass.name), ctx)); - _class._originalMilestonedProperties(ListIterate.collect(srcClass.originalMilestonedProperties, HelperModelBuilder.processProperty(context, _classGenericType, _class))) - ._generalizations(generalization) - ._qualifiedProperties(qualifiedProperties) - ._properties(withMilestoningProperties); - if (_class._generalizations().isEmpty()) - { - Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization")) - ._general(context.pureModel.getGenericType("meta::pure::metamodel::type::Any")) - ._specific(_class); - _class._generalizationsAdd(g); - } - ctx.flushVariable("this"); - }, - (Class srcClass, CompileContext context) -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class targetClass = context.pureModel.getClass(context.pureModel.buildPackageString(srcClass._package, srcClass.name), srcClass.sourceInformation); - - ProcessingContext ctx = new ProcessingContext("Class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' Third Pass"); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, context.pureModel.buildPackageString(srcClass._package, srcClass.name)); - - ListIterate.collect(srcClass.qualifiedProperties, property -> - { - ctx.push("Qualified Property " + property.name); - ctx.addInferredVariables("this", thisVariable); - MutableList body; - try - { - property.parameters.forEach(p -> p.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); - body = ListIterate.collect(property.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); - } - catch (Exception e) - { - LOGGER.warn(new LogInfo(Identity.getAnonymousIdentity().getName(), LoggingEventType.GRAPH_EXPRESSION_ERROR, "Can't build derived property '" + property.name + " of class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' - stack: " + ctx.getStack()).toString()); - if (e instanceof EngineException) - { - throw e; - } - e.printStackTrace(); - throw new EngineException(e.getMessage(), property.sourceInformation, EngineErrorType.COMPILATION); - } - ctx.flushVariable("this"); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty prop = targetClass._qualifiedProperties().detect(o -> HelperModelBuilder.isCompatibleDerivedProperty(o, property)); - HelperModelBuilder.checkCompatibility(context, body.getLast()._genericType()._rawType(), body.getLast()._multiplicity(), prop._genericType()._rawType(), prop._multiplicity(), "Error in derived property '" + srcClass.name + "." + property.name + "'", property.body.get(property.body.size() - 1).sourceInformation); - ctx.pop(); - return prop._expressionSequence(body); - }); - - HelperModelBuilder.processClassConstraints(srcClass, context, targetClass, ctx, thisVariable); - } + this::classFirstPass, + this::classSecondPass, + this::classThirdPass ) ); } + + private PackageableElement classFirstPass(Class srcClass, CompileContext context) + { + String fullPath = context.pureModel.buildPackageString(srcClass._package, srcClass.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class targetClass = new Root_meta_pure_metamodel_type_Class_Impl<>(srcClass.name, SourceInformationHelper.toM3SourceInformation(srcClass.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::type::Class")); + context.pureModel.typesIndex.put(fullPath, targetClass); + GenericType genericType = context.newGenericType(targetClass);; + context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); + return targetClass._classifierGenericType(context.newGenericType(context.pureModel.getType("meta::pure::metamodel::type::Class"), genericType)) + ._stereotypes(ListIterate.collect(srcClass.stereotypes, context::resolveStereotype)) + ._taggedValues(ListIterate.collect(srcClass.taggedValues, context::newTaggedValue)); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + private void classSecondPass(Class srcClass, CompileContext context) + { + String fullPath = context.pureModel.buildPackageString(srcClass._package, srcClass.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class _class = context.pureModel.getClass(fullPath, srcClass.sourceInformation); + GenericType _classGenericType = context.resolveGenericType(fullPath, srcClass.sourceInformation); + Set uniqueSuperTypes = Sets.mutable.empty(); + MutableList generalization = ListIterate.collect(srcClass.superTypes, superTypePtr -> + { + String superType = superTypePtr.path; + // validate no duplicated class supertype + if (!uniqueSuperTypes.add(superType)) + { + throw new EngineException("Duplicated super type '" + superType + "' in class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "'", srcClass.sourceInformation, EngineErrorType.COMPILATION); + } + Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", SourceInformationHelper.toM3SourceInformation(superTypePtr.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization"))._general(context.resolveGenericType(superType, superTypePtr.sourceInformation))._specific(_class); + if (!context.pureModel.isImmutable(superType)) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class superTypeClass; + Type type = context.resolveType(superType, superTypePtr.sourceInformation); + try + { + superTypeClass = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class) type; + } + catch (ClassCastException e) + { + throw new EngineException("Invalid supertype: '" + srcClass.name + "' cannot extend '" + superType + "' as it is not a class.", srcClass.sourceInformation, EngineErrorType.COMPILATION); + } + synchronized (superTypeClass) + { + superTypeClass._specializationsAdd(g); + } + } + return g; + }); + + MutableList> properties = ListIterate.collect(srcClass.properties, HelperModelBuilder.processProperty(context, _classGenericType, _class)); + MutableList> restrictedMilestoningProperties = Milestoning.restrictedMilestoningProperties(_class, srcClass, properties, context.pureModel); + MutableList> withMilestoningProperties = properties.select(p -> !restrictedMilestoningProperties.contains(p)).withAll(Milestoning.generateMilestoningProperties(_class, context)); + + ProcessingContext ctx = new ProcessingContext("Class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' Second Pass"); + ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, context.pureModel.buildPackageString(srcClass._package, srcClass.name)); + ctx.addInferredVariables("this", thisVariable); + + RichIterable> qualifiedProperties = ListIterate.collect(srcClass.qualifiedProperties, HelperModelBuilder.processQualifiedPropertyFirstPass(context, _class, context.pureModel.buildPackageString(srcClass._package, srcClass.name), ctx)); + _class._originalMilestonedProperties(ListIterate.collect(srcClass.originalMilestonedProperties, HelperModelBuilder.processProperty(context, _classGenericType, _class))) + ._generalizations(generalization) + ._qualifiedProperties(qualifiedProperties) + ._properties(withMilestoningProperties); + if (_class._generalizations().isEmpty()) + { + Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization")) + ._general(context.pureModel.getGenericType("meta::pure::metamodel::type::Any")) + ._specific(_class); + _class._generalizationsAdd(g); + } + ctx.flushVariable("this"); + } + + private void classThirdPass(Class srcClass, CompileContext context) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Class targetClass = context.pureModel.getClass(context.pureModel.buildPackageString(srcClass._package, srcClass.name), srcClass.sourceInformation); + + ProcessingContext ctx = new ProcessingContext("Class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' Third Pass"); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification thisVariable = HelperModelBuilder.createThisVariableForClass(context, context.pureModel.buildPackageString(srcClass._package, srcClass.name)); + + ListIterate.collect(srcClass.qualifiedProperties, property -> + { + ctx.push("Qualified Property " + property.name); + ctx.addInferredVariables("this", thisVariable); + MutableList body; + try + { + property.parameters.forEach(p -> p.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + body = ListIterate.collect(property.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + } + catch (Exception e) + { + LOGGER.warn(new LogInfo(Identity.getAnonymousIdentity().getName(), LoggingEventType.GRAPH_EXPRESSION_ERROR, "Can't build derived property '" + property.name + " of class '" + context.pureModel.buildPackageString(srcClass._package, srcClass.name) + "' - stack: " + ctx.getStack()).toString()); + if (e instanceof EngineException) + { + throw e; + } + e.printStackTrace(); + throw new EngineException(e.getMessage(), property.sourceInformation, EngineErrorType.COMPILATION); + } + ctx.flushVariable("this"); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.property.QualifiedProperty prop = targetClass._qualifiedProperties().detect(o -> HelperModelBuilder.isCompatibleDerivedProperty(o, property)); + HelperModelBuilder.checkCompatibility(context, body.getLast()._genericType()._rawType(), body.getLast()._multiplicity(), prop._genericType()._rawType(), prop._multiplicity(), "Error in derived property '" + srcClass.name + "." + property.name + "'", property.body.get(property.body.size() - 1).sourceInformation); + ctx.pop(); + return prop._expressionSequence(body); + }); + + HelperModelBuilder.processClassConstraints(srcClass, context, targetClass, ctx, thisVariable); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java index 3b4bfa7f02f..eefe4c39f5e 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java @@ -14,6 +14,8 @@ package org.finos.legend.engine.language.pure.compiler.toPureGraph; +import org.eclipse.collections.api.RichIterable; +import org.eclipse.collections.api.factory.Lists; import org.eclipse.collections.api.factory.Maps; import org.eclipse.collections.api.factory.Sets; import org.eclipse.collections.api.list.MutableList; @@ -27,22 +29,27 @@ import org.finos.legend.engine.protocol.pure.v1.model.context.EngineErrorType; import org.finos.legend.engine.protocol.pure.v1.model.context.PackageableElementPointer; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.StereotypePtr; +import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.TagPtr; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.ImportAwareCodeSection; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.Section; import org.finos.legend.engine.shared.core.deployment.DeploymentMode; import org.finos.legend.engine.shared.core.identity.Identity; -import org.finos.legend.engine.shared.core.identity.factory.*; import org.finos.legend.engine.shared.core.operational.errorManagement.EngineException; import org.finos.legend.engine.shared.core.operational.logs.LogInfo; import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; import org.finos.legend.pure.generated.Root_meta_core_runtime_Connection; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_TaggedValue_Impl; +import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_generics_GenericType_Impl; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableConnection; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime; import org.finos.legend.pure.generated.Root_meta_core_runtime_Runtime; import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.TaggedValue; 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.m3.coreinstance.meta.pure.metamodel.type.Measure; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Unit; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.SimpleFunctionExpression; @@ -166,6 +173,21 @@ public Processor getExtraProcessorOrThrow(PackageableElement element) return getCompilerExtensions().getExtraProcessorOrThrow(element); } + public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + { + return getExtraProcessorOrThrow(element).processFirstPass(element, this); + } + + public void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + { + getExtraProcessorOrThrow(element).processSecondPass(element, this); + } + + public void processThirdPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + { + getExtraProcessorOrThrow(element).processSecondPass(element, this); + } + public T resolve(String path, SourceInformation sourceInformation, Function resolver) { if (path == null) @@ -377,6 +399,11 @@ public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enum resol return this.pureModel.getEnumValue(this.resolveEnumeration(fullPath, enumerationSourceInformation), fullPath, value, sourceInformation); } + public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype resolveStereotype(StereotypePtr stereotypePointer) + { + return this.resolveStereotype(stereotypePointer.profile, stereotypePointer.value, stereotypePointer.profileSourceInformation, stereotypePointer.sourceInformation); + } + public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype resolveStereotype(String fullPath, String value) { return this.resolveStereotype(fullPath, value, SourceInformation.getUnknownSourceInformation(), SourceInformation.getUnknownSourceInformation()); @@ -387,6 +414,11 @@ public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stere return this.pureModel.getStereotype(this.resolveProfile(fullPath, profileSourceInformation), fullPath, value, sourceInformation); } + public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag resolveTag(TagPtr tagPointer) + { + return this.resolveTag(tagPointer.profile, tagPointer.value, tagPointer.profileSourceInformation, tagPointer.sourceInformation); + } + public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag resolveTag(String fullPath, String value, SourceInformation profileSourceInformation, SourceInformation sourceInformation) { return this.pureModel.getTag(this.resolveProfile(fullPath, profileSourceInformation), fullPath, value, sourceInformation); @@ -491,4 +523,30 @@ private MutableMap searchImports(String name, Function }); return results; } + + + // ------------------------------------------ SUB-ELEMENT UTILITY ----------------------------------------- + + public GenericType newGenericType(Type rawType) + { + return new Root_meta_pure_metamodel_type_generics_GenericType_Impl("", null, this.pureModel.getClass("meta::pure::metamodel::type::generics::GenericType")) + ._rawType(rawType); + } + + public GenericType newGenericType(Type rawType, GenericType typeArgument) + { + return newGenericType(rawType, Lists.fixedSize.with(typeArgument)); + } + + public GenericType newGenericType(Type rawType, RichIterable typeArguments) + { + return newGenericType(rawType)._typeArguments(typeArguments); + } + + public TaggedValue newTaggedValue(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.TaggedValue taggedValue) + { + return new Root_meta_pure_metamodel_extension_TaggedValue_Impl("", null, this.pureModel.getClass("meta::pure::metamodel::extension::TaggedValue")) + ._tag(resolveTag(taggedValue.tag)) + ._value(taggedValue.value); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java index 83ac65bc0f4..7f3161235eb 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/DataElementCompilerExtension.java @@ -27,6 +27,7 @@ import org.finos.legend.pure.generated.Root_meta_pure_data_DataElementReference; import org.finos.legend.pure.generated.Root_meta_pure_data_DataElement_Impl; import org.finos.legend.pure.generated.Root_meta_pure_data_EmbeddedData; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; public class DataElementCompilerExtension implements CompilerExtension @@ -49,28 +50,32 @@ public Iterable> getExtraProcessors() return Lists.fixedSize.of( Processor.newProcessor( DataElement.class, - (DataElement dataElement, CompileContext context) -> - { - Root_meta_pure_data_DataElement compiled = new Root_meta_pure_data_DataElement_Impl(dataElement.name, SourceInformationHelper.toM3SourceInformation(dataElement.sourceInformation), null); - GenericType mappingGenericType = HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::data::DataElement"), context); - return compiled._classifierGenericType(mappingGenericType) - ._stereotypes(ListIterate.collect(dataElement.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) - ._taggedValues(ListIterate.collect(dataElement.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); - }, - (DataElement dataElement, CompileContext context) -> - { - String fullPath = context.pureModel.buildPackageString(dataElement._package, dataElement.name); - Root_meta_pure_data_DataElement compiled = (Root_meta_pure_data_DataElement) context.pureModel.getPackageableElement(fullPath); - - ProcessingContext processingContext = new ProcessingContext("Data '" + fullPath + "' Second Pass"); - Root_meta_pure_data_EmbeddedData compiledData = dataElement.data.accept(new EmbeddedDataFirstPassBuilder(context, processingContext)); - if (compiledData instanceof Root_meta_pure_data_DataElementReference) - { - throw new EngineException("Cannot use Data element reference in a Data element", dataElement.data.sourceInformation, EngineErrorType.COMPILATION); - } - compiled._data(compiledData); - } + this::dataElementFirstPass, + this::dataElementSecondPass ) ); } + + private PackageableElement dataElementFirstPass(DataElement dataElement, CompileContext context) + { + Root_meta_pure_data_DataElement compiled = new Root_meta_pure_data_DataElement_Impl(dataElement.name, SourceInformationHelper.toM3SourceInformation(dataElement.sourceInformation), null); + GenericType mappingGenericType = context.newGenericType(context.pureModel.getType("meta::pure::data::DataElement")); + return compiled._classifierGenericType(mappingGenericType) + ._stereotypes(ListIterate.collect(dataElement.stereotypes, context::resolveStereotype)) + ._taggedValues(ListIterate.collect(dataElement.taggedValues, context::newTaggedValue)); + } + + private void dataElementSecondPass(DataElement dataElement, CompileContext context) + { + String fullPath = context.pureModel.buildPackageString(dataElement._package, dataElement.name); + Root_meta_pure_data_DataElement compiled = (Root_meta_pure_data_DataElement) context.pureModel.getPackageableElement(fullPath); + + ProcessingContext processingContext = new ProcessingContext("Data '" + fullPath + "' Second Pass"); + Root_meta_pure_data_EmbeddedData compiledData = dataElement.data.accept(new EmbeddedDataFirstPassBuilder(context, processingContext)); + if (compiledData instanceof Root_meta_pure_data_DataElementReference) + { + throw new EngineException("Cannot use Data element reference in a Data element", dataElement.data.sourceInformation, EngineErrorType.COMPILATION); + } + compiled._data(compiledData); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java index 47a8d6b7e64..6a2bcda0551 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/EnumerationCompilerExtension.java @@ -23,6 +23,7 @@ import org.finos.legend.pure.generated.Root_meta_pure_metamodel_relationship_Generalization_Impl; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Enum_Impl; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Enumeration_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.relationship.Generalization; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; @@ -46,34 +47,38 @@ public Iterable> getExtraProcessors() return Lists.fixedSize.of( Processor.newProcessor( Enumeration.class, - (Enumeration enumeration, CompileContext context) -> - { - String fullPath = context.pureModel.buildPackageString(enumeration._package, enumeration.name); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration en = new Root_meta_pure_metamodel_type_Enumeration_Impl<>(enumeration.name, SourceInformationHelper.toM3SourceInformation(enumeration.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::type::Enumeration")); - context.pureModel.typesIndex.put(fullPath, en); - GenericType genericType = HelperCoreBuilder.newGenericType(en, context); - context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); - return en._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getClass("meta::pure::metamodel::type::Enumeration"), genericType, context)) - ._stereotypes(ListIterate.collect(enumeration.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) - ._taggedValues(ListIterate.collect(enumeration.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))) - ._values(ListIterate.collect(enumeration.values, v -> new Root_meta_pure_metamodel_type_Enum_Impl(v.value, SourceInformationHelper.toM3SourceInformation(v.sourceInformation), null) - ._classifierGenericType(genericType) - ._stereotypes(ListIterate.collect(v.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) - ._taggedValues(ListIterate.collect(v.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))) - ._name(v.value))); - }, - (Enumeration enumeration, CompileContext context) -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration targetEnum = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration) context.pureModel.getType(context.pureModel.buildPackageString(enumeration._package, enumeration.name), enumeration.sourceInformation); - if (targetEnum._generalizations().isEmpty()) - { - Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization")) - ._general(context.pureModel.getGenericType("meta::pure::metamodel::type::Any")) - ._specific(targetEnum); - targetEnum._generalizationsAdd(g); - } - } + this::enumerationFirstPass, + this::enumerationSecondPass ) ); } + + private PackageableElement enumerationFirstPass(Enumeration enumeration, CompileContext context) + { + String fullPath = context.pureModel.buildPackageString(enumeration._package, enumeration.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration en = new Root_meta_pure_metamodel_type_Enumeration_Impl<>(enumeration.name, SourceInformationHelper.toM3SourceInformation(enumeration.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::type::Enumeration")); + context.pureModel.typesIndex.put(fullPath, en); + GenericType genericType = context.newGenericType(en); + context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); + return en._classifierGenericType(context.newGenericType(context.pureModel.getClass("meta::pure::metamodel::type::Enumeration"), genericType)) + ._stereotypes(ListIterate.collect(enumeration.stereotypes, context::resolveStereotype)) + ._taggedValues(ListIterate.collect(enumeration.taggedValues, context::newTaggedValue)) + ._values(ListIterate.collect(enumeration.values, v -> new Root_meta_pure_metamodel_type_Enum_Impl(v.value, SourceInformationHelper.toM3SourceInformation(v.sourceInformation), null) + ._classifierGenericType(genericType) + ._stereotypes(ListIterate.collect(v.stereotypes, context::resolveStereotype)) + ._taggedValues(ListIterate.collect(v.taggedValues, context::newTaggedValue)) + ._name(v.value))); + } + + private void enumerationSecondPass(Enumeration enumeration, CompileContext context) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration targetEnum = (org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Enumeration) context.pureModel.getType(context.pureModel.buildPackageString(enumeration._package, enumeration.name), enumeration.sourceInformation); + if (targetEnum._generalizations().isEmpty()) + { + Generalization g = new Root_meta_pure_metamodel_relationship_Generalization_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::relationship::Generalization")) + ._general(context.pureModel.getGenericType("meta::pure::metamodel::type::Any")) + ._specific(targetEnum); + targetEnum._generalizationsAdd(g); + } + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java index ce31240fae0..6fa8c1dad6b 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/FunctionCompilerExtension.java @@ -31,6 +31,7 @@ import org.finos.legend.engine.shared.core.operational.logs.LogInfo; import org.finos.legend.engine.shared.core.operational.logs.LoggingEventType; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_function_ConcreteFunctionDefinition_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.FunctionType; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.ValueSpecification; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.valuespecification.VariableExpression; @@ -61,75 +62,79 @@ public Iterable> getExtraProcessors() Processor.newProcessor( Function.class, Lists.fixedSize.with(DataElement.class, Class.class, Association.class, Mapping.class, Binding.class), + this::functionFirstPass, (Function function, CompileContext context) -> { - // NOTE: in the protocol, we still store the function name as is, but in the function index, we will store the function based on its function signature - String functionSignature = HelperModelBuilder.getSignature(function); - String functionFullName = context.pureModel.buildPackageString(function._package, functionSignature); - String functionName = context.pureModel.buildPackageString(function._package, HelperModelBuilder.getFunctionNameWithoutSignature(function)); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition targetFunc = new Root_meta_pure_metamodel_function_ConcreteFunctionDefinition_Impl<>(functionSignature, SourceInformationHelper.toM3SourceInformation(function.sourceInformation), null); + }, + this::functionThirdPass + ) + ); + } - ProcessingContext ctx = new ProcessingContext("Function '" + functionFullName + "' First Pass"); + private PackageableElement functionFirstPass(Function function, CompileContext context) + { + // NOTE: in the protocol, we still store the function name as is, but in the function index, we will store the function based on its function signature + String functionSignature = HelperModelBuilder.getSignature(function); + String functionFullName = context.pureModel.buildPackageString(function._package, functionSignature); + String functionName = context.pureModel.buildPackageString(function._package, HelperModelBuilder.getFunctionNameWithoutSignature(function)); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition targetFunc = new Root_meta_pure_metamodel_function_ConcreteFunctionDefinition_Impl<>(functionSignature, SourceInformationHelper.toM3SourceInformation(function.sourceInformation), null); - context.pureModel.setNameAndPackage(targetFunc, functionSignature, function._package, function.sourceInformation) - ._functionName(functionName) // function name to be used in the handler map -> meta::pure::functions::date::isAfterDay - ._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::metamodel::function::ConcreteFunctionDefinition"), PureModel.buildFunctionType(ListIterate.collect(function.parameters, p -> (VariableExpression) p.accept(new ValueSpecificationBuilder(context, Lists.mutable.empty(), ctx))), context.resolveGenericType(function.returnType, function.sourceInformation), context.pureModel.getMultiplicity(function.returnMultiplicity), context.pureModel), context)) - ._stereotypes(ListIterate.collect(function.stereotypes, stereotype -> HelperCoreBuilder.resolveStereotype(stereotype, context))) - ._taggedValues(ListIterate.collect(function.taggedValues, taggedValue -> HelperCoreBuilder.newTaggedValue(taggedValue, context))); - HelperModelBuilder.processFunctionConstraints(function, context, targetFunc, ctx); + ProcessingContext ctx = new ProcessingContext("Function '" + functionFullName + "' First Pass"); - context.pureModel.handlers.register(new UserDefinedFunctionHandler(context.pureModel, functionFullName, targetFunc, - ps -> new TypeAndMultiplicity(context.resolveGenericType(function.returnType, function.sourceInformation), context.pureModel.getMultiplicity(function.returnMultiplicity)), - ps -> - { - List vs = ListIterate.collect(function.parameters, p -> p.accept(new ValueSpecificationBuilder(context, Lists.mutable.empty(), ctx))); - if (ps.size() == function.parameters.size()) - { - int size = ps.size(); - // TODO clean up the check.... - try - { - for (int i = 0; i < size; i++) - { - HelperModelBuilder.checkCompatibility(context, ps.get(i)._genericType()._rawType(), ps.get(i)._multiplicity(), vs.get(i)._genericType()._rawType(), vs.get(i)._multiplicity(), "Error in function '" + functionFullName + "'", function.body.get(function.body.size() - 1).sourceInformation); - } - } - catch (Exception e) - { - return false; - } - return true; - } - return false; - })); - return targetFunc; - }, - (Function function, CompileContext context) -> - { - }, - (Function function, CompileContext context) -> + context.pureModel.setNameAndPackage(targetFunc, functionSignature, function._package, function.sourceInformation) + ._functionName(functionName) // function name to be used in the handler map -> meta::pure::functions::date::isAfterDay + ._classifierGenericType(context.newGenericType(context.pureModel.getType("meta::pure::metamodel::function::ConcreteFunctionDefinition"), PureModel.buildFunctionType(ListIterate.collect(function.parameters, p -> (VariableExpression) p.accept(new ValueSpecificationBuilder(context, Lists.mutable.empty(), ctx))), context.resolveGenericType(function.returnType, function.sourceInformation), context.pureModel.getMultiplicity(function.returnMultiplicity), context.pureModel))) + ._stereotypes(ListIterate.collect(function.stereotypes, context::resolveStereotype)) + ._taggedValues(ListIterate.collect(function.taggedValues, context::newTaggedValue)); + HelperModelBuilder.processFunctionConstraints(function, context, targetFunc, ctx); + + context.pureModel.handlers.register(new UserDefinedFunctionHandler(context.pureModel, functionFullName, targetFunc, + ps -> new TypeAndMultiplicity(context.resolveGenericType(function.returnType, function.sourceInformation), context.pureModel.getMultiplicity(function.returnMultiplicity)), + ps -> + { + List vs = ListIterate.collect(function.parameters, p -> p.accept(new ValueSpecificationBuilder(context, Lists.mutable.empty(), ctx))); + if (ps.size() == function.parameters.size()) + { + int size = ps.size(); + // TODO clean up the check.... + try { - String packageString = context.pureModel.buildPackageString(function._package, HelperModelBuilder.getSignature(function)); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition targetFunc = context.pureModel.getConcreteFunctionDefinition(packageString, function.sourceInformation); - ProcessingContext ctx = new ProcessingContext("Function '" + packageString + "' Third Pass"); - MutableList body; - try - { - function.parameters.forEach(p -> p.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); - body = ListIterate.collect(function.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); - } - catch (Exception e) + for (int i = 0; i < size; i++) { - LOGGER.warn(new LogInfo(Identity.getAnonymousIdentity().getName(), LoggingEventType.GRAPH_EXPRESSION_ERROR, "Can't build function '" + packageString + "' - stack: " + ctx.getStack()).toString()); - throw e; + HelperModelBuilder.checkCompatibility(context, ps.get(i)._genericType()._rawType(), ps.get(i)._multiplicity(), vs.get(i)._genericType()._rawType(), vs.get(i)._multiplicity(), "Error in function '" + functionFullName + "'", function.body.get(function.body.size() - 1).sourceInformation); } - FunctionType fType = ((FunctionType) targetFunc._classifierGenericType()._typeArguments().getFirst()._rawType()); - HelperModelBuilder.checkCompatibility(context, body.getLast()._genericType()._rawType(), body.getLast()._multiplicity(), fType._returnType()._rawType(), fType._returnMultiplicity(), "Error in function '" + packageString + "'", function.body.get(function.body.size() - 1).sourceInformation); - ctx.pop(); - targetFunc._expressionSequence(body); - HelperFunctionBuilder.processFunctionSuites(function, targetFunc, context, ctx); } - ) - ); + catch (Exception e) + { + return false; + } + return true; + } + return false; + })); + return targetFunc; + } + + private void functionThirdPass(Function function, CompileContext context) + { + String packageString = context.pureModel.buildPackageString(function._package, HelperModelBuilder.getSignature(function)); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition targetFunc = context.pureModel.getConcreteFunctionDefinition(packageString, function.sourceInformation); + ProcessingContext ctx = new ProcessingContext("Function '" + packageString + "' Third Pass"); + MutableList body; + try + { + function.parameters.forEach(p -> p.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + body = ListIterate.collect(function.body, expression -> expression.accept(new ValueSpecificationBuilder(context, org.eclipse.collections.api.factory.Lists.mutable.empty(), ctx))); + } + catch (Exception e) + { + LOGGER.warn(new LogInfo(Identity.getAnonymousIdentity().getName(), LoggingEventType.GRAPH_EXPRESSION_ERROR, "Can't build function '" + packageString + "' - stack: " + ctx.getStack()).toString()); + throw e; + } + FunctionType fType = ((FunctionType) targetFunc._classifierGenericType()._typeArguments().getFirst()._rawType()); + HelperModelBuilder.checkCompatibility(context, body.getLast()._genericType()._rawType(), body.getLast()._multiplicity(), fType._returnType()._rawType(), fType._returnMultiplicity(), "Error in function '" + packageString + "'", function.body.get(function.body.size() - 1).sourceInformation); + ctx.pop(); + targetFunc._expressionSequence(body); + HelperFunctionBuilder.processFunctionSuites(function, targetFunc, context, ctx); } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java deleted file mode 100644 index e4191387a3a..00000000000 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperCoreBuilder.java +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2024 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.language.pure.compiler.toPureGraph; - -import org.eclipse.collections.api.RichIterable; -import org.eclipse.collections.api.factory.Lists; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.StereotypePtr; -import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.TagPtr; -import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_TaggedValue_Impl; -import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_generics_GenericType_Impl; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.TaggedValue; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Type; -import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; - -public class HelperCoreBuilder -{ - protected static GenericType newGenericType(Type rawType, CompileContext context) - { - return new Root_meta_pure_metamodel_type_generics_GenericType_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::type::generics::GenericType")) - ._rawType(rawType); - } - - protected static GenericType newGenericType(Type rawType, GenericType typeArgument, CompileContext context) - { - return newGenericType(rawType, Lists.fixedSize.with(typeArgument), context); - } - - private static GenericType newGenericType(Type rawType, RichIterable typeArguments, CompileContext context) - { - return newGenericType(rawType, context)._typeArguments(typeArguments); - } - - protected static TaggedValue newTaggedValue(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.TaggedValue taggedValue, CompileContext context) - { - return new Root_meta_pure_metamodel_extension_TaggedValue_Impl("", null, context.pureModel.getClass("meta::pure::metamodel::extension::TaggedValue")) - ._tag(resolveTag(taggedValue.tag, context)) - ._value(taggedValue.value); - } - - private static Tag resolveTag(TagPtr tagPointer, CompileContext context) - { - return context.resolveTag(tagPointer.profile, tagPointer.value, tagPointer.profileSourceInformation, tagPointer.sourceInformation); - } - - protected static Stereotype resolveStereotype(StereotypePtr stereotypePointer, CompileContext context) - { - return context.resolveStereotype(stereotypePointer.profile, stereotypePointer.value, stereotypePointer.profileSourceInformation, stereotypePointer.sourceInformation); - } -} diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java index 072c2817b0e..fd7c68ef5b9 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperMappingBuilder.java @@ -378,7 +378,7 @@ public static Root_meta_pure_mapping_MappingClass_Impl processMappingClass(org.f org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Class rootClass = mappingclass.rootClass; if (rootClass != null) { - context.pureModel.processThirdPass(rootClass); + context.processThirdPass(rootClass); mappingClass._class(context.pureModel.getClass(context.pureModel.buildPackageString(rootClass._package, rootClass.name), rootClass.sourceInformation)); } return mappingClass; diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java index 45acd924bf5..00428894094 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MappingCompilerExtension.java @@ -39,6 +39,7 @@ import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.EnumerationMapping; import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.MappingIncludeAccessor; import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.SetImplementation; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; import java.util.Set; @@ -64,79 +65,87 @@ public Iterable> getExtraProcessors() Processor.newProcessor( Mapping.class, Lists.fixedSize.with(Enumeration.class, Class.class, Association.class, Binding.class, Store.class), - (Mapping mapping, CompileContext context) -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = new Root_meta_pure_mapping_Mapping_Impl(mapping.name, SourceInformationHelper.toM3SourceInformation(mapping.sourceInformation), context.pureModel.getClass("meta::pure::mapping::Mapping")); - GenericType mappingGenericType = HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::mapping::Mapping"), context); - return pureMapping._classifierGenericType(mappingGenericType); - }, - (Mapping mapping, CompileContext context) -> - { - final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); - RichIterable> enumerationMappings = ListIterate.collect(mapping.enumerationMappings, em -> HelperMappingBuilder.processEnumMapping(em, pureMapping, context)); - if (!mapping.includedMappings.isEmpty()) - { - CompilerExtensions extensions = context.pureModel.extensions; - RichIterable mappingIncludes = - ListIterate.collect(mapping.includedMappings, i -> - { - IncludedMappingHandler handler = extensions.getExtraIncludedMappingHandlers(i.getClass().getName()); - return handler.processMappingInclude(i, context, pureMapping, - handler.resolveMapping(i, context)); - }); - pureMapping._includesAddAll(mappingIncludes); - // validate no duplicated included mappings - Set uniqueMappingIncludes = Sets.mutable.empty(); - mappingIncludes.forEach(includedMapping -> - { - String mappingName = IncludedMappingHandler.parseIncludedMappingNameRecursively(includedMapping); - if (!uniqueMappingIncludes.add(mappingName)) - { - throw new EngineException("Duplicated mapping include '" + mappingName + - "' in " + "mapping " + - "'" + context.pureModel.buildPackageString(mapping._package, mapping.name) + "'", mapping.sourceInformation, EngineErrorType.COMPILATION); - } - }); - } - if (!enumerationMappings.isEmpty()) - { - pureMapping._enumerationMappings(enumerationMappings); - } - }, - (Mapping mapping, CompileContext context) -> - { - final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); - if (mapping.classMappings != null && pureMapping._classMappings().isEmpty()) - { - RichIterable>> setImplementations = ListIterate.collect(mapping.classMappings, cm -> cm.accept(new ClassMappingFirstPassBuilder(context, pureMapping))); - pureMapping._classMappingsAddAll(setImplementations.flatCollect(p -> org.eclipse.collections.impl.factory.Lists.mutable.with(p.getOne()).withAll(p.getTwo()))); - } - if (!mapping.tests.isEmpty()) - { - mapping.tests.forEach(t -> HelperMappingBuilder.processMappingTest(t, context)); - } - if (mapping.testSuites != null) - { - TestBuilderHelper.validateTestSuiteIdsList(mapping.testSuites, mapping.sourceInformation); - pureMapping._tests(ListIterate.collect(mapping.testSuites, suite -> HelperMappingBuilder.processMappingTestAndTestSuite(suite, pureMapping, context))); - } - if (mapping.associationMappings != null) - { - RichIterable associationImplementations = ListIterate.collect(mapping.associationMappings, cm -> HelperMappingBuilder.processAssociationImplementation(cm, context, pureMapping)); - pureMapping._associationMappings(associationImplementations); - } - if (mapping.classMappings != null) - { - mapping.classMappings.forEach(cm -> cm.accept(new ClassMappingSecondPassBuilder(context, pureMapping))); - mapping.classMappings.forEach(cm -> cm.accept(new ClassMappingThirdPassBuilder(context, pureMapping))); - } - }, - (Mapping mapping, CompileContext context) -> - { - final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); - return pureMapping._includes().collect(MappingIncludeAccessor::_included); - } + this::mappingFirstPass, + this::mappingSecondPass, + this::mappingThirdPass, + this::mappingPrerequisiteElementsPass ) ); } + + private PackageableElement mappingFirstPass(Mapping mapping, CompileContext context) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = new Root_meta_pure_mapping_Mapping_Impl(mapping.name, SourceInformationHelper.toM3SourceInformation(mapping.sourceInformation), context.pureModel.getClass("meta::pure::mapping::Mapping")); + GenericType mappingGenericType = context.newGenericType(context.pureModel.getType("meta::pure::mapping::Mapping")); + return pureMapping._classifierGenericType(mappingGenericType); + } + + private void mappingSecondPass(Mapping mapping, CompileContext context) + { + final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); + RichIterable> enumerationMappings = ListIterate.collect(mapping.enumerationMappings, em -> HelperMappingBuilder.processEnumMapping(em, pureMapping, context)); + if (!mapping.includedMappings.isEmpty()) + { + CompilerExtensions extensions = context.pureModel.extensions; + RichIterable mappingIncludes = + ListIterate.collect(mapping.includedMappings, i -> + { + IncludedMappingHandler handler = extensions.getExtraIncludedMappingHandlers(i.getClass().getName()); + return handler.processMappingInclude(i, context, pureMapping, + handler.resolveMapping(i, context)); + }); + pureMapping._includesAddAll(mappingIncludes); + // validate no duplicated included mappings + Set uniqueMappingIncludes = Sets.mutable.empty(); + mappingIncludes.forEach(includedMapping -> + { + String mappingName = IncludedMappingHandler.parseIncludedMappingNameRecursively(includedMapping); + if (!uniqueMappingIncludes.add(mappingName)) + { + throw new EngineException("Duplicated mapping include '" + mappingName + + "' in " + "mapping " + + "'" + context.pureModel.buildPackageString(mapping._package, mapping.name) + "'", mapping.sourceInformation, EngineErrorType.COMPILATION); + } + }); + } + if (!enumerationMappings.isEmpty()) + { + pureMapping._enumerationMappings(enumerationMappings); + } + } + + private void mappingThirdPass(Mapping mapping, CompileContext context) + { + final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); + if (mapping.classMappings != null && pureMapping._classMappings().isEmpty()) + { + RichIterable>> setImplementations = ListIterate.collect(mapping.classMappings, cm -> cm.accept(new ClassMappingFirstPassBuilder(context, pureMapping))); + pureMapping._classMappingsAddAll(setImplementations.flatCollect(p -> org.eclipse.collections.impl.factory.Lists.mutable.with(p.getOne()).withAll(p.getTwo()))); + } + if (!mapping.tests.isEmpty()) + { + mapping.tests.forEach(t -> HelperMappingBuilder.processMappingTest(t, context)); + } + if (mapping.testSuites != null) + { + TestBuilderHelper.validateTestSuiteIdsList(mapping.testSuites, mapping.sourceInformation); + pureMapping._tests(ListIterate.collect(mapping.testSuites, suite -> HelperMappingBuilder.processMappingTestAndTestSuite(suite, pureMapping, context))); + } + if (mapping.associationMappings != null) + { + RichIterable associationImplementations = ListIterate.collect(mapping.associationMappings, cm -> HelperMappingBuilder.processAssociationImplementation(cm, context, pureMapping)); + pureMapping._associationMappings(associationImplementations); + } + if (mapping.classMappings != null) + { + mapping.classMappings.forEach(cm -> cm.accept(new ClassMappingSecondPassBuilder(context, pureMapping))); + mapping.classMappings.forEach(cm -> cm.accept(new ClassMappingThirdPassBuilder(context, pureMapping))); + } + } + + private RichIterable mappingPrerequisiteElementsPass(Mapping mapping, CompileContext context) + { + final org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping pureMapping = context.pureModel.getMapping(context.pureModel.buildPackageString(mapping._package, mapping.name), mapping.sourceInformation); + return pureMapping._includes().collect(MappingIncludeAccessor::_included); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java index ae9466cee8a..d9db9a41a77 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/MeasureCompilerExtension.java @@ -21,6 +21,7 @@ import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.domain.Measure; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_type_Measure_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; import org.finos.legend.pure.m3.navigation.M3Paths; @@ -44,31 +45,35 @@ public Iterable> getExtraProcessors() return Lists.fixedSize.of( Processor.newProcessor( Measure.class, - (Measure measure, CompileContext context) -> - { - String fullPath = context.pureModel.buildPackageString(measure._package, measure.name); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Measure targetMeasure = new Root_meta_pure_metamodel_type_Measure_Impl(measure.name, SourceInformationHelper.toM3SourceInformation(measure.sourceInformation), null); - context.pureModel.typesIndex.put(fullPath, targetMeasure); - GenericType genericType = HelperCoreBuilder.newGenericType(targetMeasure, context); - context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); - targetMeasure._classifierGenericType(HelperCoreBuilder.newGenericType(context.pureModel.getType(M3Paths.Measure), context)); - if (measure.canonicalUnit != null) - { - HelperMeasureBuilder.processUnitPackageableElementFirstPass(measure.canonicalUnit, context); - } - measure.nonCanonicalUnits.forEach(ncu -> HelperMeasureBuilder.processUnitPackageableElementFirstPass(ncu, context)); - return targetMeasure; - }, - (Measure measure, CompileContext context) -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Measure targetMeasure = context.pureModel.getMeasure(context.pureModel.buildPackageString(measure._package, measure.name), measure.sourceInformation); - if (measure.canonicalUnit != null) - { - targetMeasure._canonicalUnit(HelperMeasureBuilder.processUnitPackageableElementSecondPass(measure.canonicalUnit, context)); - } - targetMeasure._nonCanonicalUnits(ListIterate.collect(measure.nonCanonicalUnits, ncu -> HelperMeasureBuilder.processUnitPackageableElementSecondPass(ncu, context))); - } + this::measureFirstPass, + this::measureSecondPass ) ); } + + private PackageableElement measureFirstPass(Measure measure, CompileContext context) + { + String fullPath = context.pureModel.buildPackageString(measure._package, measure.name); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Measure targetMeasure = new Root_meta_pure_metamodel_type_Measure_Impl(measure.name, SourceInformationHelper.toM3SourceInformation(measure.sourceInformation), null); + context.pureModel.typesIndex.put(fullPath, targetMeasure); + GenericType genericType = context.newGenericType(targetMeasure); + context.pureModel.typesGenericTypeIndex.put(fullPath, genericType); + targetMeasure._classifierGenericType(context.newGenericType(context.pureModel.getType(M3Paths.Measure))); + if (measure.canonicalUnit != null) + { + HelperMeasureBuilder.processUnitPackageableElementFirstPass(measure.canonicalUnit, context); + } + measure.nonCanonicalUnits.forEach(ncu -> HelperMeasureBuilder.processUnitPackageableElementFirstPass(ncu, context)); + return targetMeasure; + } + + private void measureSecondPass(Measure measure, CompileContext context) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.Measure targetMeasure = context.pureModel.getMeasure(context.pureModel.buildPackageString(measure._package, measure.name), measure.sourceInformation); + if (measure.canonicalUnit != null) + { + targetMeasure._canonicalUnit(HelperMeasureBuilder.processUnitPackageableElementSecondPass(measure.canonicalUnit, context)); + } + targetMeasure._nonCanonicalUnits(ListIterate.collect(measure.nonCanonicalUnits, ncu -> HelperMeasureBuilder.processUnitPackageableElementSecondPass(ncu, context))); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java index 7e883f531b9..67dd9366902 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableConnectionCompilerExtension.java @@ -23,6 +23,7 @@ import org.finos.legend.pure.generated.Root_meta_core_runtime_Connection; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableConnection; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableConnection_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; public class PackageableConnectionCompilerExtension implements CompilerExtension { @@ -45,18 +46,22 @@ public Iterable> getExtraProcessors() Processor.newProcessor( PackageableConnection.class, Lists.fixedSize.with(Mapping.class), - (PackageableConnection packageableConnection, CompileContext context) -> - { - Root_meta_pure_runtime_PackageableConnection metamodel = new Root_meta_pure_runtime_PackageableConnection_Impl(packageableConnection.name, SourceInformationHelper.toM3SourceInformation(packageableConnection.sourceInformation), context.pureModel.getClass("meta::pure::runtime::PackageableConnection")); - Root_meta_core_runtime_Connection connection = packageableConnection.connectionValue.accept(new ConnectionFirstPassBuilder(context)); - return metamodel._connectionValue(connection); - }, - (PackageableConnection packageableConnection, CompileContext context) -> - { - final Root_meta_core_runtime_Connection pureConnection = context.pureModel.getConnection(context.pureModel.buildPackageString(packageableConnection._package, packageableConnection.name), packageableConnection.sourceInformation); - packageableConnection.connectionValue.accept(new ConnectionSecondPassBuilder(context, pureConnection)); - } + this::packageableConnectionFirstPass, + this::packageableConnectionSecondPass ) ); } + + private PackageableElement packageableConnectionFirstPass(PackageableConnection packageableConnection, CompileContext context) + { + Root_meta_pure_runtime_PackageableConnection metamodel = new Root_meta_pure_runtime_PackageableConnection_Impl(packageableConnection.name, SourceInformationHelper.toM3SourceInformation(packageableConnection.sourceInformation), context.pureModel.getClass("meta::pure::runtime::PackageableConnection")); + Root_meta_core_runtime_Connection connection = packageableConnection.connectionValue.accept(new ConnectionFirstPassBuilder(context)); + return metamodel._connectionValue(connection); + } + + private void packageableConnectionSecondPass(PackageableConnection packageableConnection, CompileContext context) + { + final Root_meta_core_runtime_Connection pureConnection = context.pureModel.getConnection(context.pureModel.buildPackageString(packageableConnection._package, packageableConnection.name), packageableConnection.sourceInformation); + packageableConnection.connectionValue.accept(new ConnectionSecondPassBuilder(context, pureConnection)); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java index d7f358e4e0a..5192b294631 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PackageableRuntimeCompilerExtension.java @@ -25,6 +25,7 @@ import org.finos.legend.pure.generated.Root_meta_core_runtime_EngineRuntime_Impl; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime; import org.finos.legend.pure.generated.Root_meta_pure_runtime_PackageableRuntime_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.type.generics.GenericType; public class PackageableRuntimeCompilerExtension implements CompilerExtension @@ -48,24 +49,28 @@ public Iterable> getExtraProcessors() Processor.newProcessor( PackageableRuntime.class, Lists.fixedSize.with(Mapping.class, PackageableConnection.class), + this::packageableRuntimeFirstPass, (PackageableRuntime packageableRuntime, CompileContext context) -> { - Root_meta_pure_runtime_PackageableRuntime metamodel = new Root_meta_pure_runtime_PackageableRuntime_Impl(packageableRuntime.name, SourceInformationHelper.toM3SourceInformation(packageableRuntime.sourceInformation), context.pureModel.getClass("meta::pure::runtime::PackageableRuntime")); - GenericType packageableRuntimeGenericType = HelperCoreBuilder.newGenericType(context.pureModel.getType("meta::pure::runtime::PackageableRuntime"), context); - metamodel._classifierGenericType(packageableRuntimeGenericType); - Root_meta_core_runtime_EngineRuntime pureRuntime = new Root_meta_core_runtime_EngineRuntime_Impl("Root::meta::core::runtime::Runtime", SourceInformationHelper.toM3SourceInformation(packageableRuntime.sourceInformation), context.pureModel.getClass("meta::core::runtime::Runtime")); - return metamodel._runtimeValue(pureRuntime); }, - (PackageableRuntime packageableRuntime, CompileContext context) -> - { - }, - (PackageableRuntime packageableRuntime, CompileContext context) -> - { - String fullPath = context.pureModel.buildPackageString(packageableRuntime._package, packageableRuntime.name); - Root_meta_pure_runtime_PackageableRuntime metamodel = context.pureModel.getPackageableRuntime(fullPath, packageableRuntime.sourceInformation); - HelperRuntimeBuilder.buildEngineRuntime(packageableRuntime.runtimeValue, metamodel._runtimeValue(), context); - } + this::packageableRuntimeThirdPass ) ); } + + private PackageableElement packageableRuntimeFirstPass(PackageableRuntime packageableRuntime, CompileContext context) + { + Root_meta_pure_runtime_PackageableRuntime metamodel = new Root_meta_pure_runtime_PackageableRuntime_Impl(packageableRuntime.name, SourceInformationHelper.toM3SourceInformation(packageableRuntime.sourceInformation), context.pureModel.getClass("meta::pure::runtime::PackageableRuntime")); + GenericType packageableRuntimeGenericType = context.newGenericType(context.pureModel.getType("meta::pure::runtime::PackageableRuntime")); + metamodel._classifierGenericType(packageableRuntimeGenericType); + Root_meta_core_runtime_EngineRuntime pureRuntime = new Root_meta_core_runtime_EngineRuntime_Impl("Root::meta::core::runtime::Runtime", SourceInformationHelper.toM3SourceInformation(packageableRuntime.sourceInformation), context.pureModel.getClass("meta::core::runtime::Runtime")); + return metamodel._runtimeValue(pureRuntime); + } + + private void packageableRuntimeThirdPass(PackageableRuntime packageableRuntime, CompileContext context) + { + String fullPath = context.pureModel.buildPackageString(packageableRuntime._package, packageableRuntime.name); + Root_meta_pure_runtime_PackageableRuntime metamodel = context.pureModel.getPackageableRuntime(fullPath, packageableRuntime.sourceInformation); + HelperRuntimeBuilder.buildEngineRuntime(packageableRuntime.runtimeValue, metamodel._runtimeValue(), context); + } } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java index 4e2978ebdac..1479fe0cf82 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/ProfileCompilerExtension.java @@ -24,6 +24,7 @@ import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_Profile_Impl; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_Stereotype_Impl; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_extension_Tag_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Stereotype; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Tag; @@ -47,16 +48,18 @@ public Iterable> getExtraProcessors() return Lists.fixedSize.of( Processor.newProcessor( Profile.class, - (Profile profile, CompileContext context) -> - { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile targetProfile = new Root_meta_pure_metamodel_extension_Profile_Impl(profile.name, SourceInformationHelper.toM3SourceInformation(profile.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::extension::Profile")); - return targetProfile._p_stereotypes(ListIterate.collect(profile.stereotypes, st -> newStereotype(targetProfile, st.value, st.sourceInformation, context))) - ._p_tags(ListIterate.collect(profile.tags, t -> newTag(targetProfile, t.value, t.sourceInformation, context))); - } + this::profileFirstPass ) ); } + private PackageableElement profileFirstPass(Profile profile, CompileContext context) + { + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile targetProfile = new Root_meta_pure_metamodel_extension_Profile_Impl(profile.name, SourceInformationHelper.toM3SourceInformation(profile.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::extension::Profile")); + return targetProfile._p_stereotypes(ListIterate.collect(profile.stereotypes, st -> newStereotype(targetProfile, st.value, st.sourceInformation, context))) + ._p_tags(ListIterate.collect(profile.tags, t -> newTag(targetProfile, t.value, t.sourceInformation, context))); + } + private Stereotype newStereotype(org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.Profile profile, String name, SourceInformation sourceInformation, CompileContext context) { return new Root_meta_pure_metamodel_extension_Stereotype_Impl(name, SourceInformationHelper.toM3SourceInformation(sourceInformation), context.pureModel.getClass("meta::pure::metamodel::extension::Stereotype")) diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java index d505bbd15dc..c3640da85e4 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java @@ -606,12 +606,11 @@ else if (cause instanceof RuntimeException) } } - public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + private org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { return visitWithErrorHandling(element, () -> { - CompileContext context = getContext(element); - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement pureElement = context.getExtraProcessorOrThrow(element).processFirstPass(element, context); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement pureElement = getContext(element).processFirstPass(element); if (pureElement instanceof ConcreteFunctionDefinition) { return pureElement; @@ -620,12 +619,11 @@ public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElem }); } - public void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + private void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { visitWithErrorHandling(element, () -> { - CompileContext context = getContext(element); - context.getExtraProcessorOrThrow(element).processSecondPass(element, context); + getContext(element).processSecondPass(element); return null; }); } @@ -644,12 +642,11 @@ private void processMilestoningPass(org.finos.legend.engine.protocol.pure.v1.mod visitWithErrorHandling(element, () -> element.accept(new PackageableElementMilestoningPassBuilder(getContext(element)))); } - public void processThirdPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + private void processThirdPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { visitWithErrorHandling(element, () -> { - CompileContext context = getContext(element); - context.getExtraProcessorOrThrow(element).processThirdPass(element, context); + getContext(element).processThirdPass(element); return null; }); } diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java index 03aacb9eb1e..f00c53999c8 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/SectionIndexCompilerExtension.java @@ -20,6 +20,7 @@ import org.finos.legend.engine.language.pure.compiler.toPureGraph.extension.Processor; import org.finos.legend.engine.protocol.pure.v1.model.packageableElement.section.SectionIndex; import org.finos.legend.pure.generated.Root_meta_pure_metamodel_section_SectionIndex_Impl; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement; public class SectionIndexCompilerExtension implements CompilerExtension { @@ -41,9 +42,13 @@ public Iterable> getExtraProcessors() return Lists.fixedSize.of( Processor.newProcessor( SectionIndex.class, - (SectionIndex sectionIndex, CompileContext context) -> - new Root_meta_pure_metamodel_section_SectionIndex_Impl(sectionIndex.name, SourceInformationHelper.toM3SourceInformation(sectionIndex.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::section::SectionIndex")) + this::sectionIndexFirstPass ) ); } + + private PackageableElement sectionIndexFirstPass(SectionIndex sectionIndex, CompileContext context) + { + return new Root_meta_pure_metamodel_section_SectionIndex_Impl(sectionIndex.name, SourceInformationHelper.toM3SourceInformation(sectionIndex.sourceInformation), context.pureModel.getClass("meta::pure::metamodel::section::SectionIndex")); + } } diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java index 1ca53a2d58e..4b06754cf94 100644 --- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java +++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-generation/legend-engine-xt-relationalStore-grammar/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/HelperRelationalDatabaseConnectionBuilder.java @@ -58,7 +58,7 @@ public static void addDatabaseConnectionProperties(Root_meta_external_store_rela Database db = new Database(); db.name = element; db._package = ""; - context.pureModel.processFirstPass(db); + context.processFirstPass(db); } } } diff --git a/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java b/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java index b9aa9aba6e8..2a10d6596b2 100644 --- a/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java +++ b/legend-engine-xts-service/legend-engine-service-post-validation-runner/src/test/java/org/finos/legend/engine/service/post/validation/runner/TestLegendServicePostValidationRunner.java @@ -102,9 +102,9 @@ public Root_meta_legend_service_metamodel_Service compileService(Service service pkg._childrenRemove(existing); } - Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) compileContext.pureModel.processFirstPass(service); - compileContext.pureModel.processSecondPass(service); - compileContext.pureModel.processThirdPass(service); + Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) compileContext.processFirstPass(service); + compileContext.processSecondPass(service); + compileContext.processThirdPass(service); return compiledService; } diff --git a/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java b/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java index a9bba6aace9..9637d39c995 100644 --- a/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java +++ b/legend-engine-xts-service/legend-engine-services-model/src/main/java/org/finos/legend/engine/plan/execution/service/ServiceModeling.java @@ -91,8 +91,8 @@ public Root_meta_legend_service_metamodel_Service compileService(Service service pkg._childrenRemove(existing); } - Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) compileContext.pureModel.processFirstPass(service); - compileContext.pureModel.processSecondPass(service); + Root_meta_legend_service_metamodel_Service compiledService = (Root_meta_legend_service_metamodel_Service) compileContext.processFirstPass(service); + compileContext.processSecondPass(service); return compiledService; } From de7ee7af06831581e40eebd8678ba0d5ded82f46 Mon Sep 17 00:00:00 2001 From: "Kim, Jake" Date: Tue, 29 Oct 2024 14:03:03 -0400 Subject: [PATCH 3/3] Ensure first pass calls always store element package --- .../compiler/toPureGraph/CompileContext.java | 15 +++++++++++++-- .../pure/compiler/toPureGraph/PureModel.java | 18 +++++------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java index eefe4c39f5e..b42e890b265 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/CompileContext.java @@ -46,6 +46,7 @@ import org.finos.legend.pure.generated.Root_meta_core_runtime_Runtime; import org.finos.legend.pure.m3.coreinstance.meta.pure.mapping.Mapping; import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.extension.TaggedValue; +import org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.function.ConcreteFunctionDefinition; 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.m3.coreinstance.meta.pure.metamodel.type.Measure; @@ -175,7 +176,12 @@ public Processor getExtraProcessorOrThrow(PackageableElement element) public org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - return getExtraProcessorOrThrow(element).processFirstPass(element, this); + org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement pureElement = getExtraProcessorOrThrow(element).processFirstPass(element, this); + if (pureElement instanceof ConcreteFunctionDefinition) + { + return pureElement; + } + return this.pureModel.setNameAndPackage(pureElement, element.name, element._package, element.sourceInformation); } public void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) @@ -183,9 +189,14 @@ public void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.pac getExtraProcessorOrThrow(element).processSecondPass(element, this); } + protected RichIterable processPrerequisiteElementsPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + { + return getExtraProcessorOrThrow(element).getPrerequisiteElements(element, this); + } + public void processThirdPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - getExtraProcessorOrThrow(element).processSecondPass(element, this); + getExtraProcessorOrThrow(element).processThirdPass(element, this); } public T resolve(String path, SourceInformation sourceInformation, Function resolver) diff --git a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java index c3640da85e4..ca0bc746e7f 100644 --- a/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java +++ b/legend-engine-core/legend-engine-core-base/legend-engine-core-language-pure/legend-engine-language-pure-compiler/src/main/java/org/finos/legend/engine/language/pure/compiler/toPureGraph/PureModel.java @@ -606,16 +606,12 @@ else if (cause instanceof RuntimeException) } } - private org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) + private void processFirstPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - return visitWithErrorHandling(element, () -> + visitWithErrorHandling(element, () -> { - org.finos.legend.pure.m3.coreinstance.meta.pure.metamodel.PackageableElement pureElement = getContext(element).processFirstPass(element); - if (pureElement instanceof ConcreteFunctionDefinition) - { - return pureElement; - } - return setNameAndPackage(pureElement, element.name, element._package, element.sourceInformation); + getContext(element).processFirstPass(element); + return null; }); } @@ -630,11 +626,7 @@ private void processSecondPass(org.finos.legend.engine.protocol.pure.v1.model.pa private RichIterable processPrerequisiteElementsPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element) { - return visitWithErrorHandling(element, () -> - { - CompileContext context = getContext(element); - return context.getExtraProcessorOrThrow(element).getPrerequisiteElements(element, context); - }); + return visitWithErrorHandling(element, () -> getContext(element).processPrerequisiteElementsPass(element)); } private void processMilestoningPass(org.finos.legend.engine.protocol.pure.v1.model.packageableElement.PackageableElement element)