/// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection to check whether a property is not empty
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder PropertyNotEmpty
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // Add the search condition.
            return(searchBuilder.AddPropertyValueSearchCondition
                   (
                       propertyDef,
                       dataType,
                       null,
                       MFConditionType.MFConditionTypeNotEqual,
                       parentChildBehavior,
                       indirectionLevels,
                       null
                   ));
        }
        /// <inherit />
        protected override void AddSearchCondition
        (
            MFSearchBuilder mfSearchBuilder,
            int propertyDef,
            DateTime?value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            DataFunctionCall dataFunctionCall          = null,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == mfSearchBuilder)
            {
                throw new ArgumentNullException(nameof(mfSearchBuilder));
            }

            // Call the property overload.
            mfSearchBuilder.Date
            (
                propertyDef,
                // Value is not nullable in the real world, but needed here for the test to work.
                value ?? new DateTime(2020, 01, 01),
                conditionType,
                parentChildBehavior,
                indirectionLevels
            );
        }
        /// <inherit />
        protected override void AddSearchCondition
        (
            MFSearchBuilder mfSearchBuilder,
            int propertyDef,
            string value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            DataFunctionCall dataFunctionCall          = null,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == mfSearchBuilder)
            {
                throw new ArgumentNullException(nameof(mfSearchBuilder));
            }

            // Call the property overload.
            mfSearchBuilder.YearAndMonth
            (
                propertyDef,
                2020,
                1,
                conditionType,
                parentChildBehavior,
                indirectionLevels
            );
        }
