private bool TryBuildCompositeQuery( XElement compositeDefinition, IResourceModel resourceModel, IDictionary <string, CompositeSpecificationParameter> filterCriteria, IDictionary <string, object> queryStringParameters, out CompositeQuery compositeQuery) { compositeQuery = null; var aliasGenerator = new AliasGenerator(CompositeDefinitionHelper.AliasPrefix); var builderContext = new HqlBuilderContext( new StringBuilder(), new StringBuilder(), new StringBuilder(), new StringBuilder(), new Dictionary <string, object>(StringComparer.InvariantCultureIgnoreCase), null, 1, filterCriteria, queryStringParameters, new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase), aliasGenerator); compositeQuery = _compositeDefinitionProcessor.Process(compositeDefinition, resourceModel, builderContext); return(compositeQuery != null); }
/// <summary> /// Initializes a new instance of the <see cref="CompositeQuery"/> class for a /// non-root composite query. /// </summary> /// <param name="parentCompositeQuery">The composite query that provides the data for the next level up in the composite resource.</param> /// <param name="displayName">The name to be used for the collection of data represented by the composite query.</param> /// <param name="orderedFieldNames">The names of the fields in selection order.</param> /// <param name="futureQuery">The results of the query, exposed by NHibernate as a collection of <see cref="Hashtable"/> instances.</param> /// <param name="isSingleItemResult">Indicates that the results should be treated as a single result in the output.</param> public CompositeQuery( CompositeQuery parentCompositeQuery, string displayName, string[] orderedFieldNames, IEnumerable <object> futureQuery, bool isSingleItemResult) : this(parentCompositeQuery, displayName, orderedFieldNames, futureQuery, isSingleItemResult, null) { }
/// <summary> /// Initializes a new instance of the <see cref="CompositeQuery"/> class for a /// non-root composite query that is recursive, specifying the child instance's join keys /// for the recursion. /// </summary> /// <param name="parentCompositeQuery">The composite query that provides the data for the next level up in the composite resource.</param> /// <param name="displayName">The name to be used for the collection of data represented by the composite query.</param> /// <param name="orderedFieldNames">The names of the fields in selection order.</param> /// <param name="futureQuery">The results of the query, exposed by NHibernate as a collection of <see cref="Hashtable"/> instances.</param> /// <param name="isSingleItemResult">Indicates that the results should be treated as a single result in the output.</param> /// <param name="recursiveChildKeyMap">For recursive relationship, contains the names of the child instance's keys by parent key name for performing the appropriate join for recursion.</param> public CompositeQuery( CompositeQuery parentCompositeQuery, string displayName, string[] orderedFieldNames, IEnumerable <object> futureQuery, bool isSingleItemResult, IDictionary <string, string> recursiveChildKeyMap) { DisplayName = displayName; OrderedFieldNames = orderedFieldNames; IsSingleItemResult = isSingleItemResult; IsRecursive = recursiveChildKeyMap != null; _parentCompositeQuery = parentCompositeQuery; _keyFields = new Lazy <string[]>(() => GetKeyFields(_futureQueryEnumerator.Value)); _dataFields = new Lazy <string[]>(() => GetDataFields(_futureQueryEnumerator.Value)); _dataByParentKey = new Lazy <IDictionary <string, List <Hashtable> > >(() => GetDataByParentKey(_futureQueryEnumerator.Value)); _recursiveChildKeyMap = new Lazy <IDictionary <string, string> >(() => GetRecursiveChildMap(recursiveChildKeyMap)); _futureQueryEnumerator = new Lazy <IEnumeratorWithCompletion>( () => { var enumerator = futureQuery.GetEnumerator(); if (enumerator.MoveNext()) { return(new EnumeratorWithCompletionWrapper(enumerator)); } return(null); }); ChildQueries = new List <CompositeQuery>(); }
public string GetJson( XElement compositeDefinition, IDictionary <string, CompositeSpecificationParameter> parameters, IDictionary <string, object> queryStringParameters, NullValueHandling nullValueHandling = NullValueHandling.Ignore) { Preconditions.ThrowIfNull(parameters, nameof(parameters)); Preconditions.ThrowIfNull(queryStringParameters, nameof(queryStringParameters)); var resourceModel = GetResourceModel(); bool closeSession = false; CompositeQuery query = null; object result = null; try { if (!CurrentSessionContext.HasBind(_sessionFactory)) { CurrentSessionContext.Bind(_sessionFactory.OpenSession()); closeSession = true; } var fieldSelections = GetFieldSelections(queryStringParameters); if (TryBuildCompositeQuery( compositeDefinition, resourceModel, parameters, queryStringParameters, out query)) { result = ProcessResults(query, fieldSelections, nullValueHandling); // Handle Single item requests if (query.IsSingleItemResult && result == null) { throw new NotFoundException("The specified resource could not be found."); } } else { // Return an appropriate response for an empty result if (IsSingleItemRequest(compositeDefinition, resourceModel, queryStringParameters)) { throw new NotFoundException("The specified resource could not be found."); } result = new List <IDictionary>(); } } catch (Exception e) { _logger.Error(e); throw; } finally { if (closeSession) { _sessionFactory.GetCurrentSession() .Close(); } } return(JsonConvert.SerializeObject(result, Formatting.Indented, _jsonSerializerSettings)); }
public IList <IDictionary> ProcessResults( CompositeQuery query, Hashtable parentRow, string[] parentKeys, IReadOnlyList <SelectedResourceMember> fieldSelections, NullValueHandling nullValueHandling, IDictionary <string, string> recursiveChildKeyMap = null) { var results = new List <IDictionary>(); var currentEnumerator = query.GetEnumerator(parentRow, parentKeys, recursiveChildKeyMap); do { // Nothing to enumerate? if (currentEnumerator == null || currentEnumerator.IsComplete) { return(results); } // Get current row var currentRow = (Hashtable)currentEnumerator.Current; if (currentRow == null) { break; } // If the child is outside the context of the parent, quit processing if (parentRow != null && !IsChildRow(parentKeys, parentRow, recursiveChildKeyMap, currentRow)) { break; } // Convert the row to serializable form var resultItem = GetItem(currentRow, query.DataFields, query.OrderedFieldNames, fieldSelections, nullValueHandling); // Process the children foreach (var childQuery in query.ChildQueries) { SelectedResourceMember selectedMember = null; string childCollectionName = childQuery.DisplayName; // Check to see if this collection should be included if (fieldSelections != null && fieldSelections.Count > 0) { selectedMember = fieldSelections.FirstOrDefault(x => x.Equals(childCollectionName) || x.Equals("*")); if (selectedMember == null) { continue; } } resultItem[childCollectionName] = ProcessResults( childQuery, currentRow, query.KeyFields, selectedMember == null ? null : selectedMember.Children, nullValueHandling) .ApplyCardinality(childQuery.IsSingleItemResult); } // Is the current query recursive? if (query.IsRecursive) { // Need to add a child "self" collection with recursion resultItem[query.DisplayName] = ProcessResults( query, currentRow, query.KeyFields, fieldSelections, nullValueHandling, query.RecursiveChildKeyMap); // Strip out hierarchical support fields from the response resultItem.Keys.OfType <string>() .Where(k => k.StartsWith(CompositeDefinitionHelper.HierarchyMarker)) .ToList() .ForEach(k => resultItem.Remove(k)); // Add the row - we're done. results.Add(resultItem); } else { // Just add the row - we're done. results.Add(resultItem); } }while (currentEnumerator.MoveNext()); return(results); }
public object ProcessResults(CompositeQuery query, IReadOnlyList <SelectedResourceMember> fieldSelections, NullValueHandling nullValueHandling) { return(ProcessResults(query, null, null, fieldSelections, nullValueHandling) .ApplyCardinality(query.IsSingleItemResult)); }