core.pure.treepath.treePath.pure Maven / Gradle / Ivy
// Copyright 2020 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 meta::pure::metamodel::treepath::*;
Class meta::pure::metamodel::treepath::PropertyPathTreeNode extends meta::pure::functions::collection::TreeNode{
property : AbstractProperty[0..1];
children(){
$this.childrenData->cast(@PropertyPathTreeNode)
}:PropertyPathTreeNode[*];
}
function meta::pure::metamodel::treepath::buildPropertyPathTree(dfts:LambdaFunction<{T[1]->Any[*]}>[*]):PropertyPathTreeNode[1]
{
let threads = $dfts->map(dft|^PropertyPathTreeNode(childrenData=$dft.expressionSequence->at(0)->buildPropertyPath([])));
$threads->mergePropertyPaths();
}
function meta::pure::metamodel::treepath::tp_removeAutomap(v:ValueSpecification[1]):ValueSpecification[1]
{
$v->match([fe:FunctionExpression[1] | if($fe.functionName=='map',| let left = $fe.parametersValues->at(0);
let prop = $fe.parametersValues->at(1)->cast(@InstanceValue).values->at(0)->cast(@LambdaFunction).expressionSequence->at(0)->cast(@FunctionExpression);
let leftUnMapped = $left->tp_removeAutomap();
^$prop(parametersValues=$leftUnMapped);
,| $fe);,
v:ValueSpecification[1] | $v]);
}
function <> meta::pure::metamodel::treepath::buildPropertyPath(vs:ValueSpecification[1], child:PropertyPathTreeNode[0..1]):PropertyPathTreeNode[1]
{
$vs->evaluateAndDeactivate()
->match([ r:RoutedValueSpecification[1] | $r.value->buildPropertyPath($child),
v:VariableExpression[1] | if($child->isNotEmpty(),|$child->toOne(),|assert(false,'Unsupported Deep Fetch Path');^PropertyPathTreeNode();),
fe:FunctionExpression[1] | let unMappedFe = $fe->tp_removeAutomap()->cast(@FunctionExpression);
let property = $unMappedFe.func->cast(@AbstractProperty);
let parent = ^PropertyPathTreeNode(property=$property, childrenData=$child);
$unMappedFe.parametersValues->map(p|$p->buildPropertyPath($parent))->toOne();
]);
}
function <> meta::pure::metamodel::treepath::mergePropertyPaths(roots:PropertyPathTreeNode[*]):PropertyPathTreeNode[1]
{
let distinctTypes = $roots.property->type()->distinct();
assert($distinctTypes->size()==1,| 'Deep fetch Property paths should be of the same Type: '+$distinctTypes.name->makeString());
let mergedPaths = $roots.children()->fold({n, a| $a->mergeChildPropertyPathTreeNodes($n)}, []->cast(@PropertyPathTreeNode));
^PropertyPathTreeNode(childrenData=$mergedPaths);
}
function <> meta::pure::metamodel::treepath::mergeChildPropertyPathTreeNodes(dfns:PropertyPathTreeNode[*], n:PropertyPathTreeNode[1]):PropertyPathTreeNode[*]
{ let mergeNode = $dfns->filter(d|$d.property == $n.property);
if( $mergeNode->isEmpty(),|$dfns->concatenate($n);
,|assert($mergeNode->size() == 1,'Deep fetch tree merging found more than one merge compatible deep fetch nodes');
let oneMergeNode = $mergeNode->at(0);
let mergedChildren = $mergeNode.children()->concatenate($n.children())->fold({n, a| $a->mergeChildPropertyPathTreeNodes($n) }, []->cast(@PropertyPathTreeNode));
let mergeNodeWithMergedChildren = ^$oneMergeNode(childrenData=$mergedChildren);
$dfns->filter(n|$n != $oneMergeNode)->concatenate($mergeNodeWithMergedChildren);
);
}