internal void RecordModelChange( EfiChange.EfiChangeType changeType, EFObject changed, string property, object oldValue, object newValue) { switch (changeType) { case EfiChange.EfiChangeType.Create: _creates.Add(new EfiChange(changeType, changed)); break; case EfiChange.EfiChangeType.Delete: _deletes.Add(new EfiChange(changeType, changed)); break; case EfiChange.EfiChangeType.Update: EfiChange change = null; if (_updates.ContainsKey(changed)) { change = _updates[changed]; } else { change = new EfiChange(changeType, changed); _updates[changed] = change; } change.RecordModelChange(property, oldValue, newValue); break; } }
internal static ModelNodeChangeType GetChangeTypeFromEfiChange(EfiChange c) { ModelNodeChangeType t; switch (c.Type) { case EfiChange.EfiChangeType.Create: t = ModelNodeChangeType.Added; break; case EfiChange.EfiChangeType.Delete: t = ModelNodeChangeType.Deleted; break; case EfiChange.EfiChangeType.Update: t = ModelNodeChangeType.Changed; break; default: Debug.Fail("unexpected type of EfiChangeType"); throw new InvalidOperationException(); } return t; }
/// <summary> /// Processes a Create or Delete change. /// </summary> /// <returns> /// true if more model changes should be processed; otherwise, false; /// </returns> protected abstract bool ProcessCreateOrDeleteChange(EditingContext ctx, ModelToExplorerModelXRef xref, EfiChange change);
protected abstract int GetVal(EfiChange change);
public EfiChangeStableSortItem(EfiChange change, int position) { _change = change; _position = position; }
protected override bool ProcessCreateOrDeleteChange(EditingContext ctx, ModelToExplorerModelXRef xref, EfiChange change) { var artifact = change.Changed as EFArtifact; var conceptualModel = change.Changed as ConceptualEntityModel; var storageModel = change.Changed as StorageEntityModel; var mappingModel = change.Changed as MappingModel; if (null != artifact || null != conceptualModel || null != storageModel || null != mappingModel) { // reset the search results - they will no longer be valid // once the view model is recalculated below var explorerSearchResults = ExplorerSearchResults.GetExplorerSearchResults(ctx); explorerSearchResults.Reset(); // reload the UI - the ExplorerViewModelChanged will be fired // allowing the frame to rebind CreateViewModel(ctx); // don't process any more return false; } var efElement = change.Changed as EFElement; // ExplorerViewModelHelper only needs to process EFElement changes // (others are DefaultableValue and SingleItemBinding - but // ExplorerViewModel does not currently need to map these latter) if (null != efElement) { var parent = efElement.Parent as EFElement; Debug.Assert( null != parent, "received changed element of type " + change.Changed.GetType().FullName + " with non-EFElement parent of type " + (efElement.Parent == null ? "NULL" : efElement.Parent.GetType().FullName)); if (null != parent) { // special case changing of an entity's key // If we are creating/deleting a Key PropertyRef then we need // to update the underlying ExplorerProperty var propRef = efElement as PropertyRef; var keyElement = efElement as Key; if (propRef != null) { keyElement = propRef.GetParentOfType(typeof(Key)) as Key; if (keyElement != null && null != propRef.Name && null != propRef.Name.Target) { ExplorerEFElement explorerProp = xref.GetExisting(propRef.Name.Target) as ExplorerProperty; if (null != explorerProp) { explorerProp.OnModelPropertyChanged(ExplorerEFElement.IsKeyPropertyID); } } } else if (keyElement != null) { // key must be a child of an entity var et = parent as EntityType; if (et != null) { // the key is being created or completely removed, so sync up every property foreach (var prop in et.Properties()) { ExplorerEFElement explorerProp = xref.GetExisting(prop) as ExplorerProperty; if (null != explorerProp) { explorerProp.OnModelPropertyChanged(ExplorerEFElement.IsKeyPropertyID); } } } } else { // find Explorer node which maps to the model's parent // this can be null is the ViewModel does not map the // parent object if (typeof(FunctionImport) == efElement.GetType()) { // the FunctionImport Explorer Parent node has been decided to be the ConceptualEntityModel ExplorerEFElement // rather than the ConceptualEntityContainer one which we would more naturally use to match the model setup parent = parent.Parent as EFElement; } var explorerParentItem = xref.GetExisting(parent); if (null != explorerParentItem) { // now find the Explorer node which should be the new/deleted ViewModel element's parent // (may not be the same as above due to Explorer ghost nodes) explorerParentItem = explorerParentItem.GetParentNodeForElement(efElement); if (EfiChange.EfiChangeType.Create == change.Type) { // It's possible that between the Create of a parent and its child // the Children property is called on the parent which loads the // child into the parent, even though the child is being added with // change.Type = Create. For safety, we should remove the existing // child (if it exists) so as to ensure any changes in the child change // are reflected. var explorerEFElement = xref.GetExisting(efElement); if (explorerEFElement != null) { explorerParentItem.RemoveChildIfLoaded(efElement); } explorerParentItem.InsertChildIfLoaded(efElement); } else { explorerParentItem.RemoveChildIfLoaded(efElement); } } } } } return true; }
/// <summary> /// Updates corresponding view model item. /// For simplicity each change updates all item values. /// </summary> private void OnEFObjectUpdated(EfiChange change, ModelToDesignerModelXRefItem xref) { Debug.Assert(change.Changed != null); var efObject = change.Changed; // Updating a base type is a special case, because it really means creating or deleting an inheritance connector var baseType = efObject as EntityTypeBaseType; if (baseType != null) { if (xref.ContainsKey(baseType.Parent)) { // always recreate inheritance OnEFObjectDeleted(baseType, xref); if (xref.ContainsKey(baseType.Parent)) { ModelTranslatorContextItem.GetEntityModelTranslator(EditingContext).SynchronizeSingleDslModelElement(this, efObject); } } return; } // for AssociationEnd we want to update parent Association var associationEnd = efObject as AssociationEnd; if (associationEnd != null) { efObject = associationEnd.Parent; } // regardless the change always update whole element (it shouldn't be too big overhead) OnEFObjectCreatedOrUpdated(efObject, xref); }
protected override int GetVal(EfiChange change) { // we always order deletes before creates before updates. if (change.Type == EfiChange.EfiChangeType.Update) { return 100; } else if (change.Type == EfiChange.EfiChangeType.Delete) { return -1; } else { Debug.Assert(change.Type == EfiChange.EfiChangeType.Create); var entityType = change.Changed as Model.Entity.EntityType; if (entityType != null) { return 1; } var association = change.Changed as Model.Entity.Association; if (association != null) { return 2; } var prop = change.Changed as Model.Entity.Property; if (prop != null) { return 3; } var propertyRef = change.Changed as PropertyRef; if (propertyRef != null) { return 4; } var key = change.Changed as Key; if (key != null) { return 5; } var ets = change.Changed as ModelDesigner.EntityTypeShape; if (ets != null) { return 6; } var ac = change.Changed as ModelDesigner.AssociationConnector; if (ac != null) { return 7; } var ic = change.Changed as ModelDesigner.InheritanceConnector; if (ic != null) { return 8; } return 9; } }
/// <summary> /// Project the Diagram Model changes to DSL Model Elements. /// Note that this is only to ensure that DSL Model Elements are in sync with the diagram model. /// </summary> private void ProcessSingleDiagramModelChange(EfiChange change, HashSet<EFObject> extraElementsToProcess) { var diagramObject = change.Changed as ModelDiagram.BaseDiagramObject; var xref = ModelXRef; // Ignore if the change is not model diagram object or diagram object does not below to this view model diagram. if (diagramObject == null || diagramObject.Diagram == null || diagramObject.Diagram.Id != DiagramId) { return; } if (change.Type == EfiChange.EfiChangeType.Create) { EFObject efObject = null; var entityTypeShape = change.Changed as ModelDesigner.EntityTypeShape; var inheritanceConnector = change.Changed as ModelDesigner.InheritanceConnector; var associationConnector = change.Changed as ModelDesigner.AssociationConnector; if (entityTypeShape != null) { // There is a code above that will Debug.Fail if the object in extraElementsToProcess is not ConceptualEntityType Model.Entity.EntityType et = entityTypeShape.EntityType.Target as ConceptualEntityType; if (et != null) { extraElementsToProcess.Add(et); efObject = et; } } else if (inheritanceConnector != null) { var et = inheritanceConnector.EntityType.Target as ConceptualEntityType; if (et != null) { efObject = et.BaseType; } } else if (associationConnector != null) { efObject = associationConnector.Association.Target; } if (efObject != null) { OnEFObjectCreatedOrUpdated(efObject, xref); } } else if (change.Type == EfiChange.EfiChangeType.Delete) { var entityTypeShape = change.Changed as ModelDesigner.EntityTypeShape; var inheritanceConnector = change.Changed as ModelDesigner.InheritanceConnector; var associationConnector = change.Changed as ModelDesigner.AssociationConnector; EFObject efObject = null; if (entityTypeShape != null) { efObject = entityTypeShape.EntityType.Target; } else if (inheritanceConnector != null) { var et = inheritanceConnector.EntityType.Target as ConceptualEntityType; if (et != null) { efObject = et.BaseType; } } else if (associationConnector != null) { efObject = associationConnector.Association.Target; } if (efObject != null) { OnEFObjectDeleted(efObject, xref); } } }
private bool ProcessSingleModelChange(EfiChange change) { var xref = ModelXRef; if ((change.Type == EfiChange.EfiChangeType.Create || change.Type == EfiChange.EfiChangeType.Delete) && (change.Changed is EFArtifact || change.Changed is ConceptualEntityModel)) { // the artifact or model has changed on us, reload the whole thing ClearAndReloadDiagram(); return true; } else { try { switch (change.Type) { case EfiChange.EfiChangeType.Update: OnEFObjectUpdated(change, xref); break; case EfiChange.EfiChangeType.Create: // Adding association, entity-type or inheritance is no longer translate to the addition of the corresponding DSL model elements. // We only add the DSL model elements if Escher model diagrams are added (InheritanceConnector etc.) if (!(change.Changed is Model.Entity.Association || change.Changed is ConceptualEntityType || change.Changed is EntityTypeBaseType)) { OnEFObjectUpdated(change, xref); } break; case EfiChange.EfiChangeType.Delete: OnEFObjectDeleted(change.Changed, xref); break; default: Debug.Assert(false, "Unknown change type."); break; } // If Entity-type's base type has changed, invalidate the shape so the base type name in the shape can be updated. var baseType = change.Changed as EntityTypeBaseType; if (baseType != null) { Debug.Assert(baseType.Parent != null, "EntityTypeBaseType's Parent should not be null."); if (baseType.Parent != null) { var entityType = ModelXRef.GetExisting(baseType.Parent) as EntityType; // the entity type is null if it is not in the diagram. if (entityType != null) { var ets = PresentationViewsSubject.GetPresentation(entityType).FirstOrDefault() as EntityTypeShape; Debug.Assert(ets != null, "The shape for entity-type : " + entityType.Name + " is not available."); if (ets != null) { ets.Invalidate(); } } } } } catch (Exception e) { Debug.Fail("Exception caught while processing changes to the designer", e.Message); ClearAndReloadDiagram(); return true; } } return false; }