/// <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 ); }
public void SearchConditionIsCorrect ( int objectId, MFConditionType conditionType ) { // Create the search builder. var mfSearchBuilder = this.GetSearchBuilder(); // Add the search condition. mfSearchBuilder.ObjectId(objectId, conditionType); // If there's anything other than one condition then fail. if (mfSearchBuilder.Conditions.Count != 1) { Assert.Inconclusive("Only one search condition should exist"); } // Retrieve the just-added condition. var condition = mfSearchBuilder.Conditions[mfSearchBuilder.Conditions.Count]; // Ensure the condition type is correct. Assert.AreEqual(conditionType, condition.ConditionType); // Ensure the expression type is correct. Assert.AreEqual(MFExpressionType.MFExpressionTypeStatusValue, condition.Expression.Type); // Ensure the status value is correct. Assert.AreEqual(MFStatusType.MFStatusTypeObjectID, condition.Expression.DataStatusValueType); // Ensure that the typed value is correct. Assert.AreEqual(MFDataType.MFDatatypeInteger, condition.TypedValue.DataType); Assert.AreEqual(objectId, condition.TypedValue.Value as int?); }
/// <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 ); }
/// <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.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> /// 对象状态搜索 /// </summary> /// <param name="cType"></param> /// <param name="sType"></param> /// <param name="dType"></param> /// <param name="value"></param> /// <returns></returns> public static SearchCondition Status(MFConditionType cType, MFStatusType sType, MFDataType dType, object value) { var sc = new SearchCondition(); sc.ConditionType = cType; sc.Expression.DataStatusValueType = sType; MFPropertyUtils.SetValue(sc.TypedValue, dType, value); return(sc); }
/// <summary> /// 对象属性搜索 /// </summary> /// <param name="cType"></param> /// <param name="propDef"></param> /// <param name="dType"></param> /// <param name="value"></param> /// <returns></returns> public static SearchCondition Property(MFConditionType cType, int propDef, MFDataType dType, object value) { var sc = new SearchCondition(); sc.ConditionType = cType; sc.Expression.DataPropertyValuePropertyDef = propDef; MFPropertyUtils.SetValue(sc.TypedValue, dType, value); return(sc); }
public void UnhandledConditionTypeThrows ( int objectId, MFConditionType conditionType ) { // Create the search builder. var mfSearchBuilder = this.GetSearchBuilder(); // Add the search condition. mfSearchBuilder.ObjectId(objectId, conditionType); }
/// <summary> /// Adds a <see cref="SearchCondition"/> to the collection to find items by <see cref="ObjID.ID"/>. /// </summary> /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param> /// <param name="objectId">The object ID to search for.</param> /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param> /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns> public static MFSearchBuilder ObjectId ( this MFSearchBuilder searchBuilder, int objectId, MFConditionType conditionType = MFConditionType.MFConditionTypeEqual ) { // Sanity. if (null == searchBuilder) { throw new ArgumentNullException(nameof(searchBuilder)); } if (0 >= objectId) { throw new ArgumentOutOfRangeException(nameof(objectId), "Object Id must be greater than 0."); } // We can only handle certain condition types; throw for others. if (conditionType != MFConditionType.MFConditionTypeEqual && conditionType != MFConditionType.MFConditionTypeNotEqual && conditionType != MFConditionType.MFConditionTypeLessThan && conditionType != MFConditionType.MFConditionTypeLessThanOrEqual && conditionType != MFConditionType.MFConditionTypeGreaterThan && conditionType != MFConditionType.MFConditionTypeGreaterThanOrEqual) { throw new ArgumentException ( $"The condition type {conditionType} is not supported for object Ids.", nameof(conditionType) ); } // Create the search condition. var searchCondition = new SearchCondition { ConditionType = conditionType }; // Set up the expression. searchCondition.Expression.SetStatusValueExpression ( MFStatusType.MFStatusTypeObjectID ); // Set the object id. searchCondition.TypedValue.SetValue(MFDataType.MFDatatypeInteger, objectId); // Add the search condition to the collection. searchBuilder.Conditions.Add(-1, searchCondition); // Return the search builder for chaining. return(searchBuilder); }
/// <summary> /// Adds a <see cref="SearchCondition"/> to the collection for whether the specified user has the specified permission on an object. /// </summary> /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param> /// <param name="userId">The ID of the user in question.</param> /// <param name="permission">The permission that the user should have on the object.</param> /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param> /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns> public static MFSearchBuilder UserHasPermissionTo ( this MFSearchBuilder searchBuilder, int userId, MFPermissionsExpressionType permission, MFConditionType conditionType = MFConditionType.MFConditionTypeEqual ) { // Sanity. if (null == searchBuilder) { throw new ArgumentNullException(nameof(searchBuilder)); } // We can only handle certain condition types; throw for others. if (conditionType != MFConditionType.MFConditionTypeEqual && conditionType != MFConditionType.MFConditionTypeNotEqual) { throw new ArgumentException ( $"The condition type {conditionType} is not supported for permission-based search conditions.", nameof(conditionType) ); } // Create the search condition. var searchCondition = new SearchCondition { ConditionType = conditionType }; // Set up the permission expression. searchCondition.Expression.SetPermissionExpression ( permission ); // Set the condition value to the lookup. var lookup = new MFilesAPI.Lookup() { ObjectType = (int)MFBuiltInValueList.MFBuiltInValueListUsers, Item = userId }; searchCondition.TypedValue.SetValue(MFDataType.MFDatatypeLookup, lookup); // Add the search condition to the collection. searchBuilder.Conditions.Add(-1, searchCondition); // Return the search builder for chaining. return(searchBuilder); }
public void UserHasPermissionToInvalidConditionTypeThrows(MFConditionType conditionType) { // Create the search builder. var mfSearchBuilder = this.GetSearchBuilder(); // Add the search condition. mfSearchBuilder.UserHasPermissionTo ( 123, MFPermissionsExpressionType.MFVisibleTo, conditionType ); }
/// <summary> /// Adds a <see cref="SearchCondition"/> to the collection for whether the specified user can see an object. /// </summary> /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param> /// <param name="userId">The ID of the user that should be able to see the object.</param> /// <param name="conditionType">What type of search to execute (defaults to <see cref="MFConditionType.MFConditionTypeEqual"/>).</param> /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns> public static MFSearchBuilder VisibleTo ( this MFSearchBuilder searchBuilder, int userId, MFConditionType conditionType = MFConditionType.MFConditionTypeEqual ) { // Use UserHasPermissionTo method. return(searchBuilder.UserHasPermissionTo ( userId, MFPermissionsExpressionType.MFVisibleTo, conditionType )); }
/// <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 )); }
public void SearchConditionIsCorrect ( int propertyDef, DateTime?input, MFConditionType conditionType, MFParentChildBehavior parentChildBehavior, PropertyDefOrObjectTypes indirectionLevels ) { base.AssertSearchConditionIsCorrect ( propertyDef, MFDataType.MFDatatypeDate, input, conditionType, parentChildBehavior, indirectionLevels ); }
public void SearchConditionIsCorrect_WithIndirectionLevels ( int propertyDef, long?input, MFConditionType conditionType, MFParentChildBehavior parentChildBehavior, PropertyDefOrObjectTypes indirectionLevels ) { base.AssertSearchConditionIsCorrect ( propertyDef, MFDataType.MFDatatypeInteger64, input, conditionType, parentChildBehavior, indirectionLevels ); }
/// <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); }
/// <summary> /// Adds a <see cref="SearchCondition"/> to the collection to restrict files by their size. /// </summary> /// <param name="searchBuilder">The <see cref="MFSearchBuilder"/> to add the condition to.</param> /// <param name="size">The file size to restrict by (in bytes).</param> /// <param name="conditionType">What type of search to execute.</param> /// <returns>The <paramref name="searchBuilder"/> provided, for chaining.</returns> public static MFSearchBuilder FileSize ( this MFSearchBuilder searchBuilder, long size, MFConditionType conditionType ) { // Sanity. if (null == searchBuilder) { throw new ArgumentNullException(nameof(searchBuilder)); } if (size < 0) { throw new ArgumentOutOfRangeException($"The size parameter must be zero or larger.", nameof(size)); } // Create the search condition. var searchCondition = new SearchCondition { ConditionType = conditionType }; // Set up the file value expression. searchCondition.Expression.SetFileValueExpression ( MFFileValueType.MFFileValueTypeFileSize ); // Search by the size searchCondition.TypedValue.SetValue(MFDataType.MFDatatypeInteger64, size); // Add the search condition to the collection. searchBuilder.Conditions.Add(-1, searchCondition); // Return the search builder for chaining. return(searchBuilder); }
/// <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 Set(Expression Expression, MFConditionType ConditionType, TypedValue TypedValue) { throw new NotImplementedException(); }
public SearchParameters AddProperty <T>(object value, MFConditionType cType = MFConditionType.MFConditionTypeEqual) where T : IMFPropertyDefinition { Conditions.AddPropertyCondition <T>(value, cType); return(this); }
public static SearchConditions AddPropertyCondition <T>(this SearchConditions search, object value, MFConditionType cType = MFConditionType.MFConditionTypeEqual) where T : IMFPropertyDefinition { int pd_id = (int)typeof(T).GetField("id").GetRawConstantValue(); MFDataType data_type = (MFDataType)typeof(T).GetField("data_type").GetRawConstantValue(); if (value is IObjVerEx) { search.AddPropertyCondition(pd_id, cType, data_type, (value as IObjVerEx).objVerEx.ToLookup()); } else if (value is IList) { Lookups lookups = new Lookups(); foreach (IObjVerEx objVerEx in (value as IList)) { if (objVerEx == null) { break; } lookups.Add(-1, objVerEx.objVerEx.ToLookup()); } search.AddPropertyCondition(pd_id, cType, data_type, lookups); } else { search.AddPropertyCondition(pd_id, cType, data_type, value); } return(search); }
/// <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 )); }
/// <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); }
/// <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 )); }