Beispiel #1
0
        /// <summary>
        /// Verify the <see cref="RequirementsGroup"/> against this <see cref="ParameterizedCategoryRule"/>
        /// </summary>
        /// <param name="requirementsContainer">The <see cref="RequirementsContainer"/> container to check</param>
        /// <param name="violations">The collection of <see cref="RuleViolation"/> to update</param>
        private void VerifyGroup(RequirementsContainer requirementsContainer, List <RuleViolation> violations)
        {
            foreach (var group in requirementsContainer.Group)
            {
                if (group.IsMemberOfCategory(this.Category))
                {
                    var missingParameterTypes = new List <ParameterType>();
                    foreach (var parameterType in this.ParameterType)
                    {
                        var parameter = group.ParameterValue.SingleOrDefault(p => p.ParameterType == parameterType);
                        if (parameter == null)
                        {
                            missingParameterTypes.Add(parameterType);
                        }
                    }

                    if (missingParameterTypes.Count > 0)
                    {
                        var iids       = string.Join(",", missingParameterTypes.Select(x => x.Iid));
                        var shortnames = string.Join(",", missingParameterTypes.Select(x => x.ShortName));

                        var violation = new RuleViolation(Guid.NewGuid(), this.Cache, this.IDalUri);
                        violation.RuleViolatedClassKind.Add(group.ClassKind);
                        violation.ViolatingThing.Add(group.Iid);
                        violation.Description = $"The RequirementsGroup {@group.Name} does not contain parameters that reference the following parameter types {iids} with shortnames: {shortnames}";

                        violations.Add(violation);
                    }
                }

                this.VerifyGroup(group, violations);
            }
        }
        /// <summary>
        /// Query the <see cref="RequirementsContainerParameterValue"/> if it exists or create a new one
        /// </summary>
        /// <param name="reqContainer">The <see cref="RequirementsContainer"/> container</param>
        /// <param name="simpleParameterValue">The queried <see cref="RequirementsContainerParameterValue"/></param>
        /// <returns>A value indicating if the <see cref="RequirementsContainerParameterValue"/> existed</returns>
        protected bool TryQueryOrderParameterOrCreate(RequirementsContainer reqContainer, out RequirementsContainerParameterValue simpleParameterValue)
        {
            var parameterValue = this.QueryOrderParameter(reqContainer);

            if (parameterValue != null)
            {
                simpleParameterValue = parameterValue;
                return(true);
            }

            var iteration = reqContainer.GetContainerOfType <Iteration>();
            Tuple <DomainOfExpertise, Participant> domainTuple;

            if (!this.session.OpenIterations.TryGetValue(iteration, out domainTuple) || domainTuple.Item1 == null)
            {
                throw new InvalidOperationException("The domain is null.");
            }

            simpleParameterValue = new RequirementsContainerParameterValue(Guid.NewGuid(), null, null)
            {
                ParameterType = this.reqOrderParameterType,
                Value         = new ValueArray <string>(new[] { int.MaxValue.ToString() }),
            };

            return(false);
        }
Beispiel #3
0
 /// <summary>
 /// Populate the <paramref name="thingsToCheck"/>
 /// </summary>
 /// <param name="reqContainer">The <see cref="RequirementsContainer"/></param>
 /// <param name="thingsToCheck">The collection of <see cref="Guid"/> to populate</param>
 private void AddThingsToVerify(RequirementsContainer reqContainer, List <Guid> thingsToCheck)
 {
     foreach (var group in reqContainer.Group)
     {
         thingsToCheck.Add(group.Iid);
         this.AddThingsToVerify(group, thingsToCheck);
     }
 }
