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);
        }
Example #2
0
 /// <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)
 {
 }
Example #3
0
        /// <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));
 }