Beispiel #4
0
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection for a <see cref="MFDataType.MFDatatypeDate"/>
        /// or <see cref="MFDataType.MFDatatypeTimestamp"/> property definition.
        /// This method searches solely by the month component in the property value , equivalent to using
        /// a <see cref="DataFunctionCall" /> set to <see cref="DataFunctionCall.SetDataMonth" />.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="month">The 1-based number of the month to search by (1 = January, 12 = December).</param>
        /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder Month
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            int month,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }
            if (month < 1 || month > 12)
            {
                throw new ArgumentOutOfRangeException(nameof(month), "The month number must be between 1 and 12 inclusive.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // What is the data type of the property?
            DataFunctionCall dataFunctionCall;

            switch (dataType)
            {
            case MFDataType.MFDatatypeTimestamp:
            case MFDataType.MFDatatypeDate:

                // Timestamps and dates should be converted to text using a data function call.
                dataFunctionCall = new DataFunctionCall();
                dataFunctionCall.SetDataMonth();

                break;

            default:
                throw new ArgumentException($"Property {propertyDef} is not a date or timestamp property.", nameof(propertyDef));
            }

            // Use the property method.
            return(searchBuilder.Property
                   (
                       propertyDef,
                       month.ToString("00"),
                       conditionType,
                       parentChildBehavior,
                       indirectionLevels,
                       dataFunctionCall
                   ));
        }
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection for a <see cref="MFDataType.MFDatatypeDate"/>
        /// or <see cref="MFDataType.MFDatatypeTimestamp"/> property definition.
        /// This method searches solely by the year component in the property value , equivalent to using
        /// a <see cref="DataFunctionCall" /> set to <see cref="DataFunctionCall.SetDataYear"/>.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="year">The four-digit year to search by.</param>
        /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder Year
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            int year,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }
            if (year < 1000 || year > 9999)
            {
                throw new ArgumentOutOfRangeException(nameof(year), "The year must be four digits.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // What is the data type of the property?
            DataFunctionCall dataFunctionCall;

            switch (dataType)
            {
            case MFDataType.MFDatatypeTimestamp:
            case MFDataType.MFDatatypeDate:

                // Timestamps and dates should be converted to integer using a data function call.
                dataFunctionCall = new DataFunctionCall();
                dataFunctionCall.SetDataYear();

                break;

            default:
                throw new ArgumentException($"Property {propertyDef} is not a date or timestamp property.", nameof(propertyDef));
            }

            // Use the property method.
            return(searchBuilder.Property
                   (
                       propertyDef,
                       year,
                       conditionType,
                       parentChildBehavior,
                       indirectionLevels,
                       dataFunctionCall
                   ));
        }
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection for a <see cref="MFDataType.MFDatatypeInteger"/>,
        /// <see cref="MFDataType.MFDatatypeInteger64"/> or <see cref="MFDataType.MFDatatypeFloating"/> property definition.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="value">The value to search for.</param>
        /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="dataFunctionCall">An expression for modifying how the results of matches are evaluated (defaults to null).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder Property
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            long?value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null,
            DataFunctionCall dataFunctionCall          = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // If it is not valid then throw.
            if (dataType != MFDataType.MFDatatypeInteger &&
                dataType != MFDataType.MFDatatypeInteger64 &&
                dataType != MFDataType.MFDatatypeFloating &&
                dataType != MFDataType.MFDatatypeLookup &&
                dataType != MFDataType.MFDatatypeMultiSelectLookup)
            {
                throw new ArgumentException($"Property {propertyDef} is not an integer, long, real, lookup or multi-select lookup property.", nameof(propertyDef));
            }

            // Add the search condition.
            return(searchBuilder.AddPropertyValueSearchCondition
                   (
                       propertyDef,
                       dataType,
                       value,
                       conditionType,
                       parentChildBehavior,
                       indirectionLevels,
                       dataFunctionCall
                   ));
        }
 /// <summary>
 /// Adds a <see cref="SearchCondition"/> to the collection to represent a "one of" search condition (https://developer.m-files.com/APIs/COM-API/Searching/SearchConditions/#executing-a-one-of-search).
 /// </summary>
 /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
 /// <param name="propertyDef">The ID of the property to search by.</param>
 /// <param name="lookups">The items to search for (the object must have the property set to one of these).</param>
 /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
 /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
 /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
 public static MFSearchBuilder PropertyOneOf
 (
     this MFSearchBuilder searchBuilder,
     int propertyDef,
     IEnumerable <Lookup> lookups,
     MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
     PropertyDefOrObjectTypes indirectionLevels = null
 )
 {
     // Use the other overload.
     return(searchBuilder?.PropertyOneOf
            (
                propertyDef,
                lookups?.Select(lookup => lookup.Item),
                parentChildBehavior,
                indirectionLevels
            ));
 }
 /// <summary>
 /// Adds a <see cref="SearchCondition"/> to the collection to represent a "one of" search condition (https://developer.m-files.com/APIs/COM-API/Searching/SearchConditions/#executing-a-one-of-search).
 /// </summary>
 /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
 /// <param name="propertyDef">The ID of the property to search by.</param>
 /// <param name="objects">The items to search for (the object must have the property set to one of these).</param>
 /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
 /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
 /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
 public static MFSearchBuilder PropertyOneOf
 (
     this MFSearchBuilder searchBuilder,
     int propertyDef,
     IEnumerable <ObjVerEx> objects,
     MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
     PropertyDefOrObjectTypes indirectionLevels = null
 )
 {
     // Use the other overload.
     return(searchBuilder.PropertyOneOf
            (
                propertyDef,
                objects?.Where(o => o != null)?.Select(objVerEx => objVerEx.ID),
                parentChildBehavior,
                indirectionLevels
            ));
 }
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection to represent a "one of" search condition (https://developer.m-files.com/APIs/COM-API/Searching/SearchConditions/#executing-a-one-of-search).
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="lookupIds">The ids to search for (the object must have the property set to one of these IDs).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder PropertyOneOf
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            IEnumerable <int> lookupIds,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }
            if (null == lookupIds || false == lookupIds.Any())
            {
                throw new ArgumentException("The lookup collection does not contain any items.", nameof(lookupIds));
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // If it is not valid then throw.
            if (dataType != MFDataType.MFDatatypeLookup && dataType != MFDataType.MFDatatypeMultiSelectLookup)
            {
                throw new ArgumentException($"Property {propertyDef} is not a lookup or multi-select lookup property.", nameof(propertyDef));
            }

            // Add the search condition.
            return(searchBuilder.AddPropertyValueSearchCondition
                   (
                       propertyDef,
                       MFDataType.MFDatatypeMultiSelectLookup,
                       lookupIds.ToArray(),
                       MFConditionType.MFConditionTypeEqual,
                       parentChildBehavior,
                       indirectionLevels
                   ));
        }
 public void SearchConditionIsCorrect
 (
     int propertyDef,
     DateTime?input,
     MFConditionType conditionType,
     MFParentChildBehavior parentChildBehavior,
     PropertyDefOrObjectTypes indirectionLevels
 )
 {
     base.AssertSearchConditionIsCorrect
     (
         propertyDef,
         MFDataType.MFDatatypeDate,
         input,
         conditionType,
         parentChildBehavior,
         indirectionLevels
     );
 }