Beispiel #4
0
        /// <summary>
        /// Checks the validity of the <see cref="RequirementsContainer"/> ShortName property
        /// </summary>
        /// <param name="requirementsContainer">
        /// the subject <see cref="RequirementsContainer"/>
        /// </param>
        /// <param name="rule">
        /// the corresponding <see cref="IRule"/>
        /// </param>
        /// <returns>
        /// A instance of <see cref="RuleCheckResult"/> when the rule is violated, or null when all is good
        /// </returns>
        private RuleCheckResult CheckShortNameValidityOfRequirementsContainer(RequirementsContainer requirementsContainer, IRule rule)
        {
            if (!Regex.IsMatch(requirementsContainer.ShortName, "^[a-zA-Z][a-zA-Z0-9_]*$"))
            {
                return(new RuleCheckResult(requirementsContainer, rule.Id, $"The ShortName: {requirementsContainer.ShortName} is invalid. The ShortName must start with a letter and not contain any spaces or non alphanumeric characters.", rule.Severity));
            }

            return(null);
        }
        /// <summary>
        /// Query the <see cref="SimpleParameterValue"/> representing the order
        /// </summary>
        /// <param name="reqContainer">The <see cref="RequirementsContainer"/> container</param>
        /// <returns>The <see cref="SimpleParameterValue"/></returns>
        protected RequirementsContainerParameterValue QueryOrderParameter(RequirementsContainer reqContainer)
        {
            if (RequirementsModule.PluginSettings?.OrderSettings == null)
            {
                throw new InvalidOperationException("No setting for the order-parameter");
            }

            return(reqContainer.ParameterValue.FirstOrDefault(x => x.ParameterType.Iid == RequirementsModule.PluginSettings.OrderSettings.ParameterType));
        }
Beispiel #6
0
        /// <summary>
        /// Computes the bread crumb of a <see cref="RequirementsContainer"/>
        /// </summary>
        /// <param name="requirementsContainer">
        /// The <see cref="RequirementsContainer"/> of which the bread crumb is to be computed
        /// </param>
        /// <returns>
        /// RequirementsSpecification: S:ShortName
        /// RequirementsGroup: RG:ShortName
        /// </returns>
        public static string BreadCrumb(this RequirementsContainer requirementsContainer)
        {
            var container = requirementsContainer.Container as RequirementsContainer;

            if (container != null)
            {
                return(string.Format("{0}.{1}", container.BreadCrumb(), requirementsContainer.BreadCrumbPart()));
            }

            return(BreadCrumbPart(requirementsContainer));
        }
Beispiel #7
0
        /// <summary>
        /// Computes the Bread Crumb Part of a <see cref="RequirementsContainer"/>
        /// </summary>
        /// <param name="requirementsContainer">
        /// The <see cref="RequirementsContainer"/> of which the part is computed
        /// </param>
        /// <returns>
        /// RequirementsSpecification: S:ShortName
        /// RequirementsGroup: RG:ShortName
        /// </returns>
        public static string BreadCrumbPart(this RequirementsContainer requirementsContainer)
        {
            var requirementsSpecification = requirementsContainer as RequirementsSpecification;

            if (requirementsSpecification != null)
            {
                return(string.Format("S:{0}", requirementsSpecification.ShortName));
            }

            var requirementsGroup = requirementsContainer as RequirementsGroup;

            if (requirementsGroup != null)
            {
                return(string.Format("RG:{0}", requirementsGroup.ShortName));
            }

            throw new InvalidOperationException(string.Format("{0} is not supported by the BreadCrumbComputer", requirementsContainer.GetType()));
        }
Beispiel #8
0
        /// <summary>
        /// Add a <see cref="RequirementsContainerParameterValue"/> to a <see cref="RequirementsContainer"/>
        /// </summary>
        /// <param name="requirementContainer">The <see cref="RequirementsContainer"/></param>
        /// <param name="value">The <see cref="AttributeValue"/></param>
        private void SetParameterValue(RequirementsContainer requirementContainer, AttributeValue value)
        {
            if (this.datatypeDefMap[value.AttributeDefinition.DatatypeDefinition].ParameterType == null)
            {
                throw new InvalidOperationException("The datatype-definition of an AttributeValue that is mapped to a Parameter-Value shall be mapped to a ParameterType.");
            }

            var theValue   = this.GetAttributeValue(value);
            var valueArray = new string[] { theValue };

            // TODO get mapped scale
            var simpleParameter = new RequirementsContainerParameterValue
            {
                ParameterType = this.datatypeDefMap[value.AttributeDefinition.DatatypeDefinition].ParameterType
            };

            simpleParameter.Value = new ValueArray <string>(valueArray);
            requirementContainer.ParameterValue.Add(simpleParameter);
        }
