private QVTTemplate.IPropertyTemplateItem ConstructPropertyTemplateItem(QVTRelations.IRelation relation, QVTRelations.IDomainPattern domainPattern, QVTTemplate.IObjectTemplateExp objectTemplateExp, EnAr.Connector connector, EnAr.ConnectorEnd connectorEnd, EnAr.Element linkedElement, ISet <EnAr.Connector> visitedConnectors) { EssentialOCL.IOclExpression value; EMOF.IType type; QVTTemplate.IObjectTemplateExp targetObjectTemplateExp; ISet <EnAr.Connector> realVisitedConnectors = visitedConnectors ?? new HashSet <EnAr.Connector>(); ISet <EnAr.Connector> realVisitedConnectorsPropagated = new HashSet <EnAr.Connector>(realVisitedConnectors); realVisitedConnectorsPropagated.Add(connector); // Case cycle among object templates: simple variable expression if (objectElementToObjectTemplate.ContainsKey(linkedElement)) { targetObjectTemplateExp = objectElementToObjectTemplate[linkedElement]; EssentialOCL.IVariable existingVariable = targetObjectTemplateExp.BindsTo; value = new EssentialOCL.VariableExp() { ReferredVariable = existingVariable }; type = existingVariable.Type; } // Case no cycle; recursive creation of object template else { targetObjectTemplateExp = ConstructObjectTemplateExp(relation, domainPattern, linkedElement, realVisitedConnectorsPropagated); value = targetObjectTemplateExp; type = ((QVTTemplate.IObjectTemplateExp)value).BindsTo.Type; } EMOF.IProperty property = null; // If the connector end has a role, we use it to find the corresponding EMOF property if (!string.IsNullOrWhiteSpace(connectorEnd.Role)) { property = objectTemplateExp.ReferredClass.GetAllInheritedAttributes().Single(p => p.Name == connectorEnd.Role); } // If the connector end has no role (due to the else) // AND if we haven't visited the connector yet // AND if the connector has no roles whatsoever, we try to guess the type else if (!realVisitedConnectors.Contains(connector) && connector.ClientEnd.Role.IsNullOrEmpty() && connector.SupplierEnd.Role.IsNullOrEmpty()) { IList <EMOF.IProperty> candidateProperties = objectTemplateExp.ReferredClass.GetAllInheritedAttributes().Where(p => (p.Type as EMOF.IClass)?.GetAllSubTypes().Contains(type) ?? p.Type == type).ToList(); if (candidateProperties.Count == 0) { throw new InvalidQVTRelationsModelException("Relation " + relation.Name + ", invalid property connector between " + objectTemplateExp.BindsTo.Name + " and " + targetObjectTemplateExp.BindsTo.Name + ", no possible property", connector); } if (candidateProperties.Count > 1) { throw new InvalidQVTRelationsModelException("Relation " + relation.Name + ", ambiguous property connector between " + objectTemplateExp.BindsTo.Name + " and " + targetObjectTemplateExp.BindsTo.Name + ", cannot choose a property between the following: [" + string.Join(";", candidateProperties.Select(p => p.Name)) + "]", connector); } property = candidateProperties.Single(); } QVTTemplate.PropertyTemplateItem propertyTemplateItem = null; if (property != null) { propertyTemplateItem = new QVTTemplate.PropertyTemplateItem() { ReferredProperty = property, Value = value, IsOpposite = false, // TODO? ObjContainer = objectTemplateExp }; } return(propertyTemplateItem); }
/// <summary> /// Creates a new instance /// </summary> public VariableExpReferencedElementsCollection(VariableExp parent) { this._parent = parent; }