Beispiel #11
0
 public void SearchConditionIsCorrect_WithIndirectionLevels
 (
     int propertyDef,
     long?input,
     MFConditionType conditionType,
     MFParentChildBehavior parentChildBehavior,
     PropertyDefOrObjectTypes indirectionLevels
 )
 {
     base.AssertSearchConditionIsCorrect
     (
         propertyDef,
         MFDataType.MFDatatypeInteger64,
         input,
         conditionType,
         parentChildBehavior,
         indirectionLevels
     );
 }
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection to represent a "one of" search condition (https://developer.m-files.com/APIs/COM-API/Searching/SearchConditions/#executing-a-one-of-search).
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="identifiers">The items to search for (the object must have the property set to one of these).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder PropertyOneOf
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            IEnumerable <MFIdentifier> identifiers,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Use the other overload.
            return(searchBuilder?.PropertyOneOf
                   (
                       propertyDef,
                       identifiers?
                       .Where(i => i != null)
                       .Select(identifier =>
            {
                // Ensure that we're resolved.
                try
                {
                    // If we have to resolve it and have no vault reference then die.
                    if (false == identifier.IsResolved)
                    {
                        if (null == searchBuilder?.Vault)
                        {
                            throw new InvalidOperationException($"The search builder or vault reference is null, so the identifier with alias/GUID {identifier.Alias} cannot be resolved.");
                        }
                    }

                    // Resolve if needed.
                    return identifier
                    .Resolve(searchBuilder?.Vault, typeof(PropertyDef))
                    .ID;
                }
                catch (Exception e)
                {
                    throw new Exception($"Could not resolve the identifier with alias/GUID {identifier.Alias} in the current vault", e);
                }
            }),
                       parentChildBehavior,
                       indirectionLevels
                   ));
        }
Beispiel #13
0
        /// <inherit />
        protected override void AddSearchCondition
        (
            MFSearchBuilder mfSearchBuilder,
            int propertyDef,
            int[] value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            DataFunctionCall dataFunctionCall          = null,
            PropertyDefOrObjectTypes indirectionLevels = null
        )
        {
            // Sanity.
            if (null == mfSearchBuilder)
            {
                throw new ArgumentNullException(nameof(mfSearchBuilder));
            }

            // Use our extension method.
            mfSearchBuilder.PropertyOneOf(propertyDef, value, parentChildBehavior, indirectionLevels);
        }
