public static void SortLicenses(FeatureRegister FullRegister, out List<License> LicenseList, out List<License> AppLicenses, out List<License> VetAppLicenses, out List<License> OptionLicenses, Dictionary<String, FeatureInfo> FeatureAvailabilities = null) { var register = new FeatureRegisterSubset(FullRegister); // consider only license relations where features are of the same type register.LicenseRelations = register.LicenseRelations.Join(register.Features, lr => lr.FeatureId, f => f.Id, (lr, f) => new { lr, f }) .Join(register.Features, x => x.lr.ParentFeatureId, f => f.Id, (x, f) => new { x.lr, child = x.f, parent = f }) .Where(x => FullRegister.GetFeatureType(x.child.NameInCode) == FullRegister.GetFeatureType(x.parent.NameInCode)).Select(x => x.lr).ToList(); // filter out the unavailale features in order not o mix the dependencie relative to features associated with the same license. if (FeatureAvailabilities != null && FeatureAvailabilities.Count > 0) { register.Features = register.Features.Where(f => FeatureAvailabilities.Select(x => x.Key).Contains(f.NameInCode) && FeatureAvailabilities[f.NameInCode].IsAvailable).ToList(); var selectedFeaturesIds = register.Features.Select(f => f.Id).ToList(); register.FeatureLicenses = register.FeatureLicenses.Where(x => selectedFeaturesIds.Contains(x.Feature.Id)).ToList(); register.Applications = register.Applications.Where(a => selectedFeaturesIds.Contains(a.FeatureId)).ToList(); register.Options = register.Options.Where(x => selectedFeaturesIds.Contains(x.FeatureId)).ToList(); register.LicenseRelations = register.LicenseRelations.Where(lr => selectedFeaturesIds.Contains(lr.FeatureId) && selectedFeaturesIds.Contains(lr.ParentFeatureId)).ToList(); } // do not consider collapsers for license ordering var ParentFeatureIds = register.LicenseRelations.Where(lr => lr.HiderType != HiderTypes.Collapser).Select(x => x.ParentFeatureId).Join(register.Features, k => k, f => f.Id, (k, f) => f.Id).Distinct().ToList(); var UndistinctChildFeatureIds = register.LicenseRelations.Where(lr => lr.HiderType != HiderTypes.Collapser).Select(x => x.FeatureId).Join(register.Features, k => k, f => f.Id, (k, f) => f.Id).ToList(); var ChildFeatureIds = UndistinctChildFeatureIds.Distinct().ToList(); var _MultipleParentLicenses = UndistinctChildFeatureIds.GroupBy(l => l).Where(g => g.Count() > 1).Select(g => g.First()) .Join(register.FeatureLicenses, k => k, f => f.Feature.Id, (k, fl) => fl).ToList(); // Human applications var MultipleParent_HumanAppFeatLicenses = _MultipleParentLicenses.Join(register.Applications.Where(a => a.AppType == SystemEnvironment.Human), fl => fl.Feature.Id, a => a.FeatureId, (fl, a) => fl).ToList(); var _HumanFeatNoChildren = register.Applications.Where(a => a.AppType == SystemEnvironment.Human) .Join(register.FeatureLicenses, a => a.FeatureId, fl => fl.Feature.Id, (a, fl) => fl.Feature).Where(x => !ChildFeatureIds.Contains(x.Id)).ToList(); var HumanAppLicenses = FillChildren(_HumanFeatNoChildren, ParentFeatureIds, MultipleParent_HumanAppFeatLicenses, register); // Vet applications var MultipleParent_VetAppFeatLicenses = _MultipleParentLicenses.Join(register.Applications.Where(a => a.AppType == SystemEnvironment.Veterinary), fl => fl.Feature.Id, a => a.FeatureId, (fl, a) => fl).ToList(); var _VetFeatNoChildren = register.Applications.Where(a => a.AppType == SystemEnvironment.Veterinary) .Join(register.FeatureLicenses, a => a.FeatureId, fl => fl.Feature.Id, (a, fl) => fl.Feature).Where(x => !ChildFeatureIds.Contains(x.Id)).ToList(); VetAppLicenses = FillChildren(_VetFeatNoChildren, ParentFeatureIds, MultipleParent_VetAppFeatLicenses, register); // Options var MultipleParent_OptFeatLicenses = _MultipleParentLicenses.Join(register.Options, fl => fl.Feature.Id, o => o.FeatureId, (fl, o) => fl).ToList(); var _OptionFeatNoChildren = register.Options .Join(register.FeatureLicenses, o => o.FeatureId, fl => fl.Feature.Id, (o, fl) => fl.Feature).Where(x => !ChildFeatureIds.Contains(x.Id)).OrderBy(fl => fl.LicenseId).ToList(); OptionLicenses = FillChildren(_OptionFeatNoChildren, ParentFeatureIds, MultipleParent_OptFeatLicenses, register); AppLicenses = HumanAppLicenses.Union(VetAppLicenses).ToList(); LicenseList = AppLicenses.Union(OptionLicenses).ToList(); }