public static Expression EvaluateAttributes(this SCIMComparisonExpression expression, ParameterExpression parameterExpression)
        {
            var schemaAttributeId     = Expression.Property(parameterExpression, "SchemaAttributeId");
            var propertyValueString   = Expression.Property(parameterExpression, "ValueString");
            var propertyValueInteger  = Expression.Property(parameterExpression, "ValueInteger");
            var propertyValueDatetime = Expression.Property(parameterExpression, "ValueDateTime");
            var propertyValueBoolean  = Expression.Property(parameterExpression, "ValueBoolean");
            var propertyValueDecimal  = Expression.Property(parameterExpression, "ValueDecimal");
            var propertyValueBinary   = Expression.Property(parameterExpression, "ValueBinary");
            var comparison            = BuildComparisonExpression(expression, expression.LeftExpression.SchemaAttribute,
                                                                  propertyValueString,
                                                                  propertyValueInteger,
                                                                  propertyValueDatetime,
                                                                  propertyValueBoolean,
                                                                  propertyValueDecimal,
                                                                  propertyValueBinary,
                                                                  parameterExpression);

            return(Expression.And(Expression.Equal(schemaAttributeId, Expression.Constant(expression.LeftExpression.SchemaAttribute.Id)), comparison));
        }
        private static Expression BuildComparisonExpression(
            SCIMComparisonExpression comparisonExpression,
            SCIMSchemaAttribute schemaAttr,
            MemberExpression propertyValueString        = null,
            MemberExpression propertyValueInteger       = null,
            MemberExpression propertyValueDatetime      = null,
            MemberExpression propertyValueBoolean       = null,
            MemberExpression propertyValueDecimal       = null,
            MemberExpression propertyValueBinary        = null,
            ParameterExpression representationParameter = null)
        {
            representationParameter = representationParameter ?? Expression.Parameter(typeof(SCIMRepresentationAttribute), "ra");
            propertyValueString     = propertyValueString ?? Expression.Property(representationParameter, "ValueString");
            propertyValueInteger    = propertyValueInteger ?? Expression.Property(representationParameter, "ValueInteger");
            propertyValueDatetime   = propertyValueDatetime ?? Expression.Property(representationParameter, "ValueDateTime");
            propertyValueBoolean    = propertyValueBoolean ?? Expression.Property(representationParameter, "ValueBoolean");
            propertyValueDecimal    = propertyValueDecimal ?? Expression.Property(representationParameter, "ValueDecimal");
            propertyValueBinary     = propertyValueBinary ?? Expression.Property(representationParameter, "ValueBinary");
            Expression comparison = null;

            switch (comparisonExpression.ComparisonOperator)
            {
            case SCIMComparisonOperators.NE:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.STRING:
                    comparison = NotEqual(propertyValueString, Expression.Constant(comparisonExpression.Value));
                    break;

                case SCIMSchemaAttributeTypes.INTEGER:
                    comparison = NotEqual(propertyValueInteger, Expression.Constant(ParseInt(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    comparison = NotEqual(propertyValueDatetime, Expression.Constant(ParseDateTime(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.BOOLEAN:
                    comparison = NotEqual(propertyValueBoolean, Expression.Constant(ParseBoolean(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DECIMAL:
                    comparison = NotEqual(propertyValueDecimal, Expression.Constant(ParseDecimal(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.BINARY:
                    comparison = NotEqual(propertyValueBinary, Expression.Constant(comparisonExpression.Value));
                    break;
                }
                break;

            case SCIMComparisonOperators.GT:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.INTEGER:
                    comparison = GreaterThan(propertyValueInteger, Expression.Constant(ParseInt(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    comparison = GreaterThan(propertyValueDatetime, Expression.Constant(ParseDateTime(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DECIMAL:
                    comparison = GreaterThan(propertyValueDecimal, Expression.Constant(ParseDecimal(comparisonExpression.Value)));
                    break;
                }
                break;

            case SCIMComparisonOperators.GE:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.INTEGER:
                    comparison = GreaterThanOrEqual(propertyValueInteger, Expression.Constant(ParseInt(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    comparison = GreaterThanOrEqual(propertyValueDatetime, Expression.Constant(ParseDateTime(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DECIMAL:
                    comparison = GreaterThanOrEqual(propertyValueDecimal, Expression.Constant(ParseDecimal(comparisonExpression.Value)));
                    break;
                }
                break;

            case SCIMComparisonOperators.LE:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.INTEGER:
                    comparison = LessThanOrEqual(propertyValueInteger, Expression.Constant(ParseInt(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    comparison = LessThanOrEqual(propertyValueDatetime, Expression.Constant(ParseDateTime(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DECIMAL:
                    comparison = LessThanOrEqual(propertyValueDecimal, Expression.Constant(ParseDecimal(comparisonExpression.Value)));
                    break;
                }
                break;

            case SCIMComparisonOperators.LT:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.INTEGER:
                    comparison = LessThan(propertyValueInteger, Expression.Constant(ParseInt(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    comparison = LessThan(propertyValueDatetime, Expression.Constant(ParseDateTime(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DECIMAL:
                    comparison = LessThan(propertyValueDecimal, Expression.Constant(ParseDecimal(comparisonExpression.Value)));
                    break;
                }
                break;

            case SCIMComparisonOperators.EQ:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.STRING:
                    comparison = Equal(propertyValueString, Expression.Constant(comparisonExpression.Value));
                    break;

                case SCIMSchemaAttributeTypes.INTEGER:
                    comparison = Equal(propertyValueInteger, Expression.Constant(ParseInt(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    comparison = Equal(propertyValueDatetime, Expression.Constant(ParseDateTime(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.BOOLEAN:
                    comparison = Equal(propertyValueBoolean, Expression.Constant(ParseBoolean(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.DECIMAL:
                    comparison = Equal(propertyValueDecimal, Expression.Constant(ParseDecimal(comparisonExpression.Value)));
                    break;

                case SCIMSchemaAttributeTypes.BINARY:
                    comparison = Equal(propertyValueBinary, Expression.Constant(comparisonExpression.Value));
                    break;
                }
                break;

            case SCIMComparisonOperators.SW:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.STRING:
                    var startWith = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
                    comparison = Expression.Call(propertyValueString, startWith, Expression.Constant(comparisonExpression.Value));
                    break;
                }
                break;

            case SCIMComparisonOperators.EW:
                switch (schemaAttr.Type)
                {
                case SCIMSchemaAttributeTypes.STRING:
                    var endWith = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
                    comparison = Expression.Call(propertyValueString, endWith, Expression.Constant(comparisonExpression.Value));
                    break;
                }
                break;

            case SCIMComparisonOperators.CO:
                if (schemaAttr.Type == SCIMSchemaAttributeTypes.STRING)
                {
                    var contains = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                    comparison = Expression.Call(propertyValueString, contains, Expression.Constant(comparisonExpression.Value));
                }
                break;
            }

            return(comparison);
        }
        private static Expression Evaluate(this SCIMComparisonExpression comparisonExpression, ParameterExpression parameterExpression)
        {
            bool isMetadata = false;
            var  lastChild  = comparisonExpression.LeftExpression.GetLastChild();
            var  fullPath   = comparisonExpression.LeftExpression.GetFullPath();
            var  representationParameter = Expression.Parameter(typeof(SCIMRepresentationAttribute), "ra");
            var  propertySchemaAttribute = Expression.Property(representationParameter, "SchemaAttributeId");
            var  propertyValueString     = Expression.Property(representationParameter, "ValueString");
            var  propertyValueInteger    = Expression.Property(representationParameter, "ValueInteger");
            var  propertyValueDatetime   = Expression.Property(representationParameter, "ValueDateTime");
            var  schemaAttr = lastChild.SchemaAttribute;

            if (ParserConstants.MappingStandardAttributePathToProperty.ContainsKey(fullPath))
            {
                isMetadata = true;
                var name = ParserConstants.MappingStandardAttributePathToProperty[fullPath];
                var type = ParserConstants.MappingStandardAttributeTypeToType[fullPath];
                switch (type)
                {
                case SCIMSchemaAttributeTypes.STRING:
                    propertyValueString = Expression.Property(parameterExpression, name);
                    schemaAttr          = new SCIMSchemaAttribute(Guid.NewGuid().ToString())
                    {
                        Type = SCIMSchemaAttributeTypes.STRING
                    };
                    break;

                case SCIMSchemaAttributeTypes.INTEGER:
                    propertyValueInteger = Expression.Property(parameterExpression, name);
                    schemaAttr           = new SCIMSchemaAttribute(Guid.NewGuid().ToString())
                    {
                        Type = SCIMSchemaAttributeTypes.INTEGER
                    };
                    break;

                case SCIMSchemaAttributeTypes.DATETIME:
                    propertyValueDatetime = Expression.Property(parameterExpression, name);
                    schemaAttr            = new SCIMSchemaAttribute(Guid.NewGuid().ToString())
                    {
                        Type = SCIMSchemaAttributeTypes.DATETIME
                    };
                    break;
                }
            }

            var attributes = Expression.Property(parameterExpression, "FlatAttributes");
            var comparison = BuildComparisonExpression(comparisonExpression,
                                                       schemaAttr,
                                                       propertyValueString,
                                                       propertyValueInteger,
                                                       propertyValueDatetime,
                                                       representationParameter: representationParameter);

            if (isMetadata)
            {
                return(comparison);
            }

            var body = Expression.Lambda <Func <SCIMRepresentationAttribute, bool> >(
                Expression.AndAlso(Expression.Equal(propertySchemaAttribute, Expression.Constant(schemaAttr.Id)), comparison),
                representationParameter);
            var anyMethodType = typeof(Enumerable).GetMethods().First(m => m.Name == "Any" && m.GetParameters().Length == 2).MakeGenericMethod(typeof(SCIMRepresentationAttribute));

            return(Expression.Call(anyMethodType, attributes, body));
        }