Beispiel #14
0
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection for a <see cref="MFDataType.MFDatatypeDate"/>
        /// or <see cref="MFDataType.MFDatatypeTimestamp"/> property definition.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="value">The value to search for.</param>
        /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="dataFunctionCall">An expression for modifying how the results of matches are evaluated (defaults to null).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder Property
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            DateTime?value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null,
            DataFunctionCall dataFunctionCall          = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // Do we need to change the data type for the data function call?
            if (dataFunctionCall != null)
            {
                switch (dataFunctionCall.DataFunction)
                {
                case MFDataFunction.MFDataFunctionDate:
                    // If it's a timestamp then convert to date.
                    if (dataType == MFDataType.MFDatatypeTimestamp)
                    {
                        dataType = MFDataType.MFDatatypeDate;
                    }
                    break;
                }
            }

            // If it is not valid then throw.
            if (dataType != MFDataType.MFDatatypeDate &&
                dataType != MFDataType.MFDatatypeTimestamp)
            {
                throw new ArgumentException($"Property {propertyDef} is not a date or timestamp property.", nameof(propertyDef));
            }

            //// If it's a date and the value has a time component then strip it.
            if (dataType == MFDataType.MFDatatypeDate)
            {
                value = value?.Date;
            }

            // Add the search condition.
            return(searchBuilder.AddPropertyValueSearchCondition
                   (
                       propertyDef,
                       dataType,
                       value,
                       conditionType,
                       parentChildBehavior,
                       indirectionLevels,
                       dataFunctionCall
                   ));
        }
 public void SetTypedValueExpression(MFDataType DataType, int ValueList, MFParentChildBehavior PCBehaviour, DataFunctionCall DataFunctionCall = null)
 {
     throw new NotImplementedException();
 }
 public void SetValueListItemExpression(MFValueListItemPropertyDef PseudoPropertyDef, MFParentChildBehavior PCBehaviour, DataFunctionCall DataFunctionCall = null)
 {
     throw new NotImplementedException();
 }
