/// <summary> /// Returns the <see cref="SpecRelation"/> representation of a <see cref="BinaryRelationship"/>-<see cref="BinaryRelationshipRule"/> combination /// </summary> /// <param name="relationship"> /// The <see cref="BinaryRelationship"/> /// </param> /// <param name="relationGroupType">The associated <see cref="RelationGroupType"/></param> /// <param name="source">The <see cref="SpecObject"/> source</param> /// <param name="target">The <see cref="SpecObject"/> target</param> /// <returns> /// The <see cref="SpecRelation"/> /// </returns> public RelationGroup ToReqIfRelationGroup(BinaryRelationship relationship, RelationGroupType relationGroupType, Specification source, Specification target) { if (relationship == null) { throw new ArgumentNullException("relationship"); } var relationGroup = new RelationGroup { Identifier = relationship.Iid.ToString(), LastChange = DateTime.UtcNow, LongName = relationship.UserFriendlyName }; relationGroup.Type = relationGroupType; this.SetCommonAttributeValues(relationGroup, relationship); foreach (var parameterValue in relationship.ParameterValue) { var attributeDef = relationGroupType.SpecAttributes.Single(x => x.DatatypeDefinition.Identifier == parameterValue.ParameterType.Iid.ToString()); var value = this.ToReqIfAttributeValue(parameterValue.ParameterType, attributeDef, parameterValue.Value, parameterValue.Scale); relationGroup.Values.Add(value); } relationGroup.SourceSpecification = source; relationGroup.TargetSpecification = target; return(relationGroup); }
public RelationGroup FindRelations( IEnumerable <IIndex> indexes, bool referring = true, bool referred = true) { RelationGroup relations = new RelationGroup(); foreach (IIndex index in indexes) { if (referring) { foreach (var relation in this.database.Tables.GetReferringRelations(index)) { if (!relations.Referring.Contains(relation)) { relations.Referring.Add(relation); } } } if (referred) { foreach (var relation in this.database.Tables.GetReferredRelations(index)) { if (!relations.Referred.Contains(relation)) { relations.Referred.Add(relation); } } } } return(relations); }
public IEnumerable <T> ExecuteDelete <T>( IExecutionPlan <IEnumerable <T> > plan, IExecutionContext context) where T : class { var helper = new ExecutionHelper(this.Database); var table = this.Database.Tables.FindTable <T>(); var cascadedTables = helper.GetCascadedTables(table); var allTables = cascadedTables.Concat(new[] { table }).ToArray(); // Find relations // Do not add referred relations! RelationGroup allRelations = helper.FindRelations(allTables.SelectMany(x => x.Indexes), referred: false); this.AcquireWriteLock(table, context); var storedEntities = this.Query(plan, table, context); this.AcquireWriteLock(cascadedTables, context); this.LockRelatedTables(allRelations, context, except: allTables); using (AtomicLogScope log = this.StartAtomicLogOperation(context)) { IDeletePrimitive primitive = new DeletePrimitive(this.Database, log); primitive.Delete(storedEntities); log.Complete(); } return(storedEntities.ToArray()); }
public void VerifyThatTheSpectTypeCanBeSet() { var relationGroupType = new RelationGroupType(); var relationGroup = new RelationGroup(); relationGroup.SpecType = relationGroupType; Assert.AreEqual(relationGroupType, relationGroup.SpecType); }
public void VerifyThatSettingAnIncorrectSpecTypeThrowsException() { var specificationType = new SpecificationType(); var relationGroup = new RelationGroup(); Assert.That(() => relationGroup.SpecType = specificationType, Throws.TypeOf <ArgumentException>() .With.Message.EqualTo("specType must of type RelationGroupType")); }
public void Verify_That_The_SpectType_Can_Be_Set() { var relationGroupType = new RelationGroupType(); var relationGroup = new RelationGroup(); relationGroup.SpecType = relationGroupType; Assert.AreEqual(relationGroupType, relationGroup.SpecType); }
public IEnumerable <ITable> GetRelatedTables( RelationGroup relations, params ITable[] except) { return (relations.Referring.Select(x => x.ForeignTable) .Concat(relations.Referred.Select(x => x.PrimaryTable)) .Distinct() .Except(except)); }
private void LockRelatedTables( RelationGroup relations, IExecutionContext context, params ITable[] except) { var helper = new ExecutionHelper(this.Database); ITable[] relatedTables = helper.GetRelatedTables(relations, except).ToArray(); this.LockRelatedTables(relatedTables, context); }
public void Verify_That_WriteXmlAsync_Throws_Exception_When_Type_Is_Null() { var cancellationTokenSource = new CancellationTokenSource(); var relationGroup = new RelationGroup(); // Type is not set using (var memoryStream = new MemoryStream()) { using (var writer = XmlWriter.Create(memoryStream, new XmlWriterSettings { Indent = true })) { Assert.That(async() => await relationGroup.WriteXmlAsync(writer, cancellationTokenSource.Token), Throws.TypeOf <SerializationException>() .With.Message.EqualTo("The Type property of RelationGroup : may not be null")); } } // Source specification is not set var relationGroupType = new RelationGroupType(); relationGroup.Type = relationGroupType; using (var memoryStream = new MemoryStream()) { using (var writer = XmlWriter.Create(memoryStream, new XmlWriterSettings { Indent = true })) { Assert.That(async() => await relationGroup.WriteXmlAsync(writer, cancellationTokenSource.Token), Throws.TypeOf <SerializationException>() .With.Message.EqualTo("The SourceSpecification property of RelationGroup : may not be null")); } } // target specification is not set var sourceSpecification = new Specification(); relationGroup.SourceSpecification = sourceSpecification; using (var memoryStream = new MemoryStream()) { using (var writer = XmlWriter.Create(memoryStream, new XmlWriterSettings { Indent = true })) { Assert.That(async() => await relationGroup.WriteXmlAsync(writer, cancellationTokenSource.Token), Throws.TypeOf <SerializationException>() .With.Message.EqualTo("The TargetSpecification property of RelationGroup : may not be null")); } } }
public void VerifyThatWriteXmlThrowsExceptionWhenTypeIsNull() { var relationGroup = new RelationGroup(); // Type is not set using (var fs = new FileStream("test.xml", FileMode.Create)) { using (var writer = XmlWriter.Create(fs, new XmlWriterSettings { Indent = true })) { Assert.That(() => relationGroup.WriteXml(writer), Throws.TypeOf <SerializationException>() .With.Message.EqualTo("The Type property of RelationGroup : may not be null")); } } // Source specification is not set var relationGroupType = new RelationGroupType(); relationGroup.Type = relationGroupType; using (var fs = new FileStream("test.xml", FileMode.Create)) { using (var writer = XmlWriter.Create(fs, new XmlWriterSettings { Indent = true })) { Assert.That(() => relationGroup.WriteXml(writer), Throws.TypeOf <SerializationException>() .With.Message.EqualTo("The SourceSpecification property of RelationGroup : may not be null")); } } // target specification is not set var sourceSpecification = new Specification(); relationGroup.SourceSpecification = sourceSpecification; using (var fs = new FileStream("test.xml", FileMode.Create)) { using (var writer = XmlWriter.Create(fs, new XmlWriterSettings { Indent = true })) { Assert.That(() => relationGroup.WriteXml(writer), Throws.TypeOf <SerializationException>() .With.Message.EqualTo("The TargetSpecification property of RelationGroup : may not be null")); } } }
public void Delete <T>(IList <T> storedEntities) where T : class { ExecutionHelper helper = new ExecutionHelper(this.database); ITable <T> table = this.database.Tables.FindTable <T>(); // Find relations // Do not add referred relations! RelationGroup relations = helper.FindRelations(table.Indexes, referred: false); // Find referring entities var referringEntities = helper.FindReferringEntities <T>(storedEntities, relations.Referring); // Delete invalid index records for (int i = 0; i < storedEntities.Count; i++) { T storedEntity = storedEntities[i]; foreach (IIndex <T> index in table.Indexes) { index.Delete(storedEntity); log.Log.WriteIndexDelete(index, storedEntity); } } var cascadedRelations = relations.Referring.Where(x => x.Options.CascadedDeletion); foreach (IRelationInternal index in cascadedRelations) { var entities = referringEntities[index]; if (entities.Count == 0) { continue; } index.CascadedDelete(entities, this); // At this point these entities should have been removed from the database // In order to avoid foreign key validation, clear the collection // // TODO: It might be better to do foreign key validation from the // other direction: check if anything refers storedEntities entities.Clear(); } // Validate the entities that are referring to the deleted entities helper.ValidateForeignKeys(relations.Referring, referringEntities); }
/// <summary> /// Creates a <see cref="RelationGroup"/> /// </summary> private void CreateRelationGroup() { var reqIfContent = this.reqIF.CoreContent.SingleOrDefault(); var relationGroupType = (RelationGroupType)reqIfContent.SpecTypes.SingleOrDefault(x => x.GetType() == typeof(RelationGroupType)); var relationGroup = new RelationGroup(); relationGroup.Identifier = "relationgroup-1"; relationGroup.LastChange = DateTime.Parse("2015-12-01"); relationGroup.LongName = "relationgroup 1"; relationGroup.Type = relationGroupType; var sourceSpecification = reqIfContent.Specifications.SingleOrDefault(x => x.Identifier == "specification-1"); var targetSpecification = reqIfContent.Specifications.SingleOrDefault(x => x.Identifier == "specification-2"); relationGroup.SourceSpecification = sourceSpecification; relationGroup.TargetSpecification = targetSpecification; reqIfContent.SpecRelationGroups.Add(relationGroup); }
/// <summary> /// Creates a <see cref="BinaryRelationship"/> from a <see cref="RelationGroup"/> /// </summary> /// <param name="relation">The <see cref="RelationGroup"/></param> /// <returns></returns> private BinaryRelationship CreateBinaryRelationship(RelationGroup relation) { var type = this.typeMap[relation.Type]; var relationship = new BinaryRelationship { Owner = this.Owner }; RequirementsSpecification source; RequirementsSpecification target; if (!this.specificationMap.TryGetValue(relation.SourceSpecification, out source) || !this.specificationMap.TryGetValue(relation.TargetSpecification, out target)) { throw new InvalidOperationException("The source or target cannot be null. Verify that the ReqIF input is valid."); } relationship.Source = source; relationship.Target = target; relationship.Category.AddRange(type.Categories); foreach (var value in relation.Values) { var attributeMap = type.AttributeDefinitionMap.SingleOrDefault(x => x.AttributeDefinition == value.AttributeDefinition); if (attributeMap == null || attributeMap.MapKind == AttributeDefinitionMapKind.NONE) { continue; } switch (attributeMap.MapKind) { case AttributeDefinitionMapKind.PARAMETER_VALUE: this.SetParameterValue(relationship, value); break; } } this.relationGroupMap.Add(relation, relationship); return(relationship); }
public void ExecuteInsert <T>(T entity, IExecutionContext context) where T : class { var helper = new ExecutionHelper(this.Database); var table = this.Database.Tables.FindTable <T>(); table.Contraints.Apply(entity, context); // Find referred relations // Do not add referring relations! RelationGroup relations = helper.FindRelations(table.Indexes, referring: false); // Acquire locks this.AcquireWriteLock(table, context); this.LockRelatedTables(relations, context, table); try { // Validate the inserted record helper.ValidateForeignKeys(relations.Referred, new[] { entity }); using (AtomicLogScope logScope = this.StartAtomicLogOperation(context)) { foreach (IIndex <T> index in table.Indexes) { index.Insert(entity); logScope.Log.WriteIndexInsert(index, entity); } logScope.Complete(); } } finally { this.ReleaseWriteLock(table, context); } }
public IEnumerable <T> ExecuteUpdater <T>( IExecutionPlan <IEnumerable <T> > plan, IUpdater <T> updater, IExecutionContext context) where T : class { var helper = new ExecutionHelper(this.Database); var table = this.Database.Tables.FindTable <T>(); var cloner = EntityPropertyCloner <T> .Instance; // Determine which indexes are affected by the change // If the key of an index containes a changed property, it is affected IList <IIndex <T> > affectedIndexes = helper.FindAffectedIndexes(table, updater.Changes); // Find relations // Add both referring and referred relations! RelationGroup relations = helper.FindRelations(affectedIndexes); this.AcquireWriteLock(table, context); var storedEntities = Query(plan, table, context); // Lock related tables (based on found relations) this.LockRelatedTables(relations, context, table); // Find the entities referring the entities that are about to be updated var referringEntities = helper.FindReferringEntities(storedEntities, relations.Referring); using (AtomicLogScope logScope = this.StartAtomicLogOperation(context)) { // Delete invalid index records (keys are invalid) for (int i = 0; i < storedEntities.Count; i++) { T storedEntity = storedEntities[i]; foreach (IIndex <T> index in affectedIndexes) { index.Delete(storedEntity); logScope.Log.WriteIndexDelete(index, storedEntity); } } // Modify entity properties for (int i = 0; i < storedEntities.Count; i++) { T storedEntity = storedEntities[i]; // Create backup T backup = Activator.CreateInstance <T>(); cloner.Clone(storedEntity, backup); T newEntity = updater.Update(storedEntity); // Apply contraints on the entity table.Contraints.Apply(newEntity, context); // Update entity cloner.Clone(newEntity, storedEntity); logScope.Log.WriteEntityUpdate(cloner, storedEntity, backup); } // Insert to indexes the entities were removed from for (int i = 0; i < storedEntities.Count; i++) { T storedEntity = storedEntities[i]; foreach (IIndex <T> index in affectedIndexes) { index.Insert(storedEntity); logScope.Log.WriteIndexInsert(index, storedEntity); } } // Validate the updated entities helper.ValidateForeignKeys(relations.Referred, storedEntities); // Validate the entities that were referring to the old version of entities helper.ValidateForeignKeys(relations.Referring, referringEntities); logScope.Complete(); } return(storedEntities); }
private void SetupReqIf() { this.reqIf = new ReqIF(); this.reqIf.Lang = "en"; this.corecontent = new ReqIFContent(); this.reqIf.CoreContent = this.corecontent; this.stringDatadef = new DatatypeDefinitionString(); this.specificationtype = new SpecificationType(); this.specobjecttype = new SpecObjectType(); this.specrelationtype = new SpecRelationType(); this.relationgrouptype = new RelationGroupType(); this.specAttribute = new AttributeDefinitionString() { DatatypeDefinition = this.stringDatadef }; this.reqAttribute = new AttributeDefinitionString() { DatatypeDefinition = this.stringDatadef }; this.specRelationAttribute = new AttributeDefinitionString() { DatatypeDefinition = this.stringDatadef }; this.relationgroupAttribute = new AttributeDefinitionString() { DatatypeDefinition = this.stringDatadef }; this.specificationtype.SpecAttributes.Add(this.specAttribute); this.specobjecttype.SpecAttributes.Add(this.reqAttribute); this.specrelationtype.SpecAttributes.Add(this.specRelationAttribute); this.relationgrouptype.SpecAttributes.Add(this.relationgroupAttribute); this.specification1 = new Specification() { Type = this.specificationtype }; this.specification2 = new Specification() { Type = this.specificationtype }; this.specobject1 = new SpecObject() { Type = this.specobjecttype }; this.specobject2 = new SpecObject() { Type = this.specobjecttype }; this.specrelation = new SpecRelation() { Type = this.specrelationtype, Source = this.specobject1, Target = this.specobject2 }; this.relationgroup = new RelationGroup() { Type = this.relationgrouptype, SourceSpecification = this.specification1, TargetSpecification = this.specification2 }; this.specValue1 = new AttributeValueString() { AttributeDefinition = this.specAttribute, TheValue = "spec1" }; this.specValue2 = new AttributeValueString() { AttributeDefinition = this.specAttribute, TheValue = "spec2" }; this.objectValue1 = new AttributeValueString() { AttributeDefinition = this.reqAttribute, TheValue = "req1" }; this.objectValue2 = new AttributeValueString() { AttributeDefinition = this.reqAttribute, TheValue = "req2" }; this.relationgroupValue = new AttributeValueString() { AttributeDefinition = this.relationgroupAttribute, TheValue = "group" }; this.specrelationValue = new AttributeValueString() { AttributeDefinition = this.specRelationAttribute, TheValue = "specrelation" }; this.specification1.Values.Add(this.specValue1); this.specification2.Values.Add(this.specValue2); this.specobject1.Values.Add(this.objectValue1); this.specobject2.Values.Add(this.objectValue2); this.specrelation.Values.Add(this.specrelationValue); this.relationgroup.Values.Add(this.relationgroupValue); this.corecontent.DataTypes.Add(this.stringDatadef); this.corecontent.SpecTypes.AddRange(new SpecType[] { this.specobjecttype, this.specificationtype, this.specrelationtype, this.relationgrouptype }); this.corecontent.SpecObjects.AddRange(new SpecObject[] { this.specobject1, this.specobject2 }); this.corecontent.Specifications.AddRange(new Specification[] { this.specification1, this.specification2 }); this.corecontent.SpecRelations.Add(this.specrelation); this.corecontent.SpecRelationGroups.Add(this.relationgroup); this.specification1.Children.Add(new SpecHierarchy() { Object = this.specobject1 }); this.specification2.Children.Add(new SpecHierarchy() { Object = this.specobject2 }); }