public override void ElementAdded(ElementAddedEventArgs e) { base.ElementAdded(e); Generalization element = (Generalization)e.ModelElement; Store store = element.Store; Transaction current = store.TransactionManager.CurrentTransaction; if (current.IsSerializing || ModelRoot.BatchUpdating) { return; } if (element.IsInCircularInheritance()) { ErrorDisplay.Show(store, $"{element.Subclass.Name} -> {element.Superclass.Name}: That inheritance link would cause a circular reference."); current.Rollback(); return; } List <string> superclassPropertyNames = element.Superclass.AllPropertyNames.ToList(); List <string> nameClashes = element.Subclass .Attributes .Where(a => superclassPropertyNames.Contains(a.Name)) .Select(a => a.Name) .Union(element.Subclass .LocalNavigationProperties() .Where(p => p.PropertyName != null && superclassPropertyNames.Contains(p.PropertyName)) .Select(p => p.PropertyName)) .ToList(); // remove attributes in subclass that are present in superclass IF they are completely identical (except for ModelClass, of course) for (int i = 0; i < nameClashes.Count; i++) { ModelAttribute subclassAttribute = element.Subclass.Attributes.First(a => a.Name == nameClashes[i]); ModelAttribute superclassAttribute = element.Superclass.AllAttributes.First(a => a.Name == nameClashes[i]); List <(string propertyName, object thisValue, object otherValue)> differences = superclassAttribute.GetDifferences(subclassAttribute); // ignore these differences if found differences.RemoveAll(x => x.propertyName == "ModelClass" || x.propertyName == "Summary" || x.propertyName == "Description"); if (!differences.Any()) { element.Subclass.Attributes.Remove(element.Subclass.Attributes.Single(a => a.Name == nameClashes[i])); nameClashes.RemoveAt(i--); } } // if any remain with the same name, it's an error if (nameClashes.Any()) { string nameClashList = string.Join("\n ", nameClashes); ErrorDisplay.Show(store, $"{element.Subclass.Name} -> {element.Superclass.Name}: That inheritance link would cause name clashes. Resolve the following before setting the inheritance:\n {nameClashList}"); current.Rollback(); } }
/// <inheritdoc /> public override void ElementDeleting(ElementDeletingEventArgs e) { base.ElementDeleting(e); Generalization element = (Generalization)e.ModelElement; Store store = element.Store; Transaction current = store.TransactionManager.CurrentTransaction; if (current.IsSerializing) { return; } if (element.Superclass.IsDeleting) { return; } ModelClass superclass = element.Superclass; ModelClass subclass = element.Subclass; List <Association> associations = store.ElementDirectory.AllElements.OfType <Association>().Where(a => a.Source == superclass || a.Target == superclass).ToList(); if (!superclass.AllAttributes.Any() && !associations.Any()) { return; } if (!subclass.IsDeleting && QuestionDisplay.Show($"Push {superclass.Name} attributes and associations down to {subclass.Name}?") == true) { superclass.PushDown(subclass); } }
public override string GetToolTipText(DiagramItem item) { Generalization generalization = item.Shape.ModelElement as Generalization; return(generalization != null ? $"{generalization.Subclass.Name} inherits from {generalization.Superclass.Name}" : string.Empty); }
public override void ElementAdded(ElementAddedEventArgs e) { base.ElementAdded(e); Generalization element = (Generalization)e.ModelElement; Store store = element.Store; Transaction current = store.TransactionManager.CurrentTransaction; if (current.IsSerializing) { return; } if (element.IsInCircularInheritance()) { ErrorDisplay.Show($"{element.Subclass.Name} -> {element.Superclass.Name}: That inheritance link would cause a circular reference."); current.Rollback(); return; } List <string> superclassPropertyNames = element.Superclass .AllAttributes .Select(a => a.Name) .Union(element.Superclass .AllNavigationProperties() .Where(x => x.PropertyName != null) .Select(a => a.PropertyName)) .ToList(); List <string> nameClashes = element.Subclass .Attributes .Where(a => superclassPropertyNames.Contains(a.Name)) .Select(a => a.Name) .Union(element.Subclass .LocalNavigationProperties() .Where(p => p.PropertyName != null && superclassPropertyNames.Contains(p.PropertyName)) .Select(p => p.PropertyName)) .ToList(); // since we created the Id property, we'll remove it. Any other clashes are up to the user to resolve. if (nameClashes.Contains("Id") && element.Subclass.Attributes.FirstOrDefault(a => a.Name == "Id")?.IsIdentity == true && element.Superclass.AllAttributes.FirstOrDefault(a => a.Name == "Id")?.IsIdentity == true) { element.Subclass.Attributes.Remove(element.Subclass.Attributes.Single(a => a.Name == "Id")); nameClashes.Remove("Id"); } if (nameClashes.Any()) { string nameClashList = string.Join("\n ", nameClashes); ErrorDisplay.Show($"{element.Subclass.Name} -> {element.Superclass.Name}: That inheritance link would cause name clashes. Resolve the following before setting the inheritance:\n {nameClashList}"); current.Rollback(); } }
public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e) { base.ElementPropertyChanged(e); Generalization element = (Generalization)e.ModelElement; Store store = element.Store; Transaction current = store.TransactionManager.CurrentTransaction; if (current.IsSerializing) { return; } switch (e.DomainProperty.Name) { case "Superclass": case "Subclass": if (!element.IsInCircularInheritance()) { current.Rollback(); MessageBox.Show("That inheritance link would cause a circular reference."); return; } if (element.Superclass != null) { List <string> superclassPropertyNames = element.Superclass .AllAttributes .Select(a => a.Name) .Union(element.Superclass .AllNavigationProperties() .Select(a => a.PropertyName)) .ToList(); List <string> nameClashes = element.Subclass .Attributes .Where(a => superclassPropertyNames.Contains(a.Name)) .Select(a => a.Name) .Union(element.Subclass .LocalNavigationProperties() .Where(p => p.PropertyName != null && superclassPropertyNames.Contains(p.PropertyName)) .Select(p => p.PropertyName)) .ToList(); // the Add rule removes the subclass Id property if it's causing a name class, but we won't do that in the change rule if (nameClashes.Any()) { current.Rollback(); string nameClashList = string.Join(", ", nameClashes); MessageBox.Show("That inheritance link would cause name clashes. Resolve the following before setting the inheritance: " + nameClashList); } } break; } }
/// <inheritdoc /> public override void ElementDeleting(ElementDeletingEventArgs e) { base.ElementDeleting(e); Generalization element = (Generalization)e.ModelElement; Store store = element.Store; Transaction current = store.TransactionManager.CurrentTransaction; if (current.IsSerializing || ModelRoot.BatchUpdating) { return; } if (element.Superclass.IsDeleting) { return; } ModelClass subclass = element.Subclass; ModelClass superclass = element.Superclass; List <Association> associations = superclass.AllNavigationProperties() .Select(n => n.AssociationObject) .Distinct() .ToList(); if (!superclass.AllAttributes.Any() && !associations.Any()) { return; } if (!subclass.IsDeleting && BooleanQuestionDisplay.Show(store, $"Push {superclass.Name} attributes and associations down to {subclass.Name}?") == true) { superclass.PushDown(subclass); } }
public override void ElementPropertyChanged(ElementPropertyChangedEventArgs e) { base.ElementPropertyChanged(e); Generalization element = (Generalization)e.ModelElement; if (element.IsDeleted) { return; } Store store = element.Store; Transaction current = store.TransactionManager.CurrentTransaction; if (current.IsSerializing || ModelRoot.BatchUpdating) { return; } if (Equals(e.NewValue, e.OldValue)) { return; } switch (e.DomainProperty.Name) { case "Superclass": case "Subclass": if (element.Subclass.IsPropertyBag && !element.Superclass.IsPropertyBag) { ErrorDisplay.Show(store, $"{element.Subclass.Name} -> {element.Superclass.Name}: Since {element.Subclass.Name} is a property bag, it can't inherit from {element.Superclass.Name}, which is not a property bag."); current.Rollback(); return; } if (!element.IsInCircularInheritance()) { ErrorDisplay.Show(store, $"{element.Subclass.Name} -> {element.Superclass.Name}: That inheritance link would cause a circular reference."); current.Rollback(); return; } if (element.Superclass != null) { List <string> superclassPropertyNames = element.Superclass .AllAttributes .Select(a => a.Name) .Union(element.Superclass .AllNavigationProperties() .Select(a => a.PropertyName)) .ToList(); List <string> nameClashes = element.Subclass .Attributes .Where(a => superclassPropertyNames.Contains(a.Name)) .Select(a => a.Name) .Union(element.Subclass .LocalNavigationProperties() .Where(p => p.PropertyName != null && superclassPropertyNames.Contains(p.PropertyName)) .Select(p => p.PropertyName)) .ToList(); // the Add rule removes the subclass Id property if it's causing a name class, but we won't do that in the change rule if (nameClashes.Any()) { string nameClashList = string.Join("\n ", nameClashes); ErrorDisplay.Show(store, $"{element.Subclass.Name} -> {element.Superclass.Name}: That inheritance link would cause name clashes. Resolve the following before setting the inheritance:\n " + nameClashList); current.Rollback(); } } break; } }