Beispiel #17
0
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection for a <see cref="MFDataType.MFDatatypeText"/>
        /// or <see cref="MFDataType.MFDatatypeMultiLineText"/> property definition.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="value">The value to search for.</param>
        /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="dataFunctionCall">An expression for modifying how the results of matches are evaluated (defaults to null).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder Property
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            string value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null,
            DataFunctionCall dataFunctionCall          = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // Do we need to change the data type for the data function call?
            if (dataFunctionCall != null)
            {
                switch (dataFunctionCall.DataFunction)
                {
                case MFDataFunction.MFDataFunctionMonth:
                {
                    // If it's a timestamp or date then convert to text.
                    if (dataType == MFDataType.MFDatatypeTimestamp ||
                        dataType == MFDataType.MFDatatypeDate)
                    {
                        dataType = MFDataType.MFDatatypeText;
                    }

                    // Validate the value.
                    if (value?.Length != 2)
                    {
                        throw new ArgumentException
                              (
                                  $"The value {value} should contain a two-digit month number (e.g. '03').",
                                  nameof(value)
                              );
                    }

                    // Is it an integer?
                    if (false == Int32.TryParse(value, out int month))
                    {
                        throw new ArgumentException
                              (
                                  $"The value {value} should contain a two-digit month number (e.g. '03').",
                                  nameof(value)
                              );
                    }

                    // Validate the month.
                    if (month <= 0 || month > 12)
                    {
                        throw new ArgumentException
                              (
                                  $"The month value {month} should be between 1 and 12.",
                                  nameof(value)
                              );
                    }
                }
                break;

                case MFDataFunction.MFDataFunctionYearAndMonth:
                {
                    // If it's a timestamp or date then convert to text.
                    if (dataType == MFDataType.MFDatatypeTimestamp ||
                        dataType == MFDataType.MFDatatypeDate)
                    {
                        dataType = MFDataType.MFDatatypeText;
                    }

                    // Also, validate the value.
                    var splitValue = (value ?? "").Split("-".ToCharArray());
                    if (splitValue.Length != 2 ||
                        splitValue[0].Length != 4 ||
                        splitValue[1].Length != 2)
                    {
                        throw new ArgumentException
                              (
                                  $"The value {value} is not of the expected format (YYYY-MM).",
                                  nameof(value)
                              );
                    }

                    // Is it a valid set of integers?
                    {
                        if (false == Int32.TryParse(splitValue[0], out _) ||
                            false == Int32.TryParse(splitValue[1], out int month))
                        {
                            throw new ArgumentException
                                  (
                                      $"The value {value} is not of the expected format (YYYY-MM).",
                                      nameof(value)
                                  );
                        }

                        // Validate the month.
                        if (month <= 0 || month > 12)
                        {
                            throw new ArgumentException
                                  (
                                      $"The month value {month} should be between 1 and 12.",
                                      nameof(value)
                                  );
                        }
                    }
                }
                break;
                }
            }

            // If it is not okay then throw.
            if (dataType != MFDataType.MFDatatypeText &&
                dataType != MFDataType.MFDatatypeMultiLineText)
            {
                throw new ArgumentException($"Property {propertyDef} is not a text property.", nameof(propertyDef));
            }

            // Add the search condition.
            return(searchBuilder.AddPropertyValueSearchCondition
                   (
                       propertyDef,
                       dataType,
                       value,
                       conditionType,
                       parentChildBehavior,
                       indirectionLevels,
                       dataFunctionCall
                   ));
        }
        /// <summary>
        /// Adds a <see cref="SearchCondition"/> to the collection for a <see cref="MFDataType.MFDatatypeInteger"/>,
        /// <see cref="MFDataType.MFDatatypeInteger64"/> or <see cref="MFDataType.MFDatatypeFloating"/> property definition.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The ID of the property to search by.</param>
        /// <param name="value">The value to search for.</param>
        /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well (defaults to <see cref="MFParentChildBehavior.MFParentChildBehaviorNone"/>).</param>
        /// <param name="dataFunctionCall">An expression for modifying how the results of matches are evaluated (defaults to null).</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns>
        public static MFSearchBuilder Property
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            int?value,
            MFConditionType conditionType              = MFConditionType.MFConditionTypeEqual,
            MFParentChildBehavior parentChildBehavior  = MFParentChildBehavior.MFParentChildBehaviorNone,
            PropertyDefOrObjectTypes indirectionLevels = null,
            DataFunctionCall dataFunctionCall          = null
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }
            if (0 > propertyDef)
            {
                throw new ArgumentOutOfRangeException(nameof(propertyDef), "Property Ids must be greater than -1; ensure that your property alias was resolved.");
            }

            // What is the type of this property?
            var dataType = searchBuilder.Vault.PropertyDefOperations.GetPropertyDef(propertyDef).DataType;

            // Do we need to change the data type for the data function call?
            if (dataFunctionCall != null)
            {
                switch (dataFunctionCall.DataFunction)
                {
                case MFDataFunction.MFDataFunctionDaysFrom:
                case MFDataFunction.MFDataFunctionDaysTo:
                case MFDataFunction.MFDataFunctionYear:
                {
                    // If it's a timestamp then convert to integer.
                    if (dataType == MFDataType.MFDatatypeDate ||
                        dataType == MFDataType.MFDatatypeTimestamp)
                    {
                        dataType = MFDataType.MFDatatypeInteger;
                    }

                    // Ensure value has a value.
                    if (null == value)
                    {
                        throw new ArgumentException($"value cannot be null.", nameof(value));
                    }

                    // If it's a year then it should be four-digits.
                    if (dataFunctionCall.DataFunction == MFDataFunction.MFDataFunctionYear &&
                        (value < 1000 || value > 9999))
                    {
                        throw new ArgumentException($"The year must be four digits.", nameof(value));
                    }

                    break;
                }
                }
            }

            // If it is not the right data type then throw.
            if (dataType != MFDataType.MFDatatypeInteger &&
                dataType != MFDataType.MFDatatypeInteger64 &&
                dataType != MFDataType.MFDatatypeFloating &&
                dataType != MFDataType.MFDatatypeLookup &&
                dataType != MFDataType.MFDatatypeMultiSelectLookup)
            {
                throw new ArgumentException($"Property {propertyDef} is not an integer, long, real, lookup or multi-select lookup property.", nameof(propertyDef));
            }

            // Add the search condition.
            return(searchBuilder.AddPropertyValueSearchCondition
                   (
                       propertyDef,
                       dataType,
                       value,
                       conditionType,
                       parentChildBehavior,
                       indirectionLevels,
                       dataFunctionCall
                   ));
        }
 public void SetPropertyValueExpression(int PropertyDef, MFParentChildBehavior PCBehaviour, DataFunctionCall DataFunctionCall = null)
 {
     throw new NotImplementedException();
 }
