Esempio n. 1
0
        /// <summary>
        /// Analyzes a lambda expression to check whether it can be satisfied with
        /// $select and client-side materialization.
        /// </summary>
        /// <param name="le">Lambda expression.</param>
        /// <param name="re">Resource expression in scope.</param>
        /// <param name="matchMembers">Whether member accesses are matched as top-level projections.</param>
        /// <param name="context">Context of expression to analyze.</param>
        /// <returns>true if the lambda is a client-side projection; false otherwise.</returns>
        internal static bool Analyze(LambdaExpression le, ResourceExpression re, bool matchMembers, DataServiceContext context)
        {
            Debug.Assert(le != null, "le != null");

            if (le.Body.NodeType == ExpressionType.Constant)
            {
                if (ClientTypeUtil.TypeOrElementTypeIsEntity(le.Body.Type))
                {
                    throw new NotSupportedException(Strings.ALinq_CannotCreateConstantEntity);
                }

                re.Projection = new ProjectionQueryOptionExpression(le.Body.Type, le, new List <string>());
                return(true);
            }

            if (le.Body.NodeType == ExpressionType.MemberInit || le.Body.NodeType == ExpressionType.New)
            {
                AnalyzeResourceExpression(le, re, context);
                return(true);
            }

            if (matchMembers)
            {
                // Members can be projected standalone or type-casted.
                Expression withoutConverts = SkipConverts(le.Body);
                if (withoutConverts.NodeType == ExpressionType.MemberAccess)
                {
                    AnalyzeResourceExpression(le, re, context);
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 2
0
        /// <summary>
        /// Visit an <see cref="InputReferenceExpression"/>, producing a new InputReferenceExpression
        /// based on the visited form of the <see cref="QueryableResourceExpression"/> that is referenced by
        /// the InputReferenceExpression argument, <paramref name="ire"/>.
        /// </summary>
        /// <param name="ire">InputReferenceExpression expression to visit</param>
        /// <returns>Visited InputReferenceExpression expression</returns>
        internal virtual Expression VisitInputReferenceExpression(InputReferenceExpression ire)
        {
            Debug.Assert(ire != null, "ire != null -- otherwise caller never should have visited here");
            ResourceExpression re = (ResourceExpression)this.Visit(ire.Target);

            return(re.CreateReference());
        }
        /// <summary>Builds the Uri for the expression passed in.</summary>
        /// <param name="e">The expression to translate into a Uri</param>
        /// <returns>Query components</returns>
        internal QueryComponents Translate(Expression e)
        {
            Uri     uri;
            Version version;
            bool    addTrailingParens = false;
            Dictionary <Expression, Expression> normalizerRewrites = null;

            // short cut analysis if just a resource set or singleton resource.
            // note - to be backwards compatible with V1, will only append trailing () for queries
            // that include more then just a resource set.
            if (!(e is QueryableResourceExpression))
            {
                normalizerRewrites = new Dictionary <Expression, Expression>(ReferenceEqualityComparer <Expression> .Instance);
                e = Evaluator.PartialEval(e);
                e = ExpressionNormalizer.Normalize(e, normalizerRewrites);
                e = ResourceBinder.Bind(e, this.Context);
                addTrailingParens = true;
            }

            UriWriter.Translate(this.Context, addTrailingParens, e, out uri, out version);
            ResourceExpression re            = e as ResourceExpression;
            Type             lastSegmentType = re.Projection == null ? re.ResourceType : re.Projection.Selector.Parameters[0].Type;
            LambdaExpression selector        = re.Projection == null ? null : re.Projection.Selector;

            return(new QueryComponents(uri, version, lastSegmentType, selector, normalizerRewrites));
        }
        /// <summary>
        /// Retargets this input reference to point to the resource set specified by <paramref name="newTarget"/>.
        /// </summary>
        /// <param name="newTarget">The <see cref="QueryableResourceExpression"/> that this input reference should use as its target</param>
        internal void OverrideTarget(QueryableResourceExpression newTarget)
        {
            Debug.Assert(newTarget != null, "Resource set cannot be null");
            Debug.Assert(newTarget.ResourceType.Equals(this.Type), "Cannot reference a resource set with a different resource type");

            this.target = newTarget;
        }
Esempio n. 5
0
        /// <summary>
        /// Analyzes the specified <paramref name="lambda"/> for selection and updates
        /// <paramref name="resource"/>.
        /// </summary>
        /// <param name="lambda">Lambda expression to analyze.</param>
        /// <param name="resource">Resource expression to update.</param>
        /// <param name="context">Context of expression to analyze.</param>
        private static void AnalyzeResourceExpression(LambdaExpression lambda, ResourceExpression resource, DataServiceContext context)
        {
            SelectExpandPathBuilder pb = new SelectExpandPathBuilder();

            ProjectionAnalyzer.Analyze(lambda, pb, context);
            resource.Projection  = new ProjectionQueryOptionExpression(lambda.Body.Type, lambda, pb.ProjectionPaths.ToList());
            resource.ExpandPaths = pb.ExpandPaths.Union(resource.ExpandPaths, StringComparer.Ordinal).ToList();
            resource.RaiseUriVersion(pb.UriVersion);
        }
Esempio n. 6
0
        protected virtual Expression VisitResource(ResourceExpression e)
        {
            var fields = VisitFieldDeclarations(e.Fields);
            var filter = Visit(e.Filter);

            return(Equals(fields, e.Fields) && filter == e.Filter
                ? e
                : new ResourceExpression(e.Type, e.Name, fields, filter));
        }
Esempio n. 7
0
        /// <summary>
        /// Replaces Lambda parameter references or transparent scope property accesses over those Lambda
        /// parameter references with <see cref="InputReferenceExpression"/>s to the appropriate corresponding
        /// <see cref="QueryableResourceExpression"/>s, based on the 'input' QueryableResourceExpression to which the
        /// Lambda is logically applied and any enclosing transparent scope applied to that input resource.
        /// </summary>
        /// <param name="e">The expression to rebind</param>
        /// <param name="currentInput">
        /// The 'current input' resource - either the root resource or the
        /// rightmost resource in the navigation chain.</param>
        /// <param name="inputParameter">The Lambda parameter that represents a reference to the 'input'</param>
        /// <param name="referencedInputs">A list that will be populated with the resources that were referenced by the rebound expression</param>
        /// <returns>
        /// The rebound version of <paramref name="e"/> where MemberExpression/ParameterExpressions that
        /// represent resource references have been replaced with appropriate InputReferenceExpressions.
        /// </returns>
        internal static Expression Bind(Expression e, ResourceExpression currentInput, ParameterExpression inputParameter, List <ResourceExpression> referencedInputs)
        {
            Debug.Assert(e != null, "Expression cannot be null");
            Debug.Assert(currentInput != null, "A current input resource is required");
            Debug.Assert(inputParameter != null, "The input lambda parameter is required");
            Debug.Assert(referencedInputs != null, "The referenced inputs list is required");

            InputBinder binder = new InputBinder(currentInput, inputParameter);
            Expression  result = binder.Visit(e);

            referencedInputs.AddRange(binder.referencedInputs);
            return(result);
        }
Esempio n. 8
0
 public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
 {
     output.Write("using (");
     Variable.WriteTo(output);
     output.Write(" = ");
     ResourceExpression.WriteTo(output, options);
     output.WriteLine(") {");
     output.Indent();
     Body.WriteTo(output, options);
     output.Unindent();
     output.WriteLine();
     output.Write("}");
 }
Esempio n. 9
0
        protected override Expression VisitResource(ResourceExpression resource)
        {
            _stringBuilder.Append(_root);
            Visit(resource.Name);

            if (resource.Fields.Any())
            {
                AppendParameterSeparator();
                _stringBuilder.Append("fields=");
                VisitFieldDeclarations(resource.Fields);
            }

            Visit(resource.Filter);

            return(resource);
        }
Esempio n. 10
0
        internal LambdaExpression Rebind(LambdaExpression lambda, ResourceExpression source)
        {
            this.successfulRebind   = true;
            this.oldLambdaParameter = lambda.Parameters[0];
            this.projectionSource   = source;

            Expression body = this.Visit(lambda.Body);

            if (this.successfulRebind)
            {
                Type delegateType = typeof(Func <,>).MakeGenericType(new Type[] { newLambdaParameter.Type, lambda.Body.Type });
                return(Expression.Lambda(delegateType, body, new ParameterExpression[] { this.newLambdaParameter }));
            }
            else
            {
                throw new NotSupportedException(Strings.ALinq_CanOnlyProjectTheLeaf);
            }
        }
Esempio n. 11
0
        internal static LambdaExpression TryToRewrite(LambdaExpression le, ResourceExpression source)
        {
            Type             proposedParameterType = source.ResourceType;
            LambdaExpression result;

            if (!ResourceBinder.PatternRules.MatchSingleArgumentLambda(le, out le) ||                       // can only rewrite single parameter Lambdas.
                ClientTypeUtil.TypeOrElementTypeIsEntity(le.Parameters[0].Type) ||                          // only attempt to rewrite if lambda parameter is not an entity type
                !(le.Parameters[0].Type.GetProperties().Any(p => p.PropertyType == proposedParameterType))) // lambda parameter must have public property that is same as proposed type.
            {
                result = le;
            }
            else
            {
                ProjectionRewriter rewriter = new ProjectionRewriter(proposedParameterType);
                result = rewriter.Rebind(le, source);
            }

            return(result);
        }
Esempio n. 12
0
 public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
 {
     WriteILRange(output, options);
     output.Write("using");
     if (IsAsync)
     {
         output.Write(".async");
     }
     if (IsRefStruct)
     {
         output.Write(".ref");
     }
     output.Write(" (");
     Variable.WriteTo(output);
     output.Write(" = ");
     ResourceExpression.WriteTo(output, options);
     output.WriteLine(") {");
     output.Indent();
     Body.WriteTo(output, options);
     output.Unindent();
     output.WriteLine();
     output.Write("}");
 }
 /// <summary>
 /// Constructs a new input reference expression that refers to the specified resource set
 /// </summary>
 /// <param name="target">The target resource set that the new expression will reference</param>
 internal InputReferenceExpression(ResourceExpression target)
 {
     Debug.Assert(target != null, "Target resource set cannot be null");
     this.target = target;
 }
Esempio n. 14
0
        /// <summary>
        /// Resolves member accesses that represent transparent scope property accesses to the corresponding resource,
        /// iff the input resource is enclosed in a transparent scope and the specified MemberExpression represents
        /// such a property access.
        /// </summary>
        /// <param name="m">MemberExpression expression to visit</param>
        /// <returns>
        /// An InputReferenceExpression if the member access represents a transparent scope property
        /// access that can be resolved to a resource in the path that produces the input resource;
        /// otherwise the same MemberExpression is returned.
        /// </returns>
        internal override Expression VisitMemberAccess(MemberExpression m)
        {
            // If the current input resource is not enclosed in a transparent scope, then this
            // MemberExpression cannot represent a valid transparent scope access based on the input parameter.
            if (this.inputResource == null ||
                !this.inputResource.HasTransparentScope)
            {
                return(base.VisitMemberAccess(m));
            }

            ParameterExpression  innerParamRef  = null;
            Stack <PropertyInfo> nestedAccesses = new Stack <PropertyInfo>();
            MemberExpression     memberRef      = m;

            while (memberRef != null &&
                   PlatformHelper.IsProperty(memberRef.Member) &&
                   memberRef.Expression != null)
            {
                nestedAccesses.Push((PropertyInfo)memberRef.Member);

                if (memberRef.Expression.NodeType == ExpressionType.Parameter)
                {
                    innerParamRef = (ParameterExpression)memberRef.Expression;
                }

                memberRef = memberRef.Expression as MemberExpression;
            }

            // Only continue if the inner non-MemberExpression is the input reference ParameterExpression and
            // at least one property reference is present - otherwise this cannot be a transparent scope access.
            if (innerParamRef != this.inputParameter || nestedAccesses.Count == 0)
            {
                return(m);
            }

            ResourceExpression          target         = this.input;
            QueryableResourceExpression targetResource = this.inputResource;
            bool transparentScopeTraversed             = false;

            // Process all the traversals through transparent scopes.
            while (nestedAccesses.Count > 0)
            {
                if (targetResource == null || !targetResource.HasTransparentScope)
                {
                    break;
                }

                // Peek the property; pop it once it's consumed
                // (it could be a non-transparent-identifier access).
                PropertyInfo currentProp = nestedAccesses.Peek();

                // If this is the accessor for the target, then the member
                // refers to the target itself.
                if (currentProp.Name.Equals(targetResource.TransparentScope.Accessor, StringComparison.Ordinal))
                {
                    target = targetResource;
                    nestedAccesses.Pop();
                    transparentScopeTraversed = true;
                    continue;
                }

                // This member could also be one of the in-scope sources of the target.
                Expression source;
                if (!targetResource.TransparentScope.SourceAccessors.TryGetValue(currentProp.Name, out source))
                {
                    break;
                }

                transparentScopeTraversed = true;
                nestedAccesses.Pop();
                Debug.Assert(source != null, "source != null -- otherwise ResourceBinder created an accessor to nowhere");
                InputReferenceExpression sourceReference = source as InputReferenceExpression;
                if (sourceReference == null)
                {
                    targetResource = source as QueryableResourceExpression;
                    if (targetResource == null || !targetResource.HasTransparentScope)
                    {
                        target = (ResourceExpression)source;
                    }
                }
                else
                {
                    targetResource = sourceReference.Target as QueryableResourceExpression;
                    target         = targetResource;
                }
            }

            // If no traversals were made, the original expression is OK.
            if (!transparentScopeTraversed)
            {
                return(m);
            }

            // Process traversals after the transparent scope.
            Expression result = this.CreateReference(target);

            while (nestedAccesses.Count > 0)
            {
                result = Expression.Property(result, nestedAccesses.Pop());
            }

            return(result);
        }
        public void Preprocess(List <XmlAttribute> expressionAttributes, List <Resource> resources, List <IdViewObject> viewElements)
        {
            // Create all properties for viewElements
            foreach (IdViewObject viewElement in viewElements)
            {
                Tuple <CodeMemberField, CodeMemberProperty> result = CodeGeneratorHelper.GenerateProxyProperty(viewElement.Id, viewElement.TypeName, new CodeMethodInvokeExpression(GetFindViewByIdReference(viewElement.TypeName), CodeGeneratorHelper.GetAndroidResourceReference(ResourcePart.Id, viewElement.Id)));
                Fields.Add(result.Item1);
                Properties.Add(result.Item2);
            }

            // Generate property for ILocalizationService LocalizationService
            CodePropertyReferenceExpression localizationServiceReference = CreateLocalizationServiceProperty();

            // Eval all expressions
            List <ExpressionContainer> expressions = (from attribute in expressionAttributes
                                                      let expressionResult = EvaluateExpression(attribute.Value)
                                                                             where expressionResult != null
                                                                             select new ExpressionContainer
            {
                Expression = expressionResult,
                TargetObject = attribute.AttachedId,
                TargetField = attribute.LocalName,
                IsTargetingResource = false,
            }).ToList();

            // Affect a property name to all resources and check if some has expression as attribute value
            foreach (Resource res in resources)
            {
                res.PropertyName = NameGeneratorHelper.GetResourceName();
                foreach (KeyValuePair <string, string> propertyItem in res.Properties.Where(propertyItem => ParsingHelper.IsExpressionValue(propertyItem.Value)).ToList())
                {
                    res.Properties.Remove(propertyItem.Key);

                    Expression expr = EvaluateExpression(propertyItem.Value);
                    if (expr != null)
                    {
                        if (CheckCorrectExpressionInResource(expr))
                        {
                            Log.LogError("Expression {0} is invalid in a resource context (you cannot use binding)", propertyItem.Value);
                        }
                        else
                        {
                            expressions.Add(new ExpressionContainer
                            {
                                Expression          = expr,
                                TargetObject        = res.PropertyName,
                                TargetField         = propertyItem.Key,
                                IsTargetingResource = true,
                            });
                        }
                    }
                }
            }

            // Check if all resources are declared and filter those we need
            Dictionary <string, Resource> neededResource = new Dictionary <string, Resource>();
            List <string> resourceKeys = expressions.SelectMany(x => GetUsedResources(x.Expression)).Distinct().ToList();

            foreach (string key in resourceKeys)
            {
                Resource res = resources.FirstOrDefault(x => key.Equals(x.Key, StringComparison.InvariantCultureIgnoreCase));
                if (res == null)
                {
                    Log.LogError("Resource with key {0} does not exists", key);
                }
                else
                {
                    neededResource.Add(key, res);
                }
            }


            // Go through all binding expression and find those where we need to declare implicit resources
            // Will also remove all Template & TemplateSelector fields in BindingExpression
            // to only have a fully prepared adapter
            foreach (Expression bindingExpression in expressions.SelectMany(expression => GetBindingExpressions(expression.Expression)).ToList())
            {
                if (bindingExpression.Has(BindingExpression.TEMPLATE))
                {
                    // create a template selector
                    string templateSelectorKey          = NameGeneratorHelper.GetResourceKey();
                    string templateSelectorPropertyName = NameGeneratorHelper.GetResourceName();
                    neededResource.Add(templateSelectorKey, new Resource(templateSelectorKey)
                    {
                        PropertyName    = templateSelectorPropertyName,
                        ResourceElement = null,
                        Type            = Configuration.DefaultTemplateSelector
                    });
                    expressions.Add(new ExpressionContainer
                    {
                        Expression          = bindingExpression[BindingExpression.TEMPLATE],
                        TargetField         = Configuration.DefaultTemplateSelectorField,
                        TargetObject        = templateSelectorPropertyName,
                        IsTargetingResource = true,
                    });
                    bindingExpression.Remove(BindingExpression.TEMPLATE);

                    ResourceExpression templateSelectorResourceExpression = new ResourceExpression();
                    templateSelectorResourceExpression.Add(ResourceExpression.KEY, new TextExpression
                    {
                        Value = templateSelectorKey
                    });
                    bindingExpression.Add(BindingExpression.TEMPLATE_SELECTOR, templateSelectorResourceExpression);
                }

                if (bindingExpression.Has(BindingExpression.TEMPLATE_SELECTOR))
                {
                    // create an adapter
                    string adapterKey  = NameGeneratorHelper.GetResourceKey();
                    string adapterName = NameGeneratorHelper.GetResourceName();
                    neededResource.Add(adapterKey, new Resource(adapterKey)
                    {
                        PropertyName    = adapterName,
                        ResourceElement = null,
                        Type            = Configuration.DefaultAdapter
                    });
                    expressions.Add(new ExpressionContainer
                    {
                        Expression          = bindingExpression[BindingExpression.TEMPLATE_SELECTOR],
                        TargetField         = Configuration.DefaultAdapterField,
                        TargetObject        = adapterName,
                        IsTargetingResource = true,
                    });
                    bindingExpression.Remove(BindingExpression.TEMPLATE_SELECTOR);
                    ResourceExpression adapterResourceExpression = new ResourceExpression();
                    adapterResourceExpression.Add(ResourceExpression.KEY, new TextExpression
                    {
                        Value = adapterKey
                    });
                    bindingExpression.Add(BindingExpression.ADAPTER, adapterResourceExpression);
                }
            }

            // In order to check if all adapter are not used more than once since we need them to be unique target
            Dictionary <string, bool> usedAdapter = new Dictionary <string, bool>();

            foreach (ExpressionContainer expression in expressions.Where(x => x.Expression.IsOfType(ExpressionType.Binding)).ToList())
            {
                Expression bindingExpression = expression.Expression;
                if (bindingExpression.Has(BindingExpression.ADAPTER))
                {
                    // expression in Adapter could only be Resource (since it's an android platform specific things, a binding expression would not have any sense)
                    Expression resourceExpression = bindingExpression[BindingExpression.ADAPTER];
                    string     adapterKey         = resourceExpression.GetValue(ResourceExpression.KEY);
                    Resource   adapterResource    = neededResource[adapterKey];

                    if (usedAdapter.ContainsKey(adapterKey))
                    {
                        Log.LogError("The adapter with key {0} is used more than once which could lead to issue, you need one adapter per use !", adapterKey);
                    }
                    else
                    {
                        usedAdapter.Add(adapterKey, true);
                    }

                    // remove the adapter property
                    bindingExpression.Remove(BindingExpression.ADAPTER);

                    // store old target info
                    string oldTargetField  = expression.TargetField;
                    string oldTargetObject = expression.TargetObject;
                    bool   oldTargetType   = expression.IsTargetingResource;

                    // retarget the binding expression to be targeted to Adapter.Collection
                    expression.TargetField         = "Collection";
                    expression.TargetObject        = adapterResource.PropertyName;
                    expression.IsTargetingResource = false;                     //TODO : false for debug mode only, need to see what we can do about that ?

                    // add a new expression to target the old object/field couple and affect the adapter with the resource expression
                    expressions.Add(new ExpressionContainer
                    {
                        IsTargetingResource = oldTargetType,
                        TargetField         = oldTargetField,
                        TargetObject        = oldTargetObject,
                        Expression          = resourceExpression,
                    });
                }
            }

            // Create all properties for resources
            Dictionary <string, CodePropertyReferenceExpression> resourceReferences = CreatePropertiesForResources(neededResource.Values);

            // Generate all properties to handle CommandParameter and retarget all expressions if needed
            GenerateCommandParameterProperties(expressions);

            // Create a setup resources method to initalize resources with all {Resource ...} and {Translation ...} expressions
            List <ExpressionContainer> translationExpressions        = expressions.Where(x => x.Expression.IsOfType(ExpressionType.Translation)).ToList();
            List <ExpressionContainer> expressionsTargetingResources = expressions.Where(x => x.IsTargetingResource && x.Expression.IsOfType(ExpressionType.Resource)).ToList();
            List <ExpressionContainer> resourceExpressions           = expressions.Where(x => !x.IsTargetingResource && x.Expression.IsOfType(ExpressionType.Resource)).ToList();
            List <ExpressionContainer> bindingExpressions            = expressions.Where(x => !x.IsTargetingResource && x.Expression.IsOfType(ExpressionType.Binding)).ToList();

            CodeMethodReferenceExpression assignTranslationMethodReference = CreateAssignTranslationMethod(translationExpressions, localizationServiceReference);
            CodeMethodReferenceExpression setupResourcesReference          = CreateSetupResourcesMethod(expressionsTargetingResources, resourceReferences);
            CodeMethodReferenceExpression setupResourceForViewElement      = CreateSetupResourceForViewElementMethod(resourceExpressions, resourceReferences);

            CreateBindingOverrideMethod(bindingExpressions, localizationServiceReference, resourceReferences, assignTranslationMethodReference, setupResourcesReference, setupResourceForViewElement);
        }
Esempio n. 16
0
        /// <summary>
        /// Visit Query options for Resource
        /// </summary>
        /// <param name="re">Resource Expression with query options</param>
        internal void VisitQueryOptions(ResourceExpression re)
        {
            if (re.HasQueryOptions)
            {
                this.uriBuilder.Append(UriHelper.QUESTIONMARK);

                QueryableResourceExpression rse = re as QueryableResourceExpression;
                if (rse != null)
                {
                    IEnumerator options = rse.SequenceQueryOptions.GetEnumerator();
                    while (options.MoveNext())
                    {
                        Expression             e  = ((Expression)options.Current);
                        ResourceExpressionType et = (ResourceExpressionType)e.NodeType;
                        switch (et)
                        {
                        case ResourceExpressionType.SkipQueryOption:
                            this.VisitQueryOptionExpression((SkipQueryOptionExpression)e);
                            break;

                        case ResourceExpressionType.TakeQueryOption:
                            this.VisitQueryOptionExpression((TakeQueryOptionExpression)e);
                            break;

                        case ResourceExpressionType.OrderByQueryOption:
                            this.VisitQueryOptionExpression((OrderByQueryOptionExpression)e);
                            break;

                        case ResourceExpressionType.FilterQueryOption:
                            this.VisitQueryOptionExpression((FilterQueryOptionExpression)e);
                            break;

                        case ResourceExpressionType.ApplyQueryOption:
                            this.VisitQueryOptionExpression((ApplyQueryOptionExpression)e);
                            break;

                        default:
                            Debug.Assert(false, "Unexpected expression type " + ((int)et).ToString(CultureInfo.InvariantCulture));
                            break;
                        }
                    }
                }

                if (re.ExpandPaths.Count > 0)
                {
                    this.VisitExpandOptions(re.ExpandPaths);
                }

                if (re.Projection != null && re.Projection.Paths.Count > 0)
                {
                    this.VisitProjectionPaths(re.Projection.Paths);
                }

                if (re.CountOption == CountOption.CountQueryTrue)
                {
                    this.VisitCountQueryOptions(true);
                }

                if (re.CountOption == CountOption.CountQueryFalse)
                {
                    this.VisitCountQueryOptions(false);
                }

                if (re.CustomQueryOptions.Count > 0)
                {
                    this.VisitCustomQueryOptions(re.CustomQueryOptions);
                }

                this.AppendCachedQueryOptionsToUriBuilder();
            }
        }
        /// <summary>
        /// Populates the analyser type for column.
        /// </summary>
        /// <param name="report">The report.</param>
        /// <param name="entityType">The resource type returned if the analyser refers to a resource expression.</param>
        /// <param name="reportExpression">The report expression.</param>
        /// <param name="reportAnalyserColumn">The report analyser column.</param>
        private static void PopulateAnalyserTypeForColumn(Report report, EntityType entityType, ReportExpression reportExpression, ReportAnalyserColumn reportAnalyserColumn)
        {
            reportAnalyserColumn.AnalyserType = reportAnalyserColumn.Type.GetDisplayName();

            if (reportExpression.Is <StructureViewExpression>())
            {
                reportAnalyserColumn.AnalyserType    = StructureLevelsType.DisplayName;
                reportAnalyserColumn.DefaultOperator = Structured.ConditionType.AnyBelowStructureLevel;
                var expression    = reportExpression.As <StructureViewExpression>();
                var resReportNode = expression.StructureViewExpressionSourceNode.As <ResourceReportNode>();
                var eType         = resReportNode.ResourceReportNodeType;
                reportAnalyserColumn.TypeId = eType.Id;
                return;
            }

            if (!reportExpression.Is <NodeExpression>())
            {
                return;
            }

            NodeExpression nodeExpression = reportExpression.As <NodeExpression>();

            if (!nodeExpression.SourceNode.Is <ResourceReportNode>())
            {
                return;
            }

            bool isNameColumnForType = false;

            if (reportExpression.Is <FieldExpression>())
            {
                var fieldExpression = reportExpression.As <FieldExpression>();
                if (fieldExpression.FieldExpressionField.Alias != "core:name")
                {
                    return;
                }
                long sourceId = fieldExpression.SourceNode != null ? fieldExpression.SourceNode.Id : 0;
                long rootId   = report.RootNode != null ? report.RootNode.Id : 0;
                isNameColumnForType = (sourceId == rootId) && (sourceId != 0);
            }
            reportAnalyserColumn.IsNameColumnForType = isNameColumnForType;

            ResourceReportNode     resourceReportNode     = nodeExpression.SourceNode.As <ResourceReportNode>( );
            RelationshipReportNode relationshipReportNode = nodeExpression.SourceNode.As <RelationshipReportNode>( );

            if (entityType == null)
            {
                // Need to be able accept entityType as an argument, e.g. if it is from a script column
                // But also need to be able to read it from the node, e.g. if it is the root name column. Messed up.
                entityType = resourceReportNode.ResourceReportNodeType;
                if (entityType == null)
                {
                    return;
                }
            }

            ResourceExpression resourceExpression = reportExpression.As <ResourceExpression>();

            // Handle "Type" types
            //if the resource type is "Type", add current parent node type and descendant types' id as filtered entity ids (bug 24859)
            //Update: only the forward relationship is "isOfType", the "type" list will be restricted. (bug 27862)
            if (entityType.Alias == "core:type" &&
                relationshipReportNode?.FollowRelationship?.Alias == "core:isOfType"
                )
            {
                AggregateReportNode parentAggregatedNode     = resourceReportNode.ParentAggregatedNode;
                ReportNode          parentReportNode         = parentAggregatedNode != null ? parentAggregatedNode.GroupedNode : resourceReportNode.ParentReportNode;
                ResourceReportNode  parentResourceReportNode = parentReportNode != null?parentReportNode.As <ResourceReportNode>() : null;

                if (parentResourceReportNode != null && parentResourceReportNode.ResourceReportNodeType != null)
                {
                    reportAnalyserColumn.FilteredEntityIds = PerTenantEntityTypeCache.Instance.GetDescendantsAndSelf(
                        parentResourceReportNode.ResourceReportNodeType.Id).ToArray();
                }
            }

            // Handle "User" and "Person" types
            if (PerTenantEntityTypeCache.Instance.IsDerivedFrom(entityType.Id, "core:person") ||
                PerTenantEntityTypeCache.Instance.IsDerivedFrom(entityType.Id, "core:userAccount"))
            {
                // If this is a relationship or calc then make it as a user inline relationship otherwise a simple user string.
                reportAnalyserColumn.AnalyserType = nodeExpression.SourceNode.Is <FieldExpression>( ) ? "UserString" : "UserInlineRelationship";
                return;
            }

            // Treat the root 'Name' column like a lookup, so we get the 'Any Of', 'Any Except' options.
            if (isNameColumnForType)
            {
                reportAnalyserColumn.AnalyserType = "InlineRelationship";
                reportAnalyserColumn.TypeId       = entityType.Id;
            }
        }
Esempio n. 18
0
 /// <summary>
 /// Returns an <see cref="InputReferenceExpression"/> that references the specified resource,
 /// and also adds the the resource to the hashset of resources that were referenced by the
 /// expression that is being rebound.
 /// </summary>
 /// <param name="resource">The resource for which a reference was found</param>
 /// <returns>An InputReferenceExpression that represents a reference to the specified resource</returns>
 private Expression CreateReference(ResourceExpression resource)
 {
     this.referencedInputs.Add(resource);
     return(resource.CreateReference());
 }
Esempio n. 19
0
 /// <summary>
 /// Constructs a new InputBinder based on the specified input resources, which is represented by the specified ParameterExpression.
 /// </summary>
 /// <param name="resource">The current input resource from which valid references must start</param>
 /// <param name="setReferenceParam">The parameter that must be referenced in order to refer to the specified input resources</param>
 private InputBinder(ResourceExpression resource, ParameterExpression setReferenceParam)
 {
     this.input          = resource;
     this.inputResource  = resource as QueryableResourceExpression;
     this.inputParameter = setReferenceParam;
 }
Esempio n. 20
0
        /// <summary>
        /// TODO: Refactor
        /// </summary>
        internal static void CaptureMetadata(StructuredQuery query, QuerySettings settings, QueryResult result, DataTable dataTable)
        {
            if (settings.SupportClientAggregate)
            {
                int totalGroupedColumns = settings.ClientAggregate.GroupedColumns?.Count ?? 0;

                int totalColumns = totalGroupedColumns + settings.ClientAggregate.AggregatedColumns.Count;

                for (int index = 0; index < totalColumns; index++)
                {
                    int        columnIndex;
                    DataColumn tableColumn = dataTable.Columns[index];
                    if (index < totalGroupedColumns)
                    {
                        columnIndex = index;
                        if (settings.ClientAggregate.GroupedColumns != null)
                        {
                            tableColumn.ExtendedProperties["ColumnId"] = settings.ClientAggregate.GroupedColumns[columnIndex].ReportColumnId;
                        }
                    }
                    else
                    {
                        columnIndex = index - totalGroupedColumns;
                        if (settings.ClientAggregate.AggregatedColumns != null)
                        {
                            tableColumn.ExtendedProperties["ColumnId"] = settings.ClientAggregate.AggregatedColumns[columnIndex].ReportColumnId;
                        }
                    }
                    tableColumn.ExtendedProperties["ColumnIndex"] = columnIndex;
                }

                result.AggregateDataTable = dataTable;
            }
            else
            {
                int index = 0;
                foreach (SelectColumn selectColumn in query.SelectColumns)
                {
                    // Set column ID into data table column object (why??)
                    DataColumn tableColumn = dataTable.Columns[index];
                    tableColumn.ExtendedProperties["ColumnId"] = selectColumn.ColumnId;
                    // Set data type into result column info, for columns (e.g. calculated) where we can only determine it dynamically at the moment
                    ResultColumn resultColumn = result.Columns[index];
                    if (resultColumn.ColumnType == null)
                    {
                        if (selectColumn.Expression is AggregateExpression && ((AggregateExpression)selectColumn.Expression).Expression is ResourceExpression)
                        {
                            if (((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.Count ||
                                ((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.CountUniqueItems ||
                                ((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.CountUniqueNotBlanks ||
                                ((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.CountWithValues)
                            {
                                resultColumn.ColumnType = new EDC.Database.Types.Int32Type();
                            }
                            else
                            {
                                resultColumn.ColumnType = ((ResourceExpression)((AggregateExpression)selectColumn.Expression).Expression).CastType;
                                resultColumn.IsResource = true;
                                if (resultColumn.ColumnType == null)
                                {
                                    resultColumn.ColumnType = new EDC.Database.Types.ChoiceRelationshipType();
                                }
                            }
                        }
                        else if (selectColumn.Expression is AggregateExpression && ((AggregateExpression)selectColumn.Expression).Expression is ResourceDataColumn)
                        {
                            if (((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.Count ||
                                ((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.CountUniqueItems ||
                                ((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.CountUniqueNotBlanks ||
                                ((AggregateExpression)selectColumn.Expression).AggregateMethod == AggregateMethod.CountWithValues)
                            {
                                resultColumn.ColumnType = new EDC.Database.Types.Int32Type();
                            }
                            else
                            {
                                resultColumn.ColumnType = ((ResourceDataColumn)((AggregateExpression)selectColumn.Expression).Expression).CastType;
                                //resultColumn.IsResource = true;
                            }
                        }
                        else if (selectColumn.Expression is StructureViewExpression)
                        {
                            resultColumn.ColumnType = new EDC.Database.Types.StructureLevelsType();
                        }
                        else
                        {
                            ResourceExpression resourceExpression = selectColumn.Expression as ResourceExpression;
                            if (resourceExpression != null)
                            {
                                resultColumn.ColumnType = resourceExpression.CastType;
                                resultColumn.IsResource = true;
                            }
                            else
                            {
                                resultColumn.ColumnType = DatabaseType.ConvertFromType(tableColumn.DataType);
                            }
                        }
                    }

                    index++;
                }
                result.DataTable = dataTable;
            }
        }