Ejemplo n.º 1
0
        public static PIMPath BuildPIMPath(PropertyCallExp node)
        {
            PIMPath path = new PIMPath();

            OclExpression s;

            if (node.ReferredProperty.Tag is PIMAssociationEnd)
            {
                s = node;
            }
            else
            {
                PIMAttribute a = (PIMAttribute)node.ReferredProperty.Tag;

                PIMPathAttributeStep pathAttributeStep = new PIMPathAttributeStep {
                    Attribute = a
                };
                path.Steps.Add(pathAttributeStep);
                s = node.Source;
            }

            while (!(s is VariableExp))
            {
                PIMPathAssociationStep step = new PIMPathAssociationStep();
                step.AssociationEnd = (PIMAssociationEnd)((PropertyCallExp)s).ReferredProperty.Tag;
                path.Steps.Insert(0, step);
                s = ((PropertyCallExp)s).Source;
            }

            PIMPathVariableStep pathVariableStep = new PIMPathVariableStep();

            pathVariableStep.VariableExp = (VariableExp)s;
            path.Steps.Insert(0, pathVariableStep);
            return(path);
        }
Ejemplo n.º 2
0
        private bool FindNavigationsForPIMNavigationRecursive(PIMPath pimPath, int stepIndex, PSMAssociationMember currentMember, PSMPath builtPath, bool canGoToParent, ref List <PSMPath> result, PSMAssociation associationUsedAlready)
        {
            if (stepIndex == pimPath.Steps.Count)
            {
                result.Add(builtPath);
                return(true);
            }

            PIMPathStep currentStep = pimPath.Steps[stepIndex];

            if (currentStep is PIMPathAssociationStep)
            {
                Debug.Assert(currentMember != null);
                PIMPathAssociationStep      nextStep   = (PIMPathAssociationStep)currentStep;
                List <PSMAssociationMember> candidates = currentMember.ChildPSMAssociations.Where(a => allowNonTree || !a.IsNonTreeAssociation).Select(a => a.Child).ToList();

                /*
                 * we forbid non-tree associations for now,
                 * it certainly makes thinks easier and I am not sure
                 * whether it is really a restriction
                 */
                List <PSMAssociation> candidatesAssociations = currentMember.ChildPSMAssociations.Where(a => allowNonTree || !a.IsNonTreeAssociation).ToList();
                PSMAssociationMember  parent = currentMember.ParentAssociation != null ? currentMember.ParentAssociation.Parent : null;

                if (parent != null && canGoToParent && !(parent is PSMSchemaClass))
                {
                    bool candidateParent = true;
                    if (currentMember.ParentAssociation.Interpretation != null)
                    {
                        PIMAssociation    interpretedAssociation = (PIMAssociation)currentMember.ParentAssociation.Interpretation;
                        PIMAssociationEnd interpretedEnd         = currentMember.ParentAssociation.InterpretedAssociationEnd;
                        PIMAssociationEnd oppositeEnd            = interpretedAssociation.PIMAssociationEnds.Single(e => e != interpretedEnd);

                        // upwards navigation on ends with upper cardinality > 1 breaks semantics of the expression
                        if (oppositeEnd.Upper > 1)
                        {
                            candidateParent = false;
                        }
                    }

                    if (candidateParent)
                    {
                        candidates.Add(parent);
                        candidatesAssociations.Add(currentMember.ParentAssociation);
                    }
                }
                bool found = false;
                for (int index = 0; index < candidates.Count; index++)
                {
                    PSMAssociationMember candidate            = candidates[index];
                    PSMAssociation       candidateAssociation = candidatesAssociations[index];
                    bool parentStep = candidate == parent && !candidateAssociation.IsNonTreeAssociation;
                    // forbid traversing the same association several times
                    if (associationUsedAlready == candidateAssociation)
                    {
                        continue;
                    }

                    int nextStepIndex = stepIndex;

                    bool interpretedClassSatisfies = candidateAssociation.Interpretation != null &&
                                                     candidate.DownCastSatisfies <PSMClass>(c => c.Interpretation == nextStep.Class);
                    if (candidate.Interpretation == null || interpretedClassSatisfies)
                    {
                        PSMPath nextBuiltPath = (PSMPath)builtPath.Clone();
                        nextBuiltPath.Steps.Add(new PSMPathAssociationStep(nextBuiltPath)
                        {
                            Association = candidateAssociation, To = candidate, From = currentMember,
                            IsUp        = candidateAssociation.Parent == candidate
                        });

                        if (interpretedClassSatisfies)
                        {
                            nextStepIndex++;
                        }

                        found |= FindNavigationsForPIMNavigationRecursive(pimPath, nextStepIndex, candidate, nextBuiltPath,
                                                                          canGoToParent && !parentStep, ref result, parentStep ? candidateAssociation : null);
                    }
                }
                return(found);
            }
            else if (currentStep is PIMPathVariableStep)
            {
                Debug.Assert(currentMember == null);
                PIMPathVariableStep    pathVariableStep = (PIMPathVariableStep)currentStep;
                IEnumerable <PSMClass> candidates       = TargetPSMSchema.PSMClasses.Where(c => c.Interpretation == pimPath.StartingClass);
                if (!VariableClassMappings.ContainsKey(pathVariableStep.Variable))
                {
                    return(false);
                }
                candidates = candidates.Intersect(VariableClassMappings[pathVariableStep.Variable]);
                bool            found = false;
                List <PSMClass> eliminatedCandidates = new List <PSMClass>();
                eliminatedCandidates.AddRange(VariableClassMappings[pathVariableStep.Variable].Except(candidates));
                foreach (PSMClass candidate in candidates)
                {
                    PSMBridgeClass startType = psmBridge.Find(candidate);
                    builtPath = new PSMPath();
                    VariableDeclaration vd;
                    if (!variableTranslations.ContainsKey(pathVariableStep.Variable))
                    {
                        vd = new VariableDeclaration(pathVariableStep.Variable.Name, startType, null);
                        variableTranslations[pathVariableStep.Variable] = vd;
                    }
                    else
                    {
                        vd = variableTranslations[pathVariableStep.Variable];
                    }

                    builtPath.Steps.Add(new PSMPathVariableStep(builtPath)
                    {
                        VariableExp = new VariableExp(vd)
                    });
                    bool candidateUsable = FindNavigationsForPIMNavigationRecursive(pimPath, stepIndex + 1, candidate, builtPath, true, ref result, null);
                    if (!candidateUsable)
                    {
                        eliminatedCandidates.Add(candidate);
                    }
                    found |= candidateUsable;
                }
                VariableClassMappings[pathVariableStep.Variable].RemoveAll(eliminatedCandidates.Contains);
                if (PathMappings.ContainsKey(pimPath))
                {
                    PathMappings[pimPath].RemoveAll(p => eliminatedCandidates.Contains(p.StartingClass));
                }
                return(found);
            }
            else if (currentStep is PIMPathAttributeStep)
            {
                PIMPathAttributeStep pathAttributeStep = (PIMPathAttributeStep)currentStep;
                Debug.Assert(currentMember is PSMClass);

                bool found = false;
                foreach (PSMAttribute psmAttribute in ((PSMClass)currentMember).PSMAttributes)
                {
                    if (psmAttribute.Interpretation == pathAttributeStep.Attribute)
                    {
                        PSMPath nextBuiltPath = (PSMPath)builtPath.Clone();
                        nextBuiltPath.Steps.Add(new PSMPathAttributeStep(nextBuiltPath)
                        {
                            Attribute = psmAttribute
                        });
                        result.Add(nextBuiltPath);
                        found |= true;
                    }
                }
                return(found);
            }
            else
            {
                throw new NotImplementedException();
            }
        }