@finos/legend-graph
Version:
Legend graph and graph manager
549 lines • 43 kB
JavaScript
/**
* Copyright (c) 2020-present, 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.
*/
import { LogEvent, assertNonNullable, assertNonEmptyString, guaranteeType, guaranteeNonNullable, returnUndefOnError, UnsupportedOperationError, } from '@finos/legend-shared';
import { GRAPH_MANAGER_EVENT } from '../../../../../../../__lib__/GraphManagerEvent.js';
import { PurePropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/store/modelToModel/mapping/PurePropertyMapping.js';
import { RelationalPropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/store/relational/mapping/RelationalPropertyMapping.js';
import { EmbeddedFlatDataPropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/store/flatData/mapping/EmbeddedFlatDataPropertyMapping.js';
import { FlatDataPropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/store/flatData/mapping/FlatDataPropertyMapping.js';
import { Class } from '../../../../../../../graph/metamodel/pure/packageableElements/domain/Class.js';
import { InferableMappingElementIdExplicitValue } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/InferableMappingElementId.js';
import { PackageableElementImplicitReference, } from '../../../../../../../graph/metamodel/pure/packageableElements/PackageableElementReference.js';
import { PropertyImplicitReference, } from '../../../../../../../graph/metamodel/pure/packageableElements/domain/PropertyReference.js';
import { RootRelationalInstanceSetImplementation } from '../../../../../../../graph/metamodel/pure/packageableElements/store/relational/mapping/RootRelationalInstanceSetImplementation.js';
import { OtherwiseEmbeddedRelationalInstanceSetImplementation } from '../../../../../../../graph/metamodel/pure/packageableElements/store/relational/mapping/OtherwiseEmbeddedRelationalInstanceSetImplementation.js';
import { EmbeddedRelationalInstanceSetImplementation } from '../../../../../../../graph/metamodel/pure/packageableElements/store/relational/mapping/EmbeddedRelationalInstanceSetImplementation.js';
import { InlineEmbeddedRelationalInstanceSetImplementation } from '../../../../../../../graph/metamodel/pure/packageableElements/store/relational/mapping/InlineEmbeddedRelationalInstanceSetImplementation.js';
import { AssociationImplementation } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/AssociationImplementation.js';
import { V1_buildRelationalOperationElement } from './helpers/V1_DatabaseBuilderHelper.js';
import { V1_buildEmbeddedRelationalMappingProperty } from './helpers/V1_RelationalPropertyMappingBuilder.js';
import { XStorePropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/xStore/XStorePropertyMapping.js';
import { Property } from '../../../../../../../graph/metamodel/pure/packageableElements/domain/Property.js';
import { MappingClass } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/MappingClass.js';
import { LocalMappingPropertyInfo } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/LocalMappingPropertyInfo.js';
import { AggregationAwarePropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/aggregationAware/AggregationAwarePropertyMapping.js';
import { V1_buildRawLambdaWithResolvedPaths } from './helpers/V1_ValueSpecificationPathResolver.js';
import { V1_deserializeRelationalOperationElement, V1_serializeRelationalOperationElement, } from '../../pureProtocol/serializationHelpers/V1_DatabaseSerializationHelper.js';
import { V1_transformRelationalOperationElement } from '../from/V1_DatabaseTransformer.js';
import { V1_GraphTransformerContextBuilder } from '../from/V1_GraphTransformerContext.js';
import { getAllEnumerationMappings, getAllIncludedMappings, getClassMappingById, getClassMappingsByClass, } from '../../../../../../../graph/helpers/DSL_Mapping_Helper.js';
import { GraphBuilderError } from '../../../../../../../graph-manager/GraphManagerUtils.js';
import { BindingTransformer } from '../../../../../../../graph/metamodel/pure/packageableElements/externalFormat/store/DSL_ExternalFormat_BindingTransformer.js';
import { V1_resolveBinding } from './V1_DSL_ExternalFormat_GraphBuilderHelper.js';
import { INTERNAL__UnresolvedSetImplementation } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/INTERNAL__UnresolvedSetImplementation.js';
import { getAssociatedPropertyClass, getOwnProperty, getClassProperty, } from '../../../../../../../graph/helpers/DomainHelper.js';
import { SetImplementationImplicitReference } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/SetImplementationReference.js';
import { EnumerationMappingExplicitReference } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/EnumerationMappingReference.js';
import { FlatDataAssociationPropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/store/flatData/mapping/FlatDataAssociationPropertyMapping.js';
import { INTERNAL__UnknownPropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/INTERNAL__UnknownPropertyMapping.js';
import { INTERNAL__PseudoMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/INTERNAL__PseudoMapping.js';
import { RelationFunctionPropertyMapping } from '../../../../../../../graph/metamodel/pure/packageableElements/mapping/relationFunction/RelationFunctionPropertyMapping.js';
import { RelationColumn } from '../../../../../../../graph/metamodel/pure/packageableElements/relation/RelationType.js';
const TEMPORARY__resolveSetImplementationByID = (mapping, id, context) => {
const classMapping = returnUndefOnError(() => getClassMappingById(mapping, id));
const isMappingWithUnknownMappingIncludes = getAllIncludedMappings(mapping).includes(INTERNAL__PseudoMapping.INSTANCE);
if (!classMapping) {
const message = `Can't find class mapping with ID '${id}' in mapping '${mapping.path}'`;
/**
* If the mapping has unknown mapping includes, this kind of problems
* might be due to the fact that the class mapping is not reachable due to the system
* not knowing how to analyze the unknown mapping include, as such, we will not throw
* errors, otherwise, we should in strict-mode
*
* See https://github.com/finos/legend-studio/issues/880
* See https://github.com/finos/legend-studio/issues/941
*
* @discrepancy graph-building
*/
if (context.options?.strict && !isMappingWithUnknownMappingIncludes) {
throw new GraphBuilderError(message);
}
context.logService.warn(LogEvent.create(message));
return new INTERNAL__UnresolvedSetImplementation(id, mapping);
}
return classMapping;
};
const resolvePropertyMappingSourceImplementation = (immediateParent, value, topParent, context) => {
if (immediateParent instanceof AssociationImplementation) {
if (value.source) {
return TEMPORARY__resolveSetImplementationByID(immediateParent._PARENT, value.source, context);
}
const property = getOwnProperty(immediateParent.association.value, value.property.property);
const _class = getAssociatedPropertyClass(immediateParent.association.value, property);
const setImpls = getClassMappingsByClass(immediateParent._PARENT, _class);
return setImpls.find((r) => r.root.value) ?? setImpls[0];
}
return topParent;
};
export class V1_PropertyMappingBuilder {
context;
immediateParent; // either root instance set implementation or the immediate embedded parent property mapping (needed for processing embedded property mapping)
topParent;
allEnumerationMappings = [];
tableAliasIndex;
allClassMappings;
xStoreParent;
aggregationAwareParent;
constructor(context, immediateParent, topParent, allEnumerationMappings, tableAliasMap, allClassMappings, xStoreParent, aggregationAwareParent) {
this.context = context;
this.immediateParent = immediateParent;
this.topParent = topParent;
this.allEnumerationMappings = allEnumerationMappings;
this.tableAliasIndex = tableAliasMap ?? new Map();
this.allClassMappings = allClassMappings ?? [];
this.xStoreParent = xStoreParent;
this.aggregationAwareParent = aggregationAwareParent;
}
visit_PropertyMapping(propertyMapping) {
const extraPropertyMappingBuilders = this.context.extensions.plugins.flatMap((plugin) => plugin.V1_getExtraPropertyMappingBuilders?.() ?? []);
for (const builder of extraPropertyMappingBuilders) {
const extraPropertyMapping = builder(propertyMapping, this.context);
if (extraPropertyMapping) {
return extraPropertyMapping;
}
}
throw new UnsupportedOperationError(`Can't build property mapping: no compatible builder available from plugins`, propertyMapping);
}
visit_INTERNAL__UnknownPropertyMapping(propertyMapping) {
const metamodel = new INTERNAL__UnknownPropertyMapping();
metamodel.content = propertyMapping.content;
return metamodel;
}
visit_PurePropertyMapping(protocol) {
assertNonNullable(protocol.property, `Pure instance property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Pure instance property mapping 'property.property' field is missing or empty`);
assertNonNullable(protocol.transform, `Pure instance property mapping 'transform' field is missing`);
// NOTE: mapping for derived property is not supported
let property;
let localMapping;
if (protocol.localMappingProperty) {
const localMappingProperty = protocol.localMappingProperty;
const mappingClass = new MappingClass(`${this.topParent?._PARENT.path}_${this.topParent?.id}${protocol.property.property}`);
const _multiplicity = this.context.graph.getMultiplicity(localMappingProperty.multiplicity.lowerBound, localMappingProperty.multiplicity.upperBound);
const _property = new Property(protocol.property.property, _multiplicity, this.context.resolveGenericType(localMappingProperty.type), mappingClass);
property = PropertyImplicitReference.create(PackageableElementImplicitReference.create(mappingClass, protocol.property.class), _property);
localMapping = new LocalMappingPropertyInfo();
localMapping.localMappingProperty = true;
localMapping.localMappingPropertyMultiplicity = _multiplicity;
localMapping.localMappingPropertyType = this.context.resolveType(localMappingProperty.type);
}
else {
assertNonEmptyString(protocol.property.class, `Pure instance property mapping 'property.class' field is missing or empty`);
property = this.context.resolveProperty(protocol.property);
}
const propertyType = property.value.genericType.value.rawType;
let targetSetImplementation;
const topParent = guaranteeNonNullable(this.topParent);
if (propertyType instanceof Class) {
if (protocol.target) {
targetSetImplementation = TEMPORARY__resolveSetImplementationByID(topParent._PARENT, protocol.target, this.context);
}
else {
// NOTE: if no there is one non-root class mapping, auto-nominate that as the target set implementation
targetSetImplementation = getClassMappingsByClass(topParent._PARENT, guaranteeType(propertyType, Class))[0];
}
}
const sourceSetImplementation = protocol.source
? TEMPORARY__resolveSetImplementationByID(topParent._PARENT, protocol.source, this.context)
: undefined;
const purePropertyMapping = new PurePropertyMapping(topParent, property, V1_buildRawLambdaWithResolvedPaths([], protocol.transform.body, this.context), SetImplementationImplicitReference.create(sourceSetImplementation ?? topParent, protocol.source), targetSetImplementation
? SetImplementationImplicitReference.create(targetSetImplementation, protocol.target)
: undefined, protocol.explodeProperty);
if (protocol.enumMappingId) {
const enumerationMapping = this.allEnumerationMappings.find((em) => em.id.value === protocol.enumMappingId);
if (!enumerationMapping) {
// TODO: Since we don't support includedMappings, this will throw errors, but right now we can just make it undefined.
this.context.logService.debug(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), `Can't find enumeration mapping with ID '${protocol.enumMappingId}' in mapping '${topParent._PARENT.path}' (perhaps because we haven't supported included mappings)`);
}
purePropertyMapping.transformer = enumerationMapping
? EnumerationMappingExplicitReference.create(enumerationMapping)
: undefined;
}
purePropertyMapping.localMappingProperty = localMapping;
return purePropertyMapping;
}
visit_FlatDataPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Flat-data property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Flat-data property mapping 'property.property' field is missing or empty`);
assertNonNullable(protocol.transform, `Flat-data property mapping 'transform' field is missing`);
// NOTE: there are cases that property pointer class might be missing, such as when we transform grammar to JSON
// since we do not do look up, due to nesting structure introudced by embedded mappings, we might not have the class information
// as such, here we have to resolve the class being mapped depending on where the property mapping is in the class mapping
let propertyOwnerClass;
if (protocol.property.class) {
propertyOwnerClass = this.context.resolveClass(protocol.property.class).value;
}
else if (this.immediateParent instanceof EmbeddedFlatDataPropertyMapping) {
propertyOwnerClass = this.immediateParent.class.value;
}
else {
throw new GraphBuilderError(`Can't find property owner class for property '${protocol.property.property}'`);
}
// NOTE: mapping for derived property is not supported
const property = getClassProperty(propertyOwnerClass, protocol.property.property);
const sourceSetImplementation = guaranteeNonNullable(this.immediateParent instanceof EmbeddedFlatDataPropertyMapping
? this.immediateParent
: this.topParent);
// target
let targetSetImplementation;
const propertyType = property.genericType.value.rawType;
if (propertyType instanceof Class && protocol.target) {
targetSetImplementation = this.topParent
? TEMPORARY__resolveSetImplementationByID(this.topParent._PARENT, protocol.target, this.context)
: undefined;
}
const flatDataPropertyMapping = new FlatDataPropertyMapping(this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(propertyOwnerClass, protocol.property.class ?? ''), property), V1_buildRawLambdaWithResolvedPaths([], protocol.transform.body, this.context), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), targetSetImplementation
? SetImplementationImplicitReference.create(targetSetImplementation, protocol.target)
: undefined);
if (protocol.enumMappingId) {
const enumerationMapping = this.allEnumerationMappings.find((em) => em.id.value === protocol.enumMappingId);
if (!enumerationMapping) {
// TODO: Since we don't support includedMappings, this will throw errors, but right now we can just make it undefined.
this.context.logService.debug(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), `Can't find enumeration mapping with ID '${protocol.enumMappingId}' in mapping '${this.topParent?._PARENT.path} (perhaps because we haven't supported included mappings)`);
}
flatDataPropertyMapping.transformer = enumerationMapping
? EnumerationMappingExplicitReference.create(enumerationMapping)
: undefined;
}
return flatDataPropertyMapping;
}
visit_EmbeddedFlatDataPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Embedded flat-data property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Embedded flat-data property mapping property 'property.property' field is missing or empty`);
// NOTE: there are cases that property pointer class might be missing, such as when we transform grammar to JSON
// since we do not do look up, due to nesting structure introudced by embedded mappings, we might not have the class information
// as such, here we have to resolve the class being mapped depending on where the property mapping is in the class mapping
let propertyOwnerClass;
if (protocol.property.class) {
propertyOwnerClass = this.context.resolveClass(protocol.property.class).value;
}
else if (this.immediateParent instanceof EmbeddedFlatDataPropertyMapping) {
propertyOwnerClass = this.immediateParent.class.value;
}
else {
throw new GraphBuilderError(`Can't find property owner class for property '${protocol.property.property}'`);
}
const property = getClassProperty(propertyOwnerClass, protocol.property.property);
let _class;
if (protocol.class) {
_class = this.context.resolveClass(protocol.class);
}
else {
const propertyType = property.genericType.value.rawType;
const complexClass = guaranteeType(propertyType, Class, 'Only complex classes can be the target of an embedded property mapping');
_class = PackageableElementImplicitReference.create(complexClass, '');
}
const sourceSetImplementation = guaranteeNonNullable(this.immediateParent instanceof EmbeddedFlatDataPropertyMapping
? this.immediateParent
: this.topParent);
const embeddedPropertyMapping = new EmbeddedFlatDataPropertyMapping(this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(propertyOwnerClass, protocol.property.class ?? ''), property), guaranteeNonNullable(this.topParent), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), _class, InferableMappingElementIdExplicitValue.create(`${sourceSetImplementation.id.value}.${property.name}`, ''), undefined);
embeddedPropertyMapping.targetSetImplementation = protocol.target
? SetImplementationImplicitReference.create(embeddedPropertyMapping, protocol.target)
: undefined;
embeddedPropertyMapping.propertyMappings = protocol.propertyMappings.map((propertyMapping) => propertyMapping.accept_PropertyMappingVisitor(new V1_PropertyMappingBuilder(this.context, embeddedPropertyMapping, this.topParent, this.allEnumerationMappings)));
return embeddedPropertyMapping;
}
visit_RelationalPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Relational property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Relational property mapping 'property.property' field is missing or empty`);
assertNonNullable(protocol.relationalOperation, `Relational property mapping 'relationalOperation' field is missing`);
// NOTE: mapping for derived property is not supported
let propertyOwner;
let property;
let localMapping;
if (protocol.localMappingProperty) {
const localMappingProperty = protocol.localMappingProperty;
const mappingClass = new MappingClass(`${this.topParent?._PARENT.path}_${this.topParent?.id}${protocol.property.property}`);
const _multiplicity = this.context.graph.getMultiplicity(localMappingProperty.multiplicity.lowerBound, localMappingProperty.multiplicity.upperBound);
const _property = new Property(protocol.property.property, _multiplicity, this.context.resolveGenericType(localMappingProperty.type), mappingClass);
property = PropertyImplicitReference.create(PackageableElementImplicitReference.create(mappingClass, protocol.property.class), _property).value;
localMapping = new LocalMappingPropertyInfo();
localMapping.localMappingProperty = true;
localMapping.localMappingPropertyMultiplicity = _multiplicity;
localMapping.localMappingPropertyType = this.context.resolveType(localMappingProperty.type);
propertyOwner = property._OWNER;
}
else {
if (this.immediateParent instanceof AssociationImplementation) {
propertyOwner = this.immediateParent.association.value;
}
else if (protocol.property.class) {
propertyOwner = this.context.resolveClass(protocol.property.class).value;
}
else if (this.immediateParent instanceof
EmbeddedRelationalInstanceSetImplementation) {
propertyOwner =
this.immediateParent._OWNER instanceof
EmbeddedRelationalInstanceSetImplementation &&
this.immediateParent.property.value.name ===
protocol.property.property
? this.immediateParent.property.ownerReference.value
: this.immediateParent.class.value;
}
else {
throw new GraphBuilderError(`Can't find property owner class for property '${protocol.property.property}'`);
}
property =
propertyOwner instanceof Class
? getClassProperty(propertyOwner, protocol.property.property)
: getOwnProperty(propertyOwner, protocol.property.property);
}
// NOTE: mapping for derived property is not supported
// since we are not doing embedded property mappings yet, the target must have already been added to the mapping
const propertyType = property.genericType.value.rawType;
let targetSetImplementation;
if (propertyType instanceof Class) {
let parentMapping = this.topParent?._PARENT;
if (!parentMapping &&
this.immediateParent instanceof AssociationImplementation) {
parentMapping = this.immediateParent._PARENT;
}
if (protocol.target) {
targetSetImplementation = parentMapping
? TEMPORARY__resolveSetImplementationByID(parentMapping, protocol.target, this.context)
: undefined;
}
else {
targetSetImplementation = parentMapping
? getClassMappingsByClass(parentMapping, guaranteeType(propertyType, Class))[0]
: undefined;
}
}
const sourceSetImplementation = guaranteeNonNullable(resolvePropertyMappingSourceImplementation(this.immediateParent, protocol, this.topParent, this.context));
const relationalPropertyMapping = new RelationalPropertyMapping(this.topParent ?? this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(propertyOwner, protocol.property.class ?? ''), property), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), targetSetImplementation
? SetImplementationImplicitReference.create(targetSetImplementation, protocol.target)
: undefined);
if (protocol.bindingTransformer?.binding) {
const bindingTransformer = new BindingTransformer();
const binding = V1_resolveBinding(protocol.bindingTransformer.binding, this.context);
bindingTransformer.binding = binding;
relationalPropertyMapping.bindingTransformer = bindingTransformer;
}
// NOTE: we only need to use the raw form of the operation for the editor
// but we need to process it anyway so we can:
// 1. do analytics on table alias map
// 2. and to resolve paths (similar to lambda).
// As such, we will need to do a full round-trip processing for the operation
// See https://github.com/finos/legend-studio/pull/173
try {
relationalPropertyMapping.relationalOperation =
V1_serializeRelationalOperationElement(V1_transformRelationalOperationElement(V1_buildRelationalOperationElement(V1_deserializeRelationalOperationElement(protocol.relationalOperation), this.context, this.tableAliasIndex, []), new V1_GraphTransformerContextBuilder(this.context.extensions.plugins).build(), {
// NOTE: here we will always resolve paths found in the operation to full
// since right now we still delete the section index, which will cause
// these paths to be potentially become corrupted.
TEMPORARY__resolveToFullPath: true,
}));
}
catch {
relationalPropertyMapping.relationalOperation =
protocol.relationalOperation;
}
if (protocol.enumMappingId) {
const enumerationMapping = this.allEnumerationMappings.find((em) => em.id.value === protocol.enumMappingId);
if (!enumerationMapping) {
// TODO: Since we don't support includedMappings, this will throw errors, but right now we can just make it undefined.
this.context.logService.debug(LogEvent.create(GRAPH_MANAGER_EVENT.GRAPH_BUILDER_FAILURE), `Can't find enumeration mapping with ID '${protocol.enumMappingId}' in mapping '${this.topParent?._PARENT.path}' (perhaps because we haven't supported included mappings)`);
}
relationalPropertyMapping.transformer = enumerationMapping
? EnumerationMappingExplicitReference.create(enumerationMapping)
: undefined;
}
relationalPropertyMapping.localMappingProperty = localMapping;
return relationalPropertyMapping;
}
visit_FlatDataAssociationPropertyMapping(protocol) {
assertNonNullable(protocol.property, `FlatData property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `FlatData property mapping 'property.property' field is missing or empty`);
assertNonNullable(protocol.flatData, `FlatData property mapping 'flatdata' field is missing`);
assertNonNullable(protocol.sectionName, `FlatData property mapping 'sectionName' field is missing`);
// NOTE: mapping for derived property is not supported
let propertyOwner;
if (this.immediateParent instanceof AssociationImplementation) {
propertyOwner = this.immediateParent.association.value;
}
else {
throw new GraphBuilderError(`Can't find property owner class for property '${protocol.property.property}'`);
}
const property = getOwnProperty(propertyOwner, protocol.property.property);
// NOTE: mapping for derived property is not supported
// since we are not doing embedded property mappings yet, the target must have already been added to the mapping
const propertyType = property.genericType.value.rawType;
let targetSetImplementation;
if (propertyType instanceof Class) {
const parentMapping = this.immediateParent._PARENT;
if (protocol.target) {
targetSetImplementation = TEMPORARY__resolveSetImplementationByID(parentMapping, protocol.target, this.context);
}
else {
targetSetImplementation = getClassMappingsByClass(parentMapping, guaranteeType(propertyType, Class))[0];
}
}
const sourceSetImplementation = guaranteeNonNullable(resolvePropertyMappingSourceImplementation(this.immediateParent, protocol, this.topParent, this.context));
const flatDataAssociationPropertyMapping = new FlatDataAssociationPropertyMapping(this.topParent ?? this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(propertyOwner, protocol.property.class ?? ''), property), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), targetSetImplementation
? SetImplementationImplicitReference.create(targetSetImplementation, protocol.target)
: undefined);
flatDataAssociationPropertyMapping.flatData = protocol.flatData;
flatDataAssociationPropertyMapping.sectionName = protocol.sectionName;
return flatDataAssociationPropertyMapping;
}
visit_InlineEmbeddedPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Inline embedded property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Inline embedded property mapping 'property.property' field is missing or empty`);
let propertyOwnerClass;
if (protocol.property.class) {
propertyOwnerClass = this.context.resolveClass(protocol.property.class).value;
}
else if (this.immediateParent instanceof RootRelationalInstanceSetImplementation ||
this.immediateParent instanceof
EmbeddedRelationalInstanceSetImplementation) {
propertyOwnerClass = this.immediateParent.class.value;
}
else {
throw new GraphBuilderError(`Can't find property owner class for property '${protocol.property.property}'`);
}
const property = getClassProperty(propertyOwnerClass, protocol.property.property);
const propertyType = property.genericType.value.rawType;
const complexClass = guaranteeType(propertyType, Class, 'Only complex classes can be the target of an embedded property mapping');
const _class = PackageableElementImplicitReference.create(complexClass, protocol.property.class ?? '');
const id = `${this.immediateParent.id.value}_${property.name}`;
const topParent = guaranteeNonNullable(this.topParent);
const sourceSetImplementation = this.immediateParent instanceof RootRelationalInstanceSetImplementation
? this.immediateParent
: topParent;
const inline = new InlineEmbeddedRelationalInstanceSetImplementation(this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(propertyOwnerClass, protocol.property.class ?? ''), property), guaranteeType(this.topParent, RootRelationalInstanceSetImplementation), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), _class, InferableMappingElementIdExplicitValue.create(id, ''), undefined);
inline.inlineSetImplementation = TEMPORARY__resolveSetImplementationByID(topParent._PARENT, protocol.setImplementationId, this.context);
return inline;
}
visit_EmbeddedRelationalPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Embedded relational property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Embedded relational property mapping 'property.property' field is missing or empty`);
const property = V1_buildEmbeddedRelationalMappingProperty(protocol, this.immediateParent, guaranteeNonNullable(this.topParent), this.context);
const embedded = new EmbeddedRelationalInstanceSetImplementation(this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(property.propertyOwnerClass, protocol.property.class ?? ''), property.property), guaranteeType(this.topParent, RootRelationalInstanceSetImplementation), SetImplementationImplicitReference.create(property.sourceSetImplementation, protocol.source), property._class, InferableMappingElementIdExplicitValue.create(`${property.id.value}`, ''), undefined);
embedded.primaryKey = protocol.classMapping.primaryKey.map((key) => V1_buildRelationalOperationElement(key, this.context, this.tableAliasIndex, []));
embedded.propertyMappings = protocol.classMapping.propertyMappings.map((propertyMapping) => propertyMapping.accept_PropertyMappingVisitor(new V1_PropertyMappingBuilder(this.context, embedded, this.topParent, this.topParent?._PARENT
? getAllEnumerationMappings(this.topParent._PARENT)
: [], this.tableAliasIndex)));
return embedded;
}
visit_OtherwiseEmbeddedRelationalPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Otherwise embedded relational property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Otherwise embedded relational property mapping 'property.property' field is missing or empty`);
const property = V1_buildEmbeddedRelationalMappingProperty(protocol, this.immediateParent, guaranteeNonNullable(this.topParent), this.context);
const otherwiseEmbedded = new OtherwiseEmbeddedRelationalInstanceSetImplementation(this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(property.propertyOwnerClass, protocol.property.class ?? ''), property.property), guaranteeType(this.topParent, RootRelationalInstanceSetImplementation), SetImplementationImplicitReference.create(property.sourceSetImplementation, protocol.source), property._class, InferableMappingElementIdExplicitValue.create(`${property.id.value}`, ''), undefined);
otherwiseEmbedded.primaryKey = protocol.classMapping.primaryKey.map((key) => V1_buildRelationalOperationElement(key, this.context, this.tableAliasIndex, []));
otherwiseEmbedded.propertyMappings =
protocol.classMapping.propertyMappings.map((propertyMapping) => propertyMapping.accept_PropertyMappingVisitor(new V1_PropertyMappingBuilder(this.context, otherwiseEmbedded, this.topParent, this.topParent?._PARENT
? getAllEnumerationMappings(this.topParent._PARENT)
: [], this.tableAliasIndex)));
otherwiseEmbedded.otherwisePropertyMapping = guaranteeType(protocol.otherwisePropertyMapping.accept_PropertyMappingVisitor(new V1_PropertyMappingBuilder(this.context, otherwiseEmbedded, this.topParent, this.topParent?._PARENT
? getAllEnumerationMappings(this.topParent._PARENT)
: [], this.tableAliasIndex)), RelationalPropertyMapping);
return otherwiseEmbedded;
}
visit_XStorePropertyMapping(protocol) {
assertNonNullable(protocol.property, `XStore property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.class, `XStore property mapping 'property.class' field is missing or empty`);
assertNonEmptyString(protocol.property.property, `XStore property mapping 'property.property' field is missing or empty`);
assertNonNullable(protocol.crossExpression, `XStore property mapping 'crossExpression' field is missing`);
const xStoreParent = guaranteeNonNullable(this.xStoreParent, `XStore property 'xStoreParent' field is missing`);
const _association = xStoreParent.association.value;
const property = getOwnProperty(_association, protocol.property.property);
const sourceSetImplementation = guaranteeNonNullable(resolvePropertyMappingSourceImplementation(this.immediateParent, protocol, this.topParent, this.context));
let targetSetImplementation;
const propertyType = property.genericType.value.rawType;
if (propertyType instanceof Class) {
const parentMapping = this.immediateParent._PARENT;
if (protocol.target) {
targetSetImplementation = TEMPORARY__resolveSetImplementationByID(parentMapping, protocol.target, this.context);
}
else {
targetSetImplementation = getClassMappingsByClass(parentMapping, guaranteeType(propertyType, Class))[0];
}
}
const xStorePropertyMapping = new XStorePropertyMapping(xStoreParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(_association, protocol.property.class), property), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), targetSetImplementation
? SetImplementationImplicitReference.create(targetSetImplementation, protocol.target)
: undefined);
xStorePropertyMapping.crossExpression = V1_buildRawLambdaWithResolvedPaths(protocol.crossExpression.parameters, protocol.crossExpression.body, this.context);
return xStorePropertyMapping;
}
visit_AggregationAwarePropertyMapping(protocol) {
assertNonNullable(protocol.property, `Aggregation-aware property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.class, `Aggregation-aware property mapping 'property.class' field is missing or empty`);
assertNonEmptyString(protocol.property.property, `Aggregation-aware property mapping 'property.property' field is missing or empty`);
const aggregationAwareParent = guaranteeNonNullable(this.aggregationAwareParent, `Aggregation-aware property 'aggregationAwareParent' field is missing`);
const propertyMapping = aggregationAwareParent.mainSetImplementation.propertyMappings.find((p) => p.property.value.name === protocol.property.property);
const property = propertyMapping?.property ??
this.context.resolveProperty(protocol.property);
const sourceSetImplementation = guaranteeNonNullable(resolvePropertyMappingSourceImplementation(this.immediateParent, protocol, this.topParent, this.context));
let targetSetImplementation;
const propertyType = property.value.genericType.value.rawType;
if (propertyType instanceof Class) {
const parentMapping = this.immediateParent._PARENT;
if (protocol.target) {
targetSetImplementation = TEMPORARY__resolveSetImplementationByID(parentMapping, protocol.target, this.context);
}
else {
targetSetImplementation = getClassMappingsByClass(parentMapping, guaranteeType(propertyType, Class))[0];
}
}
const aggregationAwarePropertyMapping = new AggregationAwarePropertyMapping(this.topParent ?? this.immediateParent, property, SetImplementationImplicitReference.create(guaranteeNonNullable(sourceSetImplementation), protocol.source), targetSetImplementation
? SetImplementationImplicitReference.create(targetSetImplementation, protocol.target)
: undefined);
if (protocol.localMappingProperty &&
propertyMapping?.localMappingProperty) {
aggregationAwarePropertyMapping.localMappingProperty =
guaranteeNonNullable(propertyMapping.localMappingProperty);
}
return aggregationAwarePropertyMapping;
}
visit_RelationFunctionPropertyMapping(protocol) {
assertNonNullable(protocol.property, `Relation Function property mapping 'property' field is missing`);
assertNonEmptyString(protocol.property.property, `Relation Function property mapping 'property.property' field is missing or empty`);
let propertyOwner;
let property;
let localMapping;
if (protocol.localMappingProperty) {
const localMappingProperty = protocol.localMappingProperty;
const mappingClass = new MappingClass(`${this.topParent?._PARENT.path}_${this.topParent?.id}${protocol.property.property}`);
const _multiplicity = this.context.graph.getMultiplicity(localMappingProperty.multiplicity.lowerBound, localMappingProperty.multiplicity.upperBound);
const _property = new Property(protocol.property.property, _multiplicity, this.context.resolveGenericType(localMappingProperty.type), mappingClass);
property = PropertyImplicitReference.create(PackageableElementImplicitReference.create(mappingClass, protocol.property.class), _property).value;
localMapping = new LocalMappingPropertyInfo();
localMapping.localMappingProperty = true;
localMapping.localMappingPropertyMultiplicity = _multiplicity;
localMapping.localMappingPropertyType = this.context.resolveType(localMappingProperty.type);
propertyOwner = property._OWNER;
}
else {
if (protocol.property.class) {
propertyOwner = this.context.resolveClass(protocol.property.class).value;
}
else {
throw new GraphBuilderError(`Can't find property owner class for property '${protocol.property.property}'`);
}
property =
propertyOwner instanceof Class
? getClassProperty(propertyOwner, protocol.property.property)
: getOwnProperty(propertyOwner, protocol.property.property);
}
const sourceSetImplementation = guaranteeNonNullable(resolvePropertyMappingSourceImplementation(this.immediateParent, protocol, this.topParent, this.context));
const propertyType = property.genericType.value.rawType;
const propertyMapping = new RelationFunctionPropertyMapping(this.topParent ?? this.immediateParent, PropertyImplicitReference.create(PackageableElementImplicitReference.create(propertyOwner, protocol.property.class ?? ''), property), SetImplementationImplicitReference.create(sourceSetImplementation, protocol.source), undefined, new RelationColumn(protocol.column, propertyType));
propertyMapping.localMappingProperty = localMapping;
return propertyMapping;
}
}
//# sourceMappingURL=V1_PropertyMappingBuilder.js.map