Beispiel #20
0
        /// <summary>
        /// Adds a property value search condition to the collection.
        /// </summary>
        /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param>
        /// <param name="propertyDef">The property to search by.</param>
        /// <param name="dataType">The data type of the property definition (not checked).</param>
        /// <param name="value">The value to search for.</param>
        /// <param name="conditionType">What type of search to execute.</param>
        /// <param name="parentChildBehavior">Whether to accept matches to parent/child values as well.</param>
        /// <param name="dataFunctionCall">An expression for modifying how the results of matches are evaluated.</param>
        /// <param name="indirectionLevels">The indirection levels (from the search object) to access the property to match.</param>
        /// <returns></returns>
        private static MFSearchBuilder AddPropertyValueSearchCondition
        (
            this MFSearchBuilder searchBuilder,
            int propertyDef,
            MFDataType dataType,
            object value,
            MFConditionType conditionType,
            MFParentChildBehavior parentChildBehavior,
            PropertyDefOrObjectTypes indirectionLevels,
            DataFunctionCall dataFunctionCall
        )
        {
            // Sanity.
            if (null == searchBuilder)
            {
                throw new ArgumentNullException(nameof(searchBuilder));
            }

            // Create the search condition.
            var searchCondition = new SearchCondition
            {
                ConditionType = conditionType
            };

            // Set up the property value expression.
            searchCondition.Expression.SetPropertyValueExpression
            (
                propertyDef,
                parentChildBehavior,
                dataFunctionCall
            );

            // If we have any indirection levels then use them.
            if (null != indirectionLevels)
            {
                // If any indirection level points at a value list then it will except.
                // Show a nicer error message here.
                foreach (PropertyDefOrObjectType indirectionLevel in indirectionLevels)
                {
                    var objectTypeId = indirectionLevel.ID;
                    if (indirectionLevel.PropertyDef)
                    {
                        // If it's a property def then find the object type.
                        PropertyDef indirectionLevelPropertyDef;
                        try
                        {
                            indirectionLevelPropertyDef = searchBuilder
                                                          .Vault
                                                          .PropertyDefOperations
                                                          .GetPropertyDef(indirectionLevel.ID);
                        }
                        catch
                        {
                            indirectionLevelPropertyDef = null;
                        }

                        // Does it exist?
                        if (null == indirectionLevelPropertyDef)
                        {
                            throw new ArgumentException($"An indirection level references a property definition with ID {indirectionLevel.ID}, but this property definition could not be found.", nameof(indirectionLevel));
                        }

                        // Is it a list-based one?
                        if (false == indirectionLevelPropertyDef.BasedOnValueList)
                        {
                            throw new ArgumentException($"The indirection level for property {indirectionLevel.ID} does not reference a lookup-style property definition.", nameof(indirectionLevel));
                        }

                        // Record the object type id.
                        objectTypeId = indirectionLevelPropertyDef.ValueList;
                    }

                    // Is it an object type (fine) or a value list (not fine)?
                    {
                        ObjType indirectionLevelObjectType;
                        try
                        {
                            indirectionLevelObjectType = searchBuilder
                                                         .Vault
                                                         .ValueListOperations
                                                         .GetValueList(objectTypeId);
                        }
                        catch
                        {
                            indirectionLevelObjectType = null;
                        }

                        // Does it exist?
                        if (null == indirectionLevelObjectType)
                        {
                            throw new ArgumentException($"An indirection level references a value list with ID {objectTypeId}, but this value list could not be found.", nameof(indirectionLevel));
                        }

                        // If it's not a real object type then throw.
                        if (false == indirectionLevelObjectType.RealObjectType)
                        {
                            throw new ArgumentException($"An indirection level references an value list with ID {objectTypeId}, but this list does not refer to an object type (cannot be used with value lists).", nameof(indirectionLevel));
                        }
                    }
                }

                // Set the indirection levels.
                searchCondition.Expression.IndirectionLevels
                    = indirectionLevels;
            }

            // Was the value null?
            if (null == value)
            {
                searchCondition.TypedValue.SetValueToNULL(dataType);
            }
            else
            {
                searchCondition.TypedValue.SetValue(dataType, value);
            }

            // Add the search condition to the collection.
            searchBuilder.Conditions.Add(-1, searchCondition);

            // Return the search builder for chaining.
            return(searchBuilder);
        }