// this is only internal for testing purposes; it should be private otherwise... // is there a way to do that? internal DataFragment ProcessRuleTree(IPersistEntity entity, DataIndicatorLookup dataIndicators, AttributeRule[] rules, string prefix) { // todo: xxx review return value logic var f = new List <DataFragment>(); if (rules == null) { return(null); } foreach (var attributeRule in rules) { var attributeFragment = new DataFragment(); // todo: if no entity is specified then the attribute is not set; is this correct? // see at deeper tree levels if (attributeRule.EntityRules == null || attributeRule.EntityRules.EntityRule.Length <= 0) { continue; } // here we have to see if the attribute gets values that we can use ExpressMetaProperty retProp; var entityRuleValue = GetFieldValue(entity, attributeRule.AttributeName, out retProp); if (retProp == null) // we are in the case where the property does not exist in the schema { Log.Warn($"{attributeRule.AttributeName} property is not available for type {entity.GetType().Name} (as expected on attributeRule '{attributeRule.RuleID}' in {attributeRule.ParentConceptTemplate.uuid})"); continue; } if (retProp.EntityAttribute.IsEnumerable) { var propCollection = entityRuleValue as IEnumerable <object>; if (propCollection == null) { continue; } var children = propCollection.OfType <IPersistEntity>().ToArray(); foreach (var child in children) { // todo: this is likely to return the same variable names for the datatable var t = FillEntities(attributeRule.EntityRules.EntityRule, child, dataIndicators, prefix); attributeFragment.Merge(t); } } else { var t = FillEntities(attributeRule.EntityRules.EntityRule, entityRuleValue as IPersistEntity, dataIndicators, prefix); attributeFragment.Merge(t); } if (!attributeFragment.IsEmpty) { f.Add(attributeFragment); } } return(DataFragment.Combine(f)); }
/// <summary> /// Allows to use a ConceptTemplate for extracting datatables of values from an entity. /// Columns returned depend on specified dataIndicators /// </summary> /// <param name="entity">the entity of interest</param> /// <param name="template">the ConceptTemplate to apply</param> /// <param name="dataIndicators">the indicators of interest</param> /// <returns></returns> public DataTable GetData(IPersistEntity entity, ConceptTemplate template, IEnumerable <DataIndicator> dataIndicators) { var dt = new DataTable(); var indicators = dataIndicators as DataIndicator[] ?? dataIndicators.ToArray(); foreach (var dataIndicator in indicators) { var c = new DataColumn(dataIndicator.ColumnName); dt.Columns.Add(c); } var fastIndicators = new DataIndicatorLookup(indicators); // template.DebugTemplateTree(); // when ending row or going deeper it fills row var vls = GetAttributes(template, entity, fastIndicators, ""); vls?.Populate(dt); return(dt); }
internal DataFragment FillEntities(EntityRule[] rules, IPersistEntity entity, DataIndicatorLookup dataIndicators, string prefix) { // todo: review the return logic; // if (entity == null) { return(null); } foreach (var entityRule in rules) { // it's probably safe to assume that if we are here then the whole schema is the same of the element we are using // regardless from _forceModelSchema settings; it would otherwise be complicated to consider which of the schemas to use of the // array of schemes of the parent ConceptTemplate. var filterType = GetExpressType(entity.Model.Metadata, entityRule.EntityName.ToUpper()); if (filterType == null) { continue; } if (!filterType.NonAbstractSubTypes.Contains(entity.ExpressType)) { continue; } if (entityRule.References != null) { // need to resolve reference if (string.IsNullOrEmpty(entityRule.References.Template?.@ref)) { continue; } var tPrefix = prefix; // Debug.Print(@"Ref: {0} on {1} ({2})", entityRule.References.Template.@ref, entity.EntityLabel, entity.GetType().Name); var refTemplate = Mvd.GetConceptTemplate(entityRule.References.Template.@ref); if (!string.IsNullOrEmpty(entityRule.References.IdPrefix)) { tPrefix += entityRule.References.IdPrefix; } // todo: xxx this is wrong! what about the following rules? var t = GetAttributes(refTemplate, entity, dataIndicators, tPrefix); return(t); } else if (entityRule.AttributeRules != null) { // todo: xxx this is wrong! what about the following rules? // rules nested directly return(GetAttributes(entityRule.AttributeRules.AttributeRule, entity, dataIndicators, prefix)); } } return(null); }
private DataFragment ExtractRulesValues(IPersistEntity entity, DataIndicatorLookup dataIndicators, AttributeRule[] rules, string prefix) { var tmp = new List <DataFragment>(); if (rules == null) { return(null); } foreach (var attributeRule in rules) { // sort out values at current level // we have an id and indicators require it if (string.IsNullOrEmpty(attributeRule.RuleID)) { continue; } var storageName = prefix + attributeRule.RuleID; if (!dataIndicators.Contains(storageName)) { continue; } ExpressMetaProperty retProp; var value = GetFieldValue(entity, attributeRule.AttributeName, out retProp); if (retProp == null) { // propery not found in class... ignore // continue; } // set the value if (dataIndicators.Requires(storageName, DataIndicator.ValueSelectorEnum.Value)) { DataFragment tF; if (value is IEnumerable <object> ) { var asEnum = value as IEnumerable <object>; tF = new DataFragment(storageName, asEnum); } else { tF = new DataFragment(storageName, value); } tmp.Add(tF); } // set the type // if (dataIndicators.Requires(storageName, DataIndicator.ValueSelectorEnum.Type)) { var storName = DataIndicator.GetColumnName(storageName, DataIndicator.ValueSelectorEnum.Type); tmp.Add(new DataFragment(storName, value.GetType().Name)); } // set the Size // if (dataIndicators.Requires(storageName, DataIndicator.ValueSelectorEnum.Size)) { var storName = DataIndicator.GetColumnName(storageName, DataIndicator.ValueSelectorEnum.Size); if (value is IEnumerable <object> ) { var asEnum = value as IEnumerable <object>; tmp.Add(new DataFragment(storName, asEnum.Count())); } else if (value == null) { tmp.Add(new DataFragment(storName, 0)); } else { tmp.Add(new DataFragment(storName, 1)); // there's one entity } } // set Existence // ReSharper disable once InvertIf // for symmetry in code // if (dataIndicators.Requires(storageName, DataIndicator.ValueSelectorEnum.Exists)) { var storName = DataIndicator.GetColumnName(storageName, DataIndicator.ValueSelectorEnum.Exists); var storValue = value != null; if (value != null) { storValue = value.ToString().Trim() != ""; } tmp.Add(new DataFragment(storName, storValue)); // true if not null } } return(DataFragment.Combine(tmp)); }
private DataFragment GetAttributes(AttributeRule[] attributeRules, IPersistEntity entity, DataIndicatorLookup dataIndicators, string prefix) { // 1. get all values // add values at this level // var fragments = new List <DataFragment>(); var t1 = ExtractRulesValues(entity, dataIndicators, attributeRules, prefix); if (t1 != null) { fragments.Add(t1); } // process the rest of the tree // var t = ProcessRuleTree(entity, dataIndicators, attributeRules, prefix); if (t != null) { fragments.Add(t); } // 2. combine them and return return(DataFragment.Combine(fragments)); }
internal DataFragment GetAttributes(ConceptTemplate template, IPersistEntity entity, DataIndicatorLookup dataIndicators, string prefix) { var useT = template.GetSpecificConceptTemplateFor(entity); return(GetAttributes(useT.Rules, entity, dataIndicators, prefix)); }