Exemplo n.º 1
0
        internal static SubscriptionCreationOptions CreateSubscriptionOptionsFromGeneric <T>(
            DocumentConventions conventions,
            SubscriptionCreationOptions criteria,
            Expression <Func <T, bool> > predicate,
            Expression <Func <T, object> > project,
            Action <ISubscriptionIncludeBuilder <T> > includes)
        {
            criteria ??= new SubscriptionCreationOptions();
            var           collectionName = conventions.GetCollectionName(typeof(T));
            StringBuilder queryBuilder;

            if (criteria.Query != null)
            {
                queryBuilder = new StringBuilder(criteria.Query);
            }
            else
            {
                queryBuilder = new StringBuilder();
                var tType            = typeof(T);
                var includeRevisions = tType.IsConstructedGenericType && tType.GetGenericTypeDefinition() == typeof(Revision <>);
                if (includeRevisions)
                {
                    collectionName = conventions.GetCollectionName(tType.GenericTypeArguments[0]);
                }

                queryBuilder.Append("from '");
                StringExtensions.EscapeString(queryBuilder, collectionName);
                queryBuilder.Append('\'');
                if (includeRevisions)
                {
                    queryBuilder.Append(" (Revisions = true)");
                }

                criteria.Query = queryBuilder.Append(" as doc").ToString();
            }

            if (predicate != null)
            {
                var script = predicate.CompileToJavascript(
                    new JavascriptCompilationOptions(
                        JsCompilationFlags.BodyOnly,
                        JavascriptConversionExtensions.MathSupport.Instance,
                        new JavascriptConversionExtensions.DictionarySupport(),
                        JavascriptConversionExtensions.LinqMethodsSupport.Instance,
                        new JavascriptConversionExtensions.SubscriptionsWrappedConstantSupport(conventions),
                        new JavascriptConversionExtensions.ConstSupport(conventions),
                        new JavascriptConversionExtensions.ReplaceParameterWithNewName(predicate.Parameters[0], "this"),
                        JavascriptConversionExtensions.ToStringSupport.Instance,
                        JavascriptConversionExtensions.DateTimeSupport.Instance,
                        JavascriptConversionExtensions.TimeSpanSupport.Instance,
                        JavascriptConversionExtensions.InvokeSupport.Instance,
                        JavascriptConversionExtensions.NullCoalescingSupport.Instance,
                        JavascriptConversionExtensions.NestedConditionalSupport.Instance,
                        JavascriptConversionExtensions.StringSupport.Instance,
                        new JavascriptConversionExtensions.IdentityPropertySupport(conventions)
                        ));

                queryBuilder
                .Insert(0, $"declare function predicate() {{ return {script} }}{Environment.NewLine}")
                .AppendLine()
                .Append("where predicate.call(doc)");
            }

            if (project != null)
            {
                var script = project.CompileToJavascript(
                    new JavascriptCompilationOptions(
                        JsCompilationFlags.BodyOnly,
                        JavascriptConversionExtensions.MathSupport.Instance,
                        new JavascriptConversionExtensions.DictionarySupport(),
                        JavascriptConversionExtensions.LinqMethodsSupport.Instance,
                        new JavascriptConversionExtensions.ConstSupport(conventions),
                        JavascriptConversionExtensions.ToStringSupport.Instance,
                        JavascriptConversionExtensions.DateTimeSupport.Instance,
                        JavascriptConversionExtensions.TimeSpanSupport.Instance,
                        JavascriptConversionExtensions.InvokeSupport.Instance,
                        JavascriptConversionExtensions.NullCoalescingSupport.Instance,
                        JavascriptConversionExtensions.StringSupport.Instance,
                        JavascriptConversionExtensions.NestedConditionalSupport.Instance,
                        new JavascriptConversionExtensions.ReplaceParameterWithNewName(project.Parameters[0], "doc"),
                        new JavascriptConversionExtensions.IdentityPropertySupport(conventions),
                        JavascriptConversionExtensions.CounterSupport.Instance,
                        JavascriptConversionExtensions.CompareExchangeSupport.Instance,
                        new JavascriptConversionExtensions.LoadSupport(),
                        JavascriptConversionExtensions.MemberInit.Instance
                        ));

                queryBuilder
                .AppendLine()
                .Append("select ")
                .Append(script);
            }

            if (includes != null)
            {
                var builder = new IncludeBuilder <T>(conventions);
                includes(builder);

                var numberOfIncludesAdded = 0;

                if (builder.DocumentsToInclude?.Count > 0)
                {
                    queryBuilder
                    .AppendLine()
                    .Append("include ");

                    foreach (var inc in builder.DocumentsToInclude)
                    {
                        var include = "doc." + inc;

                        if (numberOfIncludesAdded > 0)
                        {
                            queryBuilder.Append(",");
                        }

                        if (IncludesUtil.RequiresQuotes(include, out var escapedInclude))
                        {
                            queryBuilder
                            .Append("'")
                            .Append(escapedInclude)
                            .Append("'");
                        }
                        else
                        {
                            queryBuilder.Append(QueryToken.IsKeyword(include) ? $"'{include}'" : include);
                        }

                        numberOfIncludesAdded++;
                    }
                }

                if (builder.AllCounters)
                {
                    if (numberOfIncludesAdded == 0)
                    {
                        queryBuilder
                        .AppendLine()
                        .Append("include ");
                    }

                    var token = CounterIncludesToken.All(string.Empty);
                    token.WriteTo(queryBuilder);

                    numberOfIncludesAdded++;
                }
                else if (builder.CountersToInclude?.Count > 0)
                {
                    if (numberOfIncludesAdded == 0)
                    {
                        queryBuilder
                        .AppendLine()
                        .Append("include ");
                    }

                    foreach (var counterName in builder.CountersToInclude)
                    {
                        if (numberOfIncludesAdded > 0)
                        {
                            queryBuilder.Append(",");
                        }

                        var token = CounterIncludesToken.Create(string.Empty, counterName);
                        token.WriteTo(queryBuilder);

                        numberOfIncludesAdded++;
                    }
                }

                if (builder.TimeSeriesToInclude != null)
                {
                    foreach (var timeSeriesRange in builder.TimeSeriesToInclude)
                    {
                        if (numberOfIncludesAdded == 0)
                        {
                            queryBuilder
                            .AppendLine()
                            .Append("include ");
                        }

                        if (numberOfIncludesAdded > 0)
                        {
                            queryBuilder.Append(",");
                        }

                        var token = TimeSeriesIncludesToken.Create(string.Empty, timeSeriesRange);
                        token.WriteTo(queryBuilder);

                        numberOfIncludesAdded++;
                    }
                }
            }

            criteria.Query = queryBuilder.ToString();
            return(criteria);
        }
        internal static SubscriptionCreationOptions CreateSubscriptionOptionsFromGeneric <T>(
            DocumentConventions conventions,
            SubscriptionCreationOptions criteria,
            Expression <Func <T, bool> > predicate,
            Expression <Func <T, object> > project,
            Action <ISubscriptionIncludeBuilder <T> > includes)
        {
            criteria ??= new SubscriptionCreationOptions();
            var collectionName = conventions.GetCollectionName(typeof(T));

            if (criteria.Query == null)
            {
                var tType            = typeof(T);
                var includeRevisions = tType.IsConstructedGenericType && tType.GetGenericTypeDefinition() == typeof(Revision <>);
                if (includeRevisions)
                {
                    collectionName = conventions.GetCollectionName(tType.GenericTypeArguments[0]);
                }

                var builder = new StringBuilder("from '");
                StringExtensions.EscapeString(builder, collectionName);
                builder.Append('\'');
                if (includeRevisions)
                {
                    builder.Append(" (Revisions = true)");
                }

                criteria.Query = builder.Append(" as doc").ToString();
            }

            if (predicate != null)
            {
                var script = predicate.CompileToJavascript(
                    new JavascriptCompilationOptions(
                        JsCompilationFlags.BodyOnly,
                        JavascriptConversionExtensions.MathSupport.Instance,
                        new JavascriptConversionExtensions.DictionarySupport(),
                        JavascriptConversionExtensions.LinqMethodsSupport.Instance,
                        new JavascriptConversionExtensions.SubscriptionsWrappedConstantSupport(conventions),
                        new JavascriptConversionExtensions.ConstSupport(conventions),
                        new JavascriptConversionExtensions.ReplaceParameterWithNewName(predicate.Parameters[0], "this"),
                        JavascriptConversionExtensions.ToStringSupport.Instance,
                        JavascriptConversionExtensions.DateTimeSupport.Instance,
                        JavascriptConversionExtensions.TimeSpanSupport.Instance,
                        JavascriptConversionExtensions.InvokeSupport.Instance,
                        JavascriptConversionExtensions.NullCoalescingSupport.Instance,
                        JavascriptConversionExtensions.NestedConditionalSupport.Instance,
                        JavascriptConversionExtensions.StringSupport.Instance
                        ));

                criteria.Query = $"declare function predicate() {{ return {script} }}{Environment.NewLine}" +
                                 $"{criteria.Query}{Environment.NewLine}" +
                                 "where predicate.call(doc)";
            }

            if (project != null)
            {
                var script = project.CompileToJavascript(
                    new JavascriptCompilationOptions(
                        JsCompilationFlags.BodyOnly,
                        JavascriptConversionExtensions.MathSupport.Instance,
                        new JavascriptConversionExtensions.DictionarySupport(),
                        JavascriptConversionExtensions.LinqMethodsSupport.Instance,
                        new JavascriptConversionExtensions.ConstSupport(conventions),
                        JavascriptConversionExtensions.ToStringSupport.Instance,
                        JavascriptConversionExtensions.DateTimeSupport.Instance,
                        JavascriptConversionExtensions.TimeSpanSupport.Instance,
                        JavascriptConversionExtensions.InvokeSupport.Instance,
                        JavascriptConversionExtensions.NullCoalescingSupport.Instance,
                        JavascriptConversionExtensions.StringSupport.Instance,
                        JavascriptConversionExtensions.NestedConditionalSupport.Instance,
                        new JavascriptConversionExtensions.ReplaceParameterWithNewName(project.Parameters[0], "doc"),
                        new JavascriptConversionExtensions.IdentityPropertySupport(conventions),
                        JavascriptConversionExtensions.CounterSupport.Instance,
                        JavascriptConversionExtensions.CompareExchangeSupport.Instance,
                        new JavascriptConversionExtensions.LoadSupport(),
                        JavascriptConversionExtensions.MemberInit.Instance
                        ));
                criteria.Query += Environment.NewLine + "select " + script;
            }

            if (includes != null)
            {
                var builder = new IncludeBuilder <T>(conventions);
                includes(builder);

                if (builder.DocumentsToInclude != null && builder.DocumentsToInclude.Count > 0)
                {
                    criteria.Query += Environment.NewLine + "include ";

                    var first = true;
                    foreach (var inc in builder.DocumentsToInclude)
                    {
                        var include = "doc." + inc;
                        if (first == false)
                        {
                            criteria.Query += ",";
                        }
                        first = false;

                        if (IncludesUtil.RequiresQuotes(include, out var escapedInclude))
                        {
                            criteria.Query += $"'{escapedInclude}'";
                        }
                        else
                        {
                            criteria.Query += QueryToken.IsKeyword(include) ? $"'{include}'" : include;
                        }
                    }
                }
            }

            return(criteria);
        }