private Getter FormGetterByRelation(Relation relation, BoundingParameter[] parameters, out ParameterNames parameterNames,out Query query) { Getter getter; if (relation.HasTrivialQuery) { getter = (keys, parPairs) => keys.Select(k => new KeyValuePair<Guid, IEnumerable<Guid>>(k, new[] {k})).ToArray(); parameterNames = new ParameterNames(new string[0]); query = null; } else { var targetQuery = relation.SelectTheBestQuery(parameters) .FirstOrDefault(); if (targetQuery == null) throw new InvalidOperationException( string.Format("Нет запроса для построения дерева: род. {0}, доч. {1} ", relation.ParentElement.Name, relation.ChildElement.Name)); query = targetQuery; getter = (keys, parPairs) => targetQuery.GetMultipleChildResourceQuery(relation.ParentElement.Name, parPairs.Keys.ToArray())(keys,parPairs.Values.ToArray()); parameterNames = new ParameterNames(targetQuery.Arguments.Where(k=>!StringComparer.InvariantCultureIgnoreCase.Equals(k,relation.ParentElement.Name))); } return getter; }
public IEnumerable<Query> SelectTheBestQuery(BoundingParameter[] parameters) { var paramsWithoutResource = parameters; var rankedQueries = Queries.Select(k => new { rank = CalcQueryRank(k, ParentElement.Name, paramsWithoutResource), query = k }).ToArray(); var bestQuery = rankedQueries.Where(k => k.rank >= 0) .OrderByDescending(k => k.rank) .Select(k => k.query); return bestQuery; }
private static double CalcQueryRank(Query query, string parentName, BoundingParameter[] parameters) { Func<string, string, bool> equals = (a, b) => string.Equals(a, b, StringComparison.InvariantCultureIgnoreCase); //отсев запросов, у которых есть параметры, не являющиеся родительским параметром или одним параметром из списка if (query.Arguments .Where(k => !equals(k, parentName)) .Any(k => parameters.All(k2 => !equals(k2.Name, k)))) return -1; double rank = 0.1; if (query.Arguments.Contains(parentName) && query.ArgCount == 1) { rank = 0.5; } else if (parameters.Length != 0) { var correctiveFloor = parameters.Max(k => k.Depth); //нужно перевести глубину параметров от текущей точки в рейтинг для текущей точки, т.е. перевернуть их все rank = query.Arguments.Where(k => !equals(k, parentName)).Select( k => correctiveFloor - parameters.Single(k2 => equals(k2.Name, k)).Depth + 1).Sum(); } if (query.Arguments.Contains(parentName)) { rank *= 2; if (query.SerialQueryIsPreferred(parentName)) rank += 1; } if (!string.IsNullOrEmpty(query.Namespace)) rank *= 100; return rank; }
private IEnumerable <PrimaryFrameNode> MakeAllPossibleWaysRec(List <string> processed, ProjectionElement element, SortedSet <BoundingParameter> orderedParameters, int depth) { if (depth == int.MinValue) { throw new InvalidOperationException("Ошибка при построении плана - слишком глубокая схема для разбора"); } if (depth == 0) { return(new PrimaryFrameNode[0]); } #region Проверка - был ли проверен текущий элемент, и добавление его к проверенным var hash = GetHashForElementAndParameters(element, new ParameterNames(orderedParameters.Select(k => k.Name))); if (processed.Contains(hash)) { return(new PrimaryFrameNode[0]); } processed.Add(hash); #endregion #region Добавление текущего элемента к родительским параметрам или обнуление глубины уже существующего параметра с данным именем foreach (var p in orderedParameters) { p.Depth++; } var parameter = orderedParameters.FirstOrDefault(k => k.Name == element.Name); int oldDepth; if (parameter == null) { parameter = new BoundingParameter(element.Name, 1); orderedParameters.Add(parameter); oldDepth = 0; } else { oldDepth = parameter.Depth; parameter.Depth = 1; } #endregion #region Обход детей дочерних нод var childElements = element.DownRelations .Select(k => new { relation = k, k.ChildElement, children = MakeAllPossibleWaysRec(processed, k.ChildElement, orderedParameters, depth - 1) }).ToArray(); #endregion processed.Remove(hash); if (oldDepth == 0) { orderedParameters.Remove(parameter); } else { parameter.Depth = oldDepth; } #region Формирование списка нод вместе с дочерними var allNodes = childElements.Select(k => new PrimaryFrameNode { Current = k.ChildElement, OrderedParameters = orderedParameters.Where(k2 => !StringComparer.InvariantCultureIgnoreCase.Equals(k2.Name, element.Name)) .Select(k2 => new BoundingParameter(k2.Name, k2.Depth)) .ToArray(), Parent = element, Relation = k.relation }) .Concat(childElements.SelectMany(k => k.children)) .ToArray(); #endregion foreach (var p in orderedParameters) { p.Depth--; } return(allNodes); }
private IEnumerable<PrimaryFrameNode> MakeAllPossibleWaysRec(List<string> processed, ProjectionElement element, SortedSet<BoundingParameter> orderedParameters, int depth) { if (depth == int.MinValue) throw new InvalidOperationException("Ошибка при построении плана - слишком глубокая схема для разбора"); if (depth == 0) return new PrimaryFrameNode[0]; #region Проверка - был ли проверен текущий элемент, и добавление его к проверенным var hash = GetHashForElementAndParameters(element, new ParameterNames(orderedParameters.Select(k => k.Name))); if (processed.Contains(hash)) return new PrimaryFrameNode[0]; processed.Add(hash); #endregion #region Добавление текущего элемента к родительским параметрам или обнуление глубины уже существующего параметра с данным именем foreach (var p in orderedParameters) { p.Depth++; } var parameter = orderedParameters.FirstOrDefault(k => k.Name == element.Name); int oldDepth; if (parameter == null) { parameter = new BoundingParameter(element.Name, 1); orderedParameters.Add(parameter); oldDepth = 0; } else { oldDepth = parameter.Depth; parameter.Depth = 1; } #endregion #region Обход детей дочерних нод var childElements = element.DownRelations .Select(k => new { relation = k, k.ChildElement, children = MakeAllPossibleWaysRec(processed, k.ChildElement, orderedParameters, depth - 1) }).ToArray(); #endregion processed.Remove(hash); if (oldDepth == 0) orderedParameters.Remove(parameter); else { parameter.Depth = oldDepth; } #region Формирование списка нод вместе с дочерними var allNodes = childElements.Select(k => new PrimaryFrameNode { Current = k.ChildElement, OrderedParameters = orderedParameters.Where(k2=>!StringComparer.InvariantCultureIgnoreCase.Equals(k2.Name,element.Name)) .Select(k2 => new BoundingParameter(k2.Name, k2.Depth)) .ToArray(), Parent = element, Relation = k.relation }) .Concat(childElements.SelectMany(k => k.children)) .ToArray(); #endregion foreach (var p in orderedParameters) { p.Depth--; } return allNodes; }
public Getter FormGetter(Relation relation, BoundingParameter[] parameters, out ParameterNames parameterNames) { var testBuilder = new FramingPlanBuilder(); Query query; return testBuilder.FormGetterByRelation(relation, parameters,out parameterNames,out query); }