Beispiel #9
0
        /// <summary>
        /// Change the container of the <paramref name="reqContainerToInsert"/> to insert
        /// </summary>
        /// <param name="transaction">The current transaction</param>
        /// <param name="reqContainerToInsert">The <see cref="RequirementsContainer"/> to insert</param>
        /// <param name="referenceGroup">The <see cref="RequirementsContainer"/> to insert before or after</param>
        protected override void ChangeContainer(ThingTransaction transaction, RequirementsContainer reqContainerToInsert, RequirementsContainer referenceGroup)
        {
            // create a clone if there is none
            var reqToInsertClone = (RequirementsGroup)transaction.UpdatedThing.SingleOrDefault(x => x.Key.Iid == reqContainerToInsert.Iid).Value;

            if (reqToInsertClone == null)
            {
                reqToInsertClone = (RequirementsGroup)reqContainerToInsert.Clone(false);
                transaction.CreateOrUpdate(reqToInsertClone);
            }

            // change container if necessary
            if (reqContainerToInsert.Container != referenceGroup.Container)
            {
                var reqContainerClone = (RequirementsContainer)referenceGroup.Container.Clone(false);

                reqContainerClone.Group.Add(reqToInsertClone);
                transaction.CreateOrUpdate(reqContainerClone);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Create 10-25 <see cref="Thing"/>s from the <see cref="SpecHierarchy"/>
        /// </summary>
        /// <param name="specHierarchy">The <see cref="SpecHierarchy"/></param>
        /// <param name="reqContainer">The <see cref="RequirementsContainer"/> representing the current level of requirement</param>
        private void ComputeRequirementFromSpecHierarchy(SpecHierarchy specHierarchy, RequirementsContainer reqContainer)
        {
            // create a group if the specHierarchy has children
            if (specHierarchy.Children.Any())
            {
                var group = this.CreateRequirementGroup(specHierarchy.Object);
                reqContainer.Group.Add(group);
                foreach (var hierarchy in specHierarchy.Children)
                {
                    this.ComputeRequirementFromSpecHierarchy(hierarchy, group);
                }
            }

            SpecTypeMap specTypeMapping;

            if (!this.typeMap.TryGetValue(specHierarchy.Object.Type, out specTypeMapping))
            {
                // The instance of this type shall not be generated
                return;
            }

            var specObjectTypeMap = (SpecObjectTypeMap)specTypeMapping;

            if (!specObjectTypeMap.IsRequirement)
            {
                var group = this.CreateRequirementGroup(specHierarchy.Object);
                reqContainer.Group.Add(group);
                return;
            }

            var requirement = this.CreateRequirement(specHierarchy.Object);

            if (requirement != null)
            {
                var group = reqContainer as RequirementsGroup;
                if (group != null)
                {
                    requirement.Group = group;
                }

                RequirementsSpecification container = null;
                var specification = reqContainer as RequirementsSpecification;
                container = specification ?? reqContainer.GetContainerOfType <RequirementsSpecification>();

                if (container == null)
                {
                    throw new InvalidOperationException("The RequirementsSpecication container is null.");
                }

                container.Requirement.Add(requirement);
            }
        }
Beispiel #11
0
 /// <summary>
 /// Change the container of the <paramref name="reqContainerToInsert"/> to insert
 /// </summary>
 /// <param name="transaction">The current transaction</param>
 /// <param name="reqContainerToInsert">The <see cref="RequirementsContainer"/> to insert</param>
 /// <param name="referenceGroup">The <see cref="RequirementsContainer"/> to insert before or after</param>
 protected override void ChangeContainer(ThingTransaction transaction, RequirementsContainer reqContainerToInsert, RequirementsContainer referenceGroup)
 {
     // do nothing - Specification cannot have their container changed
 }
Beispiel #12
0
        /// <summary>
        /// Change the <see cref="IReadOnlyList{T}"/> within the current context
        /// </summary>
        /// <param name="reqContainerToInsert">The <see cref="RequirementsContainer"/> to insert</param>
        /// <param name="referenceGroup">The <see cref="RequirementsContainer"/> to insert before or after</param>
        protected override IReadOnlyList <RequirementsContainer> QueryAllContextReqContainer(RequirementsContainer reqContainerToInsert, RequirementsContainer referenceGroup)
        {
            var iteration = (Iteration)referenceGroup.Container;

            return(iteration.RequirementsSpecification);
        }
Beispiel #13
0
        /// <summary>
        /// Change the <see cref="IReadOnlyList{T}"/> within the current context
        /// </summary>
        /// <param name="reqContainerToInsert">The <see cref="RequirementsContainer"/> to insert</param>
        /// <param name="referenceGroup">The <see cref="RequirementsContainer"/> to insert before or after</param>
        protected override IReadOnlyList <RequirementsContainer> QueryAllContextReqContainer(RequirementsContainer reqContainerToInsert, RequirementsContainer referenceGroup)
        {
            var reqContainer = (RequirementsContainer)referenceGroup.Container;

            var allGroupInContext = reqContainer.Group.Where(x => x.Iid != reqContainerToInsert.Iid).ToList();

            allGroupInContext.Add((RequirementsGroup)reqContainerToInsert);

            return(allGroupInContext);
        }
        /// <summary>
        /// Creates and returns a <see cref="ThingTransaction"/> that contains required operations to insert <paramref name="groupToInsert"/> before <paramref name="referenceGroup"/>
        /// </summary>
        /// <param name="groupToInsert">The <see cref="T"/> to insert</param>
        /// <param name="referenceGroup">The <see cref="T"/> that comes right after <paramref name="groupToInsert"/></param>
        /// <param name="insertKind">The <see cref="InsertKind"/></param>
        /// <returns>The <see cref="ThingTransaction"/></returns>
        public ThingTransaction Insert(RequirementsContainer groupToInsert, RequirementsContainer referenceGroup, InsertKind insertKind)
        {
            var transaction       = new ThingTransaction(TransactionContextResolver.ResolveContext(groupToInsert));
            var allGroupInContext = this.QueryAllContextReqContainer(groupToInsert, referenceGroup);

            // contains all new or clone of SimpleParameterValue
            var paramValuesClone      = new Dictionary <Guid, RequirementsContainerParameterValue>();
            var unorderedReqContainer = new List <RequirementsContainer>();

            // put all ParameterValueSet in transaction as update if existing, as created otherwise
            foreach (var group in allGroupInContext)
            {
                // Create SimpleParameterValue if missing
                RequirementsContainerParameterValue orderValue;
                if (!this.TryQueryOrderParameterOrCreate(group, out orderValue) && this.session.PermissionService.CanWrite(ClassKind.RequirementsContainerParameterValue, group))
                {
                    var cloneReq = group.Clone(false);
                    cloneReq.ParameterValue.Add(orderValue);
                    transaction.CreateOrUpdate(cloneReq);
                    transaction.CreateOrUpdate(orderValue);
                    paramValuesClone.Add(group.Iid, orderValue);

                    // keep tab on unordered req to put order on their shortname
                    unorderedReqContainer.Add(group);
                }
                else if (this.session.PermissionService.CanWrite(orderValue))
                {
                    var cloneValue = orderValue.Clone(false);
                    if (group.Iid == groupToInsert.Iid)
                    {
                        // reset current value to max
                        cloneValue.Value = new ValueArray <string>(new[] { int.MaxValue.ToString() });
                    }

                    transaction.CreateOrUpdate(cloneValue);
                    paramValuesClone.Add(group.Iid, cloneValue);
                }
            }

            // potentionally change container if they are different and update the container
            this.ChangeContainer(transaction, groupToInsert, referenceGroup);

            // keys
            unorderedReqContainer = unorderedReqContainer.OrderBy(x => x.ShortName).ToList();
            var unorderedReqId = unorderedReqContainer.Select(x => x.Iid).ToList();

            var orderedParamClone = paramValuesClone.Where(x => !unorderedReqId.Contains(x.Key)).OrderBy(x => this.getOrderKey(x.Value)).ToList();

            orderedParamClone.AddRange(paramValuesClone.Where(x => unorderedReqId.Contains(x.Key)).OrderBy(x => unorderedReqId.IndexOf(x.Key)));

            paramValuesClone = orderedParamClone.ToDictionary(x => x.Key, x => x.Value);
            var reqOrderedUuid = paramValuesClone.Where(x => x.Key != groupToInsert.Iid).OrderBy(x => this.getOrderKey(x.Value)).Select(x => x.Key).ToList();

            var indexOfRefInsertReq = reqOrderedUuid.IndexOf(referenceGroup.Iid);
            var endReqIdInterval    = insertKind == InsertKind.InsertBefore
                ? indexOfRefInsertReq > 0 ? (Guid?)reqOrderedUuid[indexOfRefInsertReq - 1] : null
                : indexOfRefInsertReq < reqOrderedUuid.Count - 1
                    ? (Guid?)reqOrderedUuid[indexOfRefInsertReq + 1]
                    : null;

            var upperPair = insertKind == InsertKind.InsertBefore ? paramValuesClone.First(x => x.Key == referenceGroup.Iid) : endReqIdInterval.HasValue ? paramValuesClone.First(x => x.Key == endReqIdInterval) : default(KeyValuePair <Guid, RequirementsContainerParameterValue>);
            var lowerPair = insertKind == InsertKind.InsertBefore ? endReqIdInterval.HasValue ? paramValuesClone.First(x => x.Key == endReqIdInterval) : default(KeyValuePair <Guid, RequirementsContainerParameterValue>) : paramValuesClone.First(x => x.Key == referenceGroup.Iid);

            var upperKey = upperPair.Value != null?this.getOrderKey(upperPair.Value) : int.MaxValue;

            var lowerKey = lowerPair.Value != null?this.getOrderKey(lowerPair.Value) : int.MinValue;

            // either just update key of the dropped requirement or recompute all keys
            var insertKey = this.ComputeOrderKey(lowerKey, upperKey, paramValuesClone.Values.Select(this.getOrderKey).ToList(), false);

            if (insertKey.HasValue)
            {
                paramValuesClone[groupToInsert.Iid].Value = new ValueArray <string>(new[] { insertKey.ToString() });
            }
            else
            {
                // recompute all keys in ascending order
                var lower = 0;

                if (unorderedReqContainer.Any(x => !this.session.PermissionService.CanWrite(ClassKind.RequirementsContainerParameterValue, x)))
                {
                    // if no permission to update everything, just update value with min or max depending on the kind of insert
                    insertKey = this.ComputeOrderKey(lowerKey, upperKey, paramValuesClone.Values.Select(this.getOrderKey).ToList(), true);
                    paramValuesClone[groupToInsert.Iid].Value = new ValueArray <string>(new[] { insertKey.ToString() });
                }
                else
                {
                    // have permission to update all keys, so do so
                    foreach (var simpleParameterValue in paramValuesClone)
                    {
                        if (simpleParameterValue.Key == groupToInsert.Iid)
                        {
                            continue;
                        }

                        var key = this.ComputeOrderKey(lower, Int32.MaxValue, new List <int>(), true);
                        if (simpleParameterValue.Key == referenceGroup.Iid && insertKind == InsertKind.InsertBefore)
                        {
                            var reqValueToInsert = paramValuesClone.First(x => x.Key == groupToInsert.Iid);
                            reqValueToInsert.Value.Value = new ValueArray <string>(new[] { key.ToString() });
                            lower = key.Value;
                            key   = this.ComputeOrderKey(lower, Int32.MaxValue, new List <int>(), true);
                            simpleParameterValue.Value.Value = new ValueArray <string>(new[] { key.ToString() });
                            lower = key.Value;
                        }
                        else if (simpleParameterValue.Key == referenceGroup.Iid && insertKind == InsertKind.InsertAfter)
                        {
                            simpleParameterValue.Value.Value = new ValueArray <string>(new[] { key.ToString() });
                            lower = key.Value;

                            key = this.ComputeOrderKey(lower, Int32.MaxValue, new List <int>(), true);
                            var reqValueToInsert = paramValuesClone.First(x => x.Key == groupToInsert.Iid);
                            reqValueToInsert.Value.Value = new ValueArray <string>(new[] { key.ToString() });
                            lower = key.Value;
                        }
                        else
                        {
                            simpleParameterValue.Value.Value = new ValueArray <string>(new[] { key.ToString() });
                            lower = key.Value;
                        }
                    }
                }
            }

            return(transaction);
        }
 /// <summary>
 /// Change the <see cref="IReadOnlyList{T}"/> within the current context
 /// </summary>
 /// <param name="reqContainerToInsert">The <see cref="RequirementsContainer"/> to insert</param>
 /// <param name="referenceGroup">The <see cref="RequirementsContainer"/> to insert before or after</param>
 protected abstract IReadOnlyList <RequirementsContainer> QueryAllContextReqContainer(RequirementsContainer reqContainerToInsert, RequirementsContainer referenceGroup);
 /// <summary>
 /// Change the container of the <paramref name="reqContainerToInsert"/> to insert
 /// </summary>
 /// <param name="transaction">The current transaction</param>
 /// <param name="reqContainerToInsert">The <see cref="RequirementsContainer"/> to insert</param>
 /// <param name="referenceGroup">The <see cref="RequirementsContainer"/> to insert before or after</param>
 protected abstract void ChangeContainer(ThingTransaction transaction, RequirementsContainer reqContainerToInsert, RequirementsContainer referenceGroup);