public static ICollection <AttributeInfo> Get(ServiceKey key, bool populateLists) { var config = ServiceConfiguration.Get(key.Id, key.EffectiveDate); var list = ValidValueRuleParser.GetRules(config.ValidValueRule); var set = new ValidValueRuleSet(); set.AddRules(list); var attributeSet = set.GetAttributes(key, SearchOptions.ALL_FALSE); //If we have an attribute with no valid options, clear the value and try again... var emptyAttributes = (from a in attributeSet where a.Values == null || a.Values.Count == 0 select a.Name).ToList(); if (emptyAttributes.Count > 0) { foreach (var a in emptyAttributes) { key.RemoveAttribute(a); } attributeSet = set.GetAttributes(key, SearchOptions.ALL_FALSE); } IDictionary <string, AttributeInfo> tempList = new Dictionary <string, AttributeInfo>(); foreach (var a in attributeSet) { tempList[a.Name] = a; } key.AddMissingAttributes(); //Next we need to look if there are non-list items that need to be collected. foreach (var pair in config.Attributes) { AttributeInfo a = null; if (tempList.ContainsKey(pair.Key)) { tempList.TryGetValue(pair.Key, out a); } tempList[pair.Key] = AttributeFactory.CreateAttribute(pair.Value, pair.Key, a, key); if ((pair.Value.Type == AttributeType.Parent || pair.Value.Type == AttributeType.Related) && key.HasAttribute(pair.Key)) { tempList[pair.Key].SetValue(key.GetAttributeValue(pair.Key, SearchOptions.ALL_TRUE)); } } var ruleSet = new ServiceRuleSet(); ruleSet.AddDefaults(key); // add defaults so rules such as IsApplicable can use them //key doesn't have all the data we have generated so to use the latest we will build a ValueHolder that has what we need... string aValue; foreach (var a in tempList.Values) { aValue = a.GetValue(); if (!string.IsNullOrEmpty(aValue)) // don't add empty values { ruleSet.AddValue(a.Name, new RuleValue(aValue)); } } //Determine which attributes we don't need var finalList = tempList.Values.Where(a => config.IsConfigurableAttribute(a.Name, ruleSet)).ToDictionary(a => a.Name); //Last we need to try and add a description to attributes that haven't had them added yet... //and flag them as optional or not. We will also set the default value if there is one. foreach (var a in finalList.Values) { a.Optional = config.IsOptional(a.Name, ruleSet).ToString(); a.Label = config.GetLabel(a.Name); if (config.HasDefault(a.Name)) { try { a.DefaultValue = config.GetDefaultValue(a.Name, key); } catch (Exception) { } } a.Hidden = config.IsHidden(a.Name, key); a.MaxRepeats = config.GetMaxRepeats(a.Name); a.RequiresRefresh = config.GetRequiresRefresh(a.Name); a.ReadOnly = config.IsReadOnly(a.Name, key); a.ApplicableForChange = config.GetApplicableForChange(a.Name); a.AffectsChildren = config.AffectsChildren(a.Name); a.DesignImpact = config.IsDesignImpact(a.Name, key); a.ProvisioningImpact = config.IsProvisioningImpact(a.Name, key); var attribute = a as ListAttribute; if (attribute != null) { var la = attribute; if (populateLists && la.GetValue() != null && !la.ReadOnly && !la.Hidden) { //Since the value has been set, the list of options is empty. If it is asked for, we will determine //the list of options if this was not set. var myKey = key.Clone(false); myKey.AddValue(la.Name, null); var myAtts = set.GetAttributes(myKey, SearchOptions.ALL_FALSE); foreach (var av in from myAtt in myAtts where myAtt.Name.Equals(la.Name) from av in ((ListAttribute)myAtt).GetList() select av) { la.AddValue(av); } } } } return(config.SortList(finalList.Values)); }