/// <summary> /// Customize childshape create to set an initial location for a <see cref="BarkerEntityShape"/> /// </summary> protected override ShapeElement CreateChildShape(ModelElement element) { object barkerEntityPositionsObject; Dictionary <Guid, PointD> barkerEntityPositions; PointD initialLocation; BarkerErModelContainsBinaryAssociation modelContainsAssociation; EntityType barkerEntity; ConceptType conceptType; ObjectType objectType; if (null != (barkerEntity = element as EntityType)) { if (element.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo.TryGetValue(BarkerEntityPositionDictionaryKey, out barkerEntityPositionsObject) && null != (barkerEntityPositions = barkerEntityPositionsObject as Dictionary <Guid, PointD>) && null != (conceptType = EntityTypeIsPrimarilyForConceptType.GetConceptType(barkerEntity)) && null != (objectType = ConceptTypeIsForObjectType.GetObjectType(conceptType)) && barkerEntityPositions.TryGetValue(objectType.Id, out initialLocation)) { return(new BarkerEntityShape( this.Partition, new PropertyAssignment(BarkerEntityShape.AbsoluteBoundsDomainPropertyId, new RectangleD(initialLocation, new SizeD(1, 0.3))))); } } else if (null != (modelContainsAssociation = element as BarkerErModelContainsBinaryAssociation)) { return(new AssociationConnector(Partition)); } return(base.CreateChildShape(element)); }
/// <summary> /// Serializes this <see cref="BarkerERDiagram"/>. /// </summary> /// <param name="writer">A <see cref="T:System.Xml.XmlWriter"/> that will write the custom serialization contents.</param> void IXmlSerializable.WriteXml(XmlWriter writer) { string rvNamespace = BarkerERShapeDomainModel.XmlNamespace; // <BarkerERDiagram> // <BarkerEntityShape ObjectTypeRef="" Location="x, y" /> // ... // </BarkerERDiagram> ISerializationContext serializationContext = ((ISerializationContextHost)Store).SerializationContext; writer.WriteStartElement(BarkerERDiagramElementName, rvNamespace); writer.WriteAttributeString(IdAttributeName, serializationContext.GetIdentifierString(Id)); writer.WriteAttributeString(SubjectRefAttributeName, serializationContext.GetIdentifierString(this.ModelElement.Id)); TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(PointD)); foreach (ShapeElement shapeElement in this.NestedChildShapes) { BarkerEntityShape barkerEntityShape = shapeElement as BarkerEntityShape; if (barkerEntityShape != null) { ConceptType conceptType; ObjectType objectType; if (null != (conceptType = EntityTypeIsPrimarilyForConceptType.GetConceptType((EntityType)barkerEntityShape.ModelElement)) && null != (objectType = ConceptTypeIsForObjectType.GetObjectType(conceptType))) { writer.WriteStartElement(BarkerEntityShapeElementName, rvNamespace); writer.WriteAttributeString(ObjectTypeRefAttributeName, serializationContext.GetIdentifierString(objectType.Id)); writer.WriteAttributeString(LocationAttributeName, typeConverter.ConvertToInvariantString(barkerEntityShape.Location)); writer.WriteEndElement(); } } } writer.WriteEndElement(); }
/// <summary> /// DeletingRule: typeof(ORMSolutions.ORMArchitect.ORMAbstractionToBarkerERBridge.EntityTypeIsPrimarilyForConceptType) /// Cache the position of the <see cref="BarkerEntityShape"/> corresponding to the object type being deleted /// </summary> private static void ConceptTypeDetachingFromEntityTypeRule(ElementDeletingEventArgs e) { EntityTypeIsPrimarilyForConceptType link = (EntityTypeIsPrimarilyForConceptType)e.ModelElement; ObjectType objectType; if (null != (objectType = ConceptTypeIsForObjectType.GetObjectType(link.ConceptType)) && !objectType.IsDeleting) { RememberBarkerEntityShapeLocations(objectType, link.EntityType); } }
/// <summary> /// DeletingRule: typeof(ORMSolutions.ORMArchitect.ORMToORMAbstractionBridge.ConceptTypeIsForObjectType) /// Cache the position of the <see cref="BarkerEntityShape"/> corresponding to the object type being deleted /// </summary> private static void ConceptTypeDetachingFromObjectTypeRule(ElementDeletingEventArgs e) { ConceptTypeIsForObjectType link = (ConceptTypeIsForObjectType)e.ModelElement; ObjectType objectType = link.ObjectType; EntityType barkerEntity; if (!objectType.IsDeleting && null != (barkerEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(link.ConceptType))) { RememberBarkerEntityShapeLocations(objectType, barkerEntity); } }
/// <summary> /// for many-to-many associations; it is assumed that IsSimpleManyToManyAssociation has been /// called on the passed-in concept type and returned true /// </summary> /// <param name="parentConceptType"></param> /// <param name="notifyAdded"></param> /// <param name="associationCounter"></param> private static void CreateBinaryAssociation(ConceptType parentConceptType, INotifyElementAdded notifyAdded, ref int associationCounter) { if (BinaryAssociationHasConceptType.GetBinaryAssociation(parentConceptType).Count == 0) { LinkedElementCollection <ConceptTypeChild> associationChildren = ConceptTypeHasChildAsPartOfAssociation.GetTargetCollection(parentConceptType); ConceptTypeChild relation1, relation2; ConceptType ct1, ct2; if (null != (relation1 = associationChildren[0]) && null != (relation2 = associationChildren[1]) && null != (ct1 = relation1.Target as ConceptType) && null != (ct2 = relation2.Target as ConceptType)) { // create association BinaryAssociation b = new BinaryAssociation(parentConceptType.Store, new PropertyAssignment[] { new PropertyAssignment(BinaryAssociation.NumberDomainPropertyId, associationCounter++) }); //new BinaryAssociationHasConceptTypeChild(b, relation); BinaryAssociationHasConceptType.GetConceptType(b).Add(parentConceptType); Role r1 = new Role(parentConceptType.Store, new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, ct1.Name) }); Role r2 = new Role(parentConceptType.Store, new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, ct2.Name) }); b.RoleCollection.Add(r1); b.RoleCollection.Add(r2); EntityType sourceEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(ct1); EntityType targetEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(ct2); sourceEntity.RoleCollection.Add(r1); targetEntity.RoleCollection.Add(r2); sourceEntity.BarkerErModel.BinaryAssociationCollection.Add(b); //determine whether roles are mandatory or optional //TODO //set multi-values r1.IsMultiValued = true; r2.IsMultiValued = true; //notify elements added if (notifyAdded != null) { notifyAdded.ElementAdded(b, true); notifyAdded.ElementAdded(r1, true); notifyAdded.ElementAdded(r2, true); } } } }
private static void UpdateEntitiesForConceptType(ConceptType conceptType, Predicate <ConceptType> conceptTypeFilter, Predicate <EntityType> entityFilter) { EntityType primaryEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(conceptType); if (primaryEntity != null && (entityFilter == null || !entityFilter(primaryEntity))) { UpdateEntityPresentationSize(primaryEntity); } Predicate <ConceptType> recurseConceptTypeFilter = delegate(ConceptType testConceptType) { return(testConceptType == conceptType || (conceptTypeFilter != null && conceptTypeFilter(testConceptType))); }; Predicate <EntityType> recurseEntityFilter = delegate(EntityType testEntity) { return(testEntity == primaryEntity); }; foreach (ConceptType relatingConceptType in ConceptTypeRelatesToConceptType.GetRelatingConceptTypeCollection(conceptType)) { if (relatingConceptType == conceptType || (conceptTypeFilter != null && conceptTypeFilter(relatingConceptType))) { continue; } UpdateEntitiesForConceptType( relatingConceptType, recurseConceptTypeFilter, recurseEntityFilter); } foreach (ConceptType assimilatedConceptType in ConceptTypeAssimilatesConceptType.GetAssimilatedConceptTypeCollection(conceptType)) { if (assimilatedConceptType == conceptType || (conceptTypeFilter != null && conceptTypeFilter(assimilatedConceptType))) { continue; } UpdateEntitiesForConceptType( assimilatedConceptType, recurseConceptTypeFilter, recurseEntityFilter); } }
private static void CreateAttributesAndBinaryRelationships(ConceptType conceptType, INotifyElementAdded notifyAdded, ref int associationCounter) { List <Attribute> attributesForConceptType = new List <Attribute>(); foreach (InformationType informationType in InformationType.GetLinksToInformationTypeFormatCollection(conceptType)) { attributesForConceptType.Add(CreateAttributeForInformationType(informationType, new Stack <ConceptTypeChild>())); } foreach (ConceptTypeRelatesToConceptType conceptTypeRelation in ConceptTypeRelatesToConceptType.GetLinksToRelatedConceptTypeCollection(conceptType)) { if (!CreateBinaryAssociation(conceptTypeRelation, conceptType, conceptTypeRelation.RelatedConceptType, notifyAdded, ref associationCounter)) { //if binary association was not created - let's create an attribute for it attributesForConceptType.AddRange(GetAttributesForConceptTypeRelation(conceptTypeRelation, new Stack <ConceptTypeChild>())); } } foreach (ConceptTypeAssimilatesConceptType conceptTypeAssimilation in ConceptTypeAssimilatesConceptType.GetLinksToAssimilatedConceptTypeCollection(conceptType)) { if (!conceptTypeAssimilation.RefersToSubtype) { CreateBinaryAssociation(conceptTypeAssimilation, conceptType, conceptTypeAssimilation.AssimilatedConceptType, notifyAdded, ref associationCounter); } } EntityType conceptTypeEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(conceptType); if (conceptTypeEntity != null) { conceptTypeEntity.AttributeCollection.AddRange(attributesForConceptType); if (notifyAdded != null) { foreach (Attribute attr in attributesForConceptType) { notifyAdded.ElementAdded(attr, true); } } } }
private static bool AllStepsMandatory(EntityType entity, IEnumerable <ConceptTypeChild> links) { bool allStepsMandatory = true; ConceptType lastTarget = null; bool firstPass = true; foreach (ConceptTypeChild child in links) { if (!child.IsMandatory) { ConceptTypeAssimilatesConceptType assimilation = child as ConceptTypeAssimilatesConceptType; if (assimilation != null) { // The IsMandatory property applies when stepping parent-to-target, However, stepping target-to-parent // is always considered mandatory. See if we're in this situation. if (firstPass) { lastTarget = EntityTypeIsPrimarilyForConceptType.GetConceptType(entity); } if (lastTarget != null && lastTarget == assimilation.Target) { lastTarget = assimilation.Parent; firstPass = false; continue; } } allStepsMandatory = false; break; } lastTarget = child.Target as ConceptType; firstPass = false; } return(allStepsMandatory); }
/// <summary> /// Verify that an abstraction model has an appropriate Barker ER model and bridge /// </summary> protected override void ProcessElement(AbstractionModel element, Store store, INotifyElementAdded notifyAdded) { BarkerErModel barkerModel = BarkerErModelIsForAbstractionModel.GetBarkerErModel(element); if (barkerModel == null) { // Create the initial Barker ER model and notify barkerModel = new BarkerErModel( store, new PropertyAssignment[] { new PropertyAssignment(BarkerErModel.NameDomainPropertyId, element.Name) }); new BarkerErModelIsForAbstractionModel(barkerModel, element); BarkerERModelGenerationSetting generationSetting = new BarkerERModelGenerationSetting(store, new PropertyAssignment( BarkerERModelGenerationSetting.CoreAlgorithmVersionDomainPropertyId, CurrentCoreAlgorithmVersion), new PropertyAssignment( BarkerERModelGenerationSetting.NameAlgorithmVersionDomainPropertyId, CurrentNameAlgorithmVersion)); new GenerationSettingTargetsBarkerERModel(generationSetting, barkerModel); new ORMCore.GenerationStateHasGenerationSetting(ORMCore.GenerationState.EnsureGenerationState(store), generationSetting); notifyAdded.ElementAdded(barkerModel, true); FullyGenerateBarkerERModel(barkerModel, element, notifyAdded); } else { BarkerERModelGenerationSetting generationSetting = GenerationSettingTargetsBarkerERModel.GetGenerationSetting(barkerModel); bool regenerateAll = generationSetting == null || generationSetting.CoreAlgorithmVersion != CurrentCoreAlgorithmVersion; bool regenerateNames = false; if (!regenerateAll) { foreach (EntityType barkerEntity in barkerModel.EntityTypeCollection) { if (null == EntityTypeIsPrimarilyForConceptType.GetLinkToConceptType(barkerEntity)) { regenerateAll = true; break; } // Theoretically we should also check that all attributes and uniqueness constraints // are pathed back to the abstraction model. However, this is far from a full validation, // and the scenario we're trying to cover is the abstraction model regenerating during // load and removing our bridge elements. The entity type check above is sufficient. } regenerateNames = !regenerateAll && generationSetting.NameAlgorithmVersion != CurrentNameAlgorithmVersion; generationSetting.NameAlgorithmVersion = CurrentNameAlgorithmVersion; } else { if (generationSetting == null) { generationSetting = new BarkerERModelGenerationSetting(store, new PropertyAssignment( BarkerERModelGenerationSetting.CoreAlgorithmVersionDomainPropertyId, CurrentCoreAlgorithmVersion), new PropertyAssignment( BarkerERModelGenerationSetting.NameAlgorithmVersionDomainPropertyId, CurrentNameAlgorithmVersion)); new GenerationSettingTargetsBarkerERModel(generationSetting, barkerModel); new ORMCore.GenerationStateHasGenerationSetting(ORMCore.GenerationState.EnsureGenerationState(store), generationSetting); } else { regenerateNames = generationSetting.NameAlgorithmVersion != CurrentNameAlgorithmVersion; generationSetting.CoreAlgorithmVersion = CurrentCoreAlgorithmVersion; generationSetting.NameAlgorithmVersion = CurrentNameAlgorithmVersion; } } if (regenerateAll) { barkerModel.BinaryAssociationCollection.Clear(); barkerModel.EntityTypeCollection.Clear(); barkerModel.ExclusiveArcCollection.Clear(); FullyGenerateBarkerERModel(barkerModel, element, notifyAdded); } else if (regenerateNames) { //NameGeneration.GenerateAllNames(barkerModel); } } }
/// <summary> /// for regular relationships /// </summary> /// <param name="relation"></param> /// <param name="source"></param> /// <param name="target"></param> /// <param name="notifyAdded"></param> /// <param name="associationCounter"></param> /// <returns></returns> private static bool CreateBinaryAssociation(ConceptTypeChild relation, ConceptType source, ConceptType target, INotifyElementAdded notifyAdded, ref int associationCounter) { if (BinaryAssociationHasConceptTypeChild.GetBinaryAssociation(relation).Count > 0) { //it has already been created return(true); } else if (EntityTypeIsPrimarilyForConceptType.GetEntityType(target) != null) { #region create association BinaryAssociation b = new BinaryAssociation(relation.Store, new PropertyAssignment[] { new PropertyAssignment(BinaryAssociation.NumberDomainPropertyId, associationCounter++) }); //new BinaryAssociationHasConceptTypeChild(b, relation); BinaryAssociationHasConceptTypeChild.GetConceptTypeChildPath(b).Add(relation); Role r1 = new Role(relation.Store, new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, source.Name) }); Role r2 = new Role(relation.Store, new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, target.Name) }); b.RoleCollection.Add(r1); b.RoleCollection.Add(r2); EntityType sourceEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(source); EntityType targetEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(target); sourceEntity.RoleCollection.Add(r1); targetEntity.RoleCollection.Add(r2); sourceEntity.BarkerErModel.BinaryAssociationCollection.Add(b); #endregion //determine whether roles are mandatory or optional List <ConceptTypeChild> links = new List <ConceptTypeChild>(1); links.Add(relation); r1.IsMandatory = AllStepsMandatory(targetEntity, links); if (relation is ConceptTypeAssimilatesConceptType) { r2.IsMandatory = AllStepsMandatory(sourceEntity, links); } #region determine whether roles are multivalued or not - and possibly rename ORMCore.ObjectType sourceObjectType = ConceptTypeIsForObjectType.GetObjectType(source); ORMCore.ObjectType targetObjectType = ConceptTypeIsForObjectType.GetObjectType(target); ORMCore.UniquenessConstraint uSource = null, uTarget = null; foreach (ORMCore.FactType factType in ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(relation)) { Debug.Assert(factType.RoleCollection.Count == 2, "Error when mapping to Barker ER; the fact type is not binary"); foreach (ORMCore.RoleBase r in factType.RoleCollection) { //need to use RoleBase because we might run into RoleProxy ORMCore.Role role = r.Role; foreach (ORMCore.ConstraintRoleSequence constraintRoleSequence in role.ConstraintRoleSequenceCollection) { ORMCore.UniquenessConstraint uninquenessConstraint = constraintRoleSequence as ORMCore.UniquenessConstraint; if (uninquenessConstraint != null && //check that it's a uniqueness constraint uninquenessConstraint.Modality == ORMCore.ConstraintModality.Alethic && //check it's alethic uninquenessConstraint.IsInternal) //check it's internal { if (role.RolePlayer == sourceObjectType) { uSource = uninquenessConstraint; } if (role.RolePlayer == targetObjectType) { uTarget = uninquenessConstraint; } } } } //name the roles properly //TODO this is a hack; proper name generation is yet to be implemented foreach (ORMCore.ReadingOrder order in factType.ReadingOrderCollection) { string text = order.ReadingText; int first = text.IndexOf('}') + 1; text = text.Substring(first, text.LastIndexOf('{') - first); text = text.Trim(); if (!string.IsNullOrEmpty(text) && order.RoleCollection != null && order.RoleCollection.Count > 0 && order.RoleCollection[0].Role != null) { ORMCore.ObjectType o = order.RoleCollection[0].Role.RolePlayer; if (o == sourceObjectType) { r1.PredicateText = text; } else if (o == targetObjectType) { r2.PredicateText = text; } } } } if (uSource != null && uSource == uTarget) { //it's many-to-many r1.IsMultiValued = true; r2.IsMultiValued = true; } else if (uSource == null || uTarget == null) { //it's one-to-many r1.IsMultiValued = uSource != null; r2.IsMultiValued = uTarget != null; } else if (uSource != null && uTarget != null) { //it's one-to-one r1.IsMultiValued = false; r2.IsMultiValued = false; } else { Debug.Fail("Found a fact type with no uniqueness constraints!"); } #endregion #region primary id? foreach (Uniqueness u in UniquenessIncludesConceptTypeChild.GetUniquenessCollection(relation)) { if (u.IsPreferred) { r1.IsPrimaryIdComponent = true; break; } } #endregion //notify elements added if (notifyAdded != null) { notifyAdded.ElementAdded(b, true); notifyAdded.ElementAdded(r1, true); notifyAdded.ElementAdded(r2, true); } return(true); } else { //should not create binary association in this case return(false); } }