예제 #1
0
        /// <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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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());
        }
예제 #4
0
        public void VerifyThatTheSpectTypeCanBeSet()
        {
            var relationGroupType = new RelationGroupType();
            var relationGroup     = new RelationGroup();

            relationGroup.SpecType = relationGroupType;

            Assert.AreEqual(relationGroupType, relationGroup.SpecType);
        }
예제 #5
0
        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);
        }
예제 #7
0
 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));
 }
예제 #8
0
        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"));
                }
            }
        }
예제 #10
0
        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"));
                }
            }
        }
예제 #11
0
        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);
        }
예제 #13
0
        /// <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);
        }
예제 #14
0
        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);
            }
        }
예제 #15
0
        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
            });
        }