/// <summary> /// Initializes a new instance of the <see cref="CategoryRowViewModel"/> class. /// </summary> /// <param name="category"> /// The <see cref="Category"/> that is represented by the current row-view-model /// </param> /// <param name="categorizableThing"> /// The <see cref="CategoryRowViewModel"/> that is a member of subject the <see cref="Category"/>. /// </param> public CategoryRowViewModel(Category category, ICategorizableThing categorizableThing) { this.Category = category; this.SuperCategories = (category.SuperCategory.Count == 0) ? string.Empty : string.Join(", ", category.SuperCategory.Select(x => x.ShortName)); this.ContainerRdl = category.Container is ReferenceDataLibrary container ? container.ShortName : string.Empty; this.Level = categorizableThing is ElementDefinition ? "ED" : "EU"; }
/// <summary> /// Queries the <see cref="ICategorizableThing"/> and checks whether it is a member of the /// supplied <see cref="Category"/>, this includes membership of the sub <see cref="Category"/> instances /// of the provided <see cref="Category"/> /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> instance that is being queried. /// </param> /// <param name="category"> /// The <see cref="Category"/> that the <see cref="ICategorizableThing"/> may be a member of. /// </param> /// <param name="requiredRdls"> /// An <see cref="IEnumerable{ReferenceDataLibrary}"/> that holds all <see cref="ReferenceDataLibrary"/>s /// where derived <see cref="Category"/>s if <paramref name="category"/> can be found. /// </param> /// <returns> /// returns true if the <see cref="ICategorizableThing"/> is a member of the <paramref name="category"/>, including it's /// sub <see cref="Category"/> instances. Returns false if the <see cref="ICategorizableThing"/> is not a member /// of the <paramref name="category"/> nor any of it's sub <see cref="Category"/> instances. /// </returns> public static bool IsMemberOfCategory(this ICategorizableThing categorizableThing, Category category, IEnumerable <ReferenceDataLibrary> requiredRdls) { var categoriesinRequiredRdls = requiredRdls.SelectMany(x => x.DefinedCategory).ToList(); var categoriesToCheck = category.AllDerivedCategories(categoriesinRequiredRdls).ToList(); return(IsMemberOfCategoryImplementation(categorizableThing, category, categoriesToCheck)); }
/// <summary> /// Queries the <see cref="ICategorizableThing"/> and checks whether it is a member of the /// supplied <see cref="Category"/>, this includes membership of the sub <see cref="Category"/> instances /// of the provided <see cref="Category"/> /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> instance that is being queried. /// </param> /// <param name="category"> /// The <see cref="Category"/> that the <see cref="ICategorizableThing"/> may be a member of. /// </param> /// <param name="allDerivedCategories"> /// A <see cref="IEnumerable{Category}"/> that contains all <see cref="Category"/>s that are derived from <paramref name="category"/>. /// </param> /// <returns> /// returns true if the <see cref="ICategorizableThing"/> is a member of the <paramref name="category"/>, including it's /// sub <see cref="Category"/> instances. Returns false if the <see cref="ICategorizableThing"/> is not a member /// of the <paramref name="category"/> nor any of it's sub <see cref="Category"/> instances. /// </returns> private static bool IsMemberOfCategoryImplementation(this ICategorizableThing categorizableThing, Category category, IEnumerable <Category> allDerivedCategories) { var categoriesToCheck = allDerivedCategories.ToList(); categoriesToCheck.Add(category); var memberOfCategories = categorizableThing.GetAllCategories(); return(memberOfCategories.Any(memberOfCategory => categoriesToCheck.Contains(memberOfCategory))); }
/// <summary> /// Checks if the <see cref="ICategorizableThing" /> has any categories that fall under the filter criteria /// </summary> /// <param name="thing">The <see cref="ICategorizableThing" /> to check</param> /// <param name="sourceConfiguration">The <see cref="SourceConfigurationViewModel" /> that defines the parameters.</param> /// <returns>True if the criteria is met.</returns> public static bool IsCategoryApplicableToConfiguration(ICategorizableThing thing, SourceConfigurationViewModel sourceConfiguration) { var thingCategories = new List <Category>(thing.Category); // if the thing is ElementUsage, add the ElementDefinition categories if (thing is ElementUsage usage) { thingCategories.AddRange(usage.ElementDefinition.Category); } switch (sourceConfiguration.SelectedBooleanOperatorKind) { case CategoryBooleanOperatorKind.OR: // if subcategories should be selected, expand the list var allCategories = new List <Category>(sourceConfiguration.SelectedCategories); if (sourceConfiguration.IncludeSubcategories) { foreach (var category in sourceConfiguration.SelectedCategories) { allCategories.AddRange(category.AllDerivedCategories()); } } return(thingCategories.Intersect(allCategories).Any()); case CategoryBooleanOperatorKind.AND: var categoryLists = new List <bool>(); foreach (var category in sourceConfiguration.SelectedCategories) { var categoryGroup = new List <Category> { category }; if (sourceConfiguration.IncludeSubcategories) { categoryGroup.AddRange(category.AllDerivedCategories()); } categoryLists.Add(thingCategories.Intersect(categoryGroup).Any()); } return(categoryLists.All(x => x)); } return(false); }
/// <summary> /// Queries all the categories and super categories from the categories of an <see cref="ICategorizableThing"/> /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> that is to be queried for all its categories and its super categories. /// </param> /// <param name="removeDuplicates"> /// a value indicating whether the duplicates should be reoved or not. /// </param> /// <returns> /// an <see cref="IEnumerable{Category}"/> that contains all the categories, duplicates are removed. /// </returns> /// <remarks> /// If the <paramref name="categorizableThing"/> is an <see cref="ElementUsage"/> the returned <see cref="Category"/> instances /// include those of the referenced <see cref="ElementDefinition"/>. /// </remarks> public static IEnumerable <Category> GetAllCategories(this ICategorizableThing categorizableThing, bool removeDuplicates = true) { var allCategories = new List <Category>(); var elementUsage = categorizableThing as ElementUsage; if (elementUsage != null) { var elementDefinition = elementUsage.ElementDefinition; if (elementDefinition != null) { allCategories.AddRange(elementDefinition.Category); } } allCategories.AddRange(categorizableThing.Category); var result = new List <Category>(); foreach (var category in allCategories) { foreach (var c in category.AllSuperCategories()) { result.Add(c); } result.Add(category); } if (removeDuplicates) { return(result.Distinct()); } else { return(result); } }
/// <summary> /// Determines whether the provided <see cref="Category"/> is in the chain of <see cref="ReferenceDataLibrary"/> /// of the <see cref="ICategorizableThing"/> /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> for which is being determined whether it may be categorized using the provided <see cref="Category"/> /// </param> /// <param name="category"> /// The <see cref="Category"/> that may or may not be in the chain-of-rdls of the <see cref="ICategorizableThing"/> /// </param> /// <returns> /// returns true when the <see cref="Category"/> is in the chain-of-rdls of the <see cref="ICategorizableThing"/> /// </returns> /// <remarks> /// even though <see cref="DomainOfExpertise"/> and <see cref="SiteLogEntry"/> are <see cref="ICategorizableThing"/> these /// classes are outside the scope of any chain-of-rdls. For these two types true is always returned. /// </remarks> public static bool IsCategoryInChainOfRdls(this ICategorizableThing categorizableThing, Category category) { if (categorizableThing is DomainOfExpertise) { return(true); } if (categorizableThing is SiteLogEntry) { return(true); } var thing = categorizableThing as Thing; if (thing.TopContainer is EngineeringModel engineeringModel) { var requiredRdl = engineeringModel.EngineeringModelSetup.RequiredRdl.Single(); return(requiredRdl.QueryCategoriesFromChainOfRdls().Contains(category)); } var containerRdl = thing.GetContainerOfType <ReferenceDataLibrary>(); return(containerRdl.QueryCategoriesFromChainOfRdls().Contains(category)); }
/// <summary> /// Checks whether the categories that a <see cref="ICategorizableThing"/> is a member of are in the chain of <see cref="ReferenceDataLibrary"/> /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> whose member <see cref="Category"/> are checked /// </param> /// <param name="referenceDataLibrary"> /// The <see cref="ReferenceDataLibrary"/> that is used as leaf for the chain of <see cref="ReferenceDataLibrary"/> /// </param> /// <param name="rule"> /// The <see cref="IRule"/> that is being checked /// </param> /// <returns> /// an instance of <see cref="RuleCheckResult"/> if a rule is violated, null if no rule is violated. /// </returns> private RuleCheckResult CheckWhetherCategoriesOfCategorizableThingAreInTheChainOfRdls(ICategorizableThing categorizableThing, ReferenceDataLibrary referenceDataLibrary, IRule rule) { var thing = categorizableThing as Thing; var outOfChainOfRdlCategories = new List <Category>(); foreach (var category in categorizableThing.Category) { if (!referenceDataLibrary.IsCategoryInChainOfRdls(category)) { outOfChainOfRdlCategories.Add(category); } } if (outOfChainOfRdlCategories.Any()) { var categoryIdentifiers = string.Join(",", outOfChainOfRdlCategories.Select(r => r.Iid)); var categoryShortNames = string.Join(",", outOfChainOfRdlCategories.Select(r => r.ShortName)); var result = new RuleCheckResult(thing, rule.Id, $"The ICategorizableThing is a member of Categories that are not in the chain of Reference Data Libraries: {categoryIdentifiers}:{categoryShortNames}", SeverityKind.Error); return(result); } return(null); }
/// <summary> /// Sets the common <see cref="AttributeValue"/> /// </summary> /// <param name="elementWithAttributes">The <see cref="SpecElementWithAttributes"/> to modify</param> /// <param name="thing">The associated <see cref="ICategorizableThing"/></param> private void SetCommonAttributeValues(SpecElementWithAttributes elementWithAttributes, ICategorizableThing thing) { var shortNameType = (AttributeDefinitionString)elementWithAttributes.SpecType.SpecAttributes.Single(x => x.DatatypeDefinition == this.TextDatatypeDefinition && x.LongName == ShortNameAttributeDefName); var nameType = (AttributeDefinitionString)elementWithAttributes.SpecType.SpecAttributes.Single(x => x.DatatypeDefinition == this.TextDatatypeDefinition && x.LongName == NameAttributeDefName); var categoryType = (AttributeDefinitionString)elementWithAttributes.SpecType.SpecAttributes.Single(x => x.DatatypeDefinition == this.TextDatatypeDefinition && x.LongName == CategoryAttributeDefName); var castthing = (Thing)thing; // Add shortname var shortname = new AttributeValueString { TheValue = castthing.UserFriendlyShortName ?? string.Empty, Definition = shortNameType }; elementWithAttributes.Values.Add(shortname); // Add name var name = new AttributeValueString { TheValue = castthing.UserFriendlyName ?? string.Empty, Definition = nameType }; elementWithAttributes.Values.Add(name); // Add Category var category = new AttributeValueString { TheValue = thing.Category.Any() ? string.Join(", ", thing.Category.Select(x => x.ShortName)) : emptyContent, Definition = categoryType }; elementWithAttributes.Values.Add(category); }
/// <summary> /// Queries the <see cref="ICategorizableThing"/> and checks whether it is a member of the /// supplied <see cref="Category"/>, this includes membership of the sub <see cref="Category"/> instances /// of the provided <see cref="Category"/> /// Extensive usage of this overload can slow down performance significantly. /// Please use the overload that takes an <see cref="IEnumerable{ReferenceDataLibrary}"/> as a parameter for better performance. /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> instance that is being queried. /// </param> /// <param name="category"> /// The <see cref="Category"/> that the <see cref="ICategorizableThing"/> may be a member of. /// </param> /// <returns> /// returns true if the <see cref="ICategorizableThing"/> is a member of the <paramref name="category"/>, including it's /// sub <see cref="Category"/> instances. Returns false if the <see cref="ICategorizableThing"/> is not a member /// of the <paramref name="category"/> nor any of it's sub <see cref="Category"/> instances. /// </returns> public static bool IsMemberOfCategory(this ICategorizableThing categorizableThing, Category category) { var categoriesToCheck = category.AllDerivedCategories().ToList(); return(IsMemberOfCategoryImplementation(categorizableThing, category, categoriesToCheck)); }
/// <summary> /// Queries all the super categories of the categories of an <see cref="ICategorizableThing"/> /// and returns the categories and all the super categories up the inheritance chain. /// </summary> /// <param name="categorizableThing"> /// The <see cref="ICategorizableThing"/> that is to be queried for all its categories and its super categories. /// </param> /// <returns> /// the short names of the categories and super categories concatenated as a string /// </returns> public static string GetAllCategoryShortNames(this ICategorizableThing categorizableThing) { var allCategories = categorizableThing.GetAllCategories(); return(allCategories.Aggregate(string.Empty, (current, cat) => $"{current} {cat.ShortName}").Trim()); }
/// <summary> /// Validates whether the <see cref="Category"/> can be applied to the target <see cref="ICategorizableThing"/> /// as part of a frag-n-drop operation /// </summary> /// <param name="permissionService"> /// The <see cref="IPermissionService"/> used to determine whether the active <see cref="Participant"/> has the appropriate /// permissions to update the target <see cref="ICategorizableThing"/> /// </param> /// <param name="target"> /// The target <see cref="ICategorizableThing"/> to which the <see cref="Category"/> may or may not be applied. /// </param> /// <param name="category"> /// The <see cref="Category"/> for which the <see cref="ICategorizableThing"/> is being validated /// </param> /// <param name="logger"> /// The <see cref="ILogger"/> used for logging /// </param> /// <returns> /// <see cref="DragDropEffects.Copy"/> when the <see cref="Category"/> can applied, <see cref="DragDropEffects.None"/> otherwise /// </returns> public static DragDropEffects ValidateDragDrop(IPermissionService permissionService, ICategorizableThing target, Category category, ILogger logger) { if (!(target is Thing thing)) { logger.Warn("The target {0} is not a Thing", target); return(DragDropEffects.None); } if (!permissionService.CanWrite(thing)) { logger.Info("Permission denied to apply the Category."); return(DragDropEffects.None); } if (!category.PermissibleClass.Contains(thing.ClassKind)) { logger.Info("The Category {0} can not be applied to this kind of Thing: {1}", category.ShortName, thing.ClassKind); return(DragDropEffects.None); } if (!target.IsCategoryInChainOfRdls(category)) { logger.Info("The Category {0} is not in the same chain of rdls as the target {1}", category.ShortName, thing.ClassKind); return(DragDropEffects.None); } if (target.Category.Contains(category)) { logger.Info("The Category {0} has already been applied to this {1}", category.ShortName, thing.ClassKind); return(DragDropEffects.None); } return(DragDropEffects.Copy); }