diff --git a/ChangeLog.md b/ChangeLog.md
index a60a265..d9b64a4 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -6,6 +6,22 @@ All notable changes to MIMWAL project will be documented in this file. The "Unre
* Support for multi-valued attributes in `[//Effective]` lookup in AuthZ workflows.
* Implement Approve Request Activity.
+* Support for `[//Value]` lookups in Query definitions across rest of the activities.
+
+------------
+
+### Version 2.18.0318.0
+
+#### Added
+
+* [ConvertNumberToList][ConvertNumberToListFunction] function.
+* [Multiply][MultiplyFunction] function.
+* [Divide][DivideFunction] function.
+* [Mod][ModFunction] function.
+
+#### Changed
+
+* [ConvertToString][ConvertToStringFunction] will return null if the input parameter is null instead of throwing an exception.
------------
@@ -171,3 +187,7 @@ All notable changes to MIMWAL project will be documented in this file. The "Unre
[ExecuteSqlScalarFunction]: https://github.com/Microsoft/MIMWAL/wiki/ExecuteSqlScalar-Function
[ValueByKeyFunction]: https://github.com/Microsoft/MIMWAL/wiki/ValueByKey-Function
[DateTimeFromStringFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeFromString-Function
+[ConvertNumberToListFunction]: https://github.com/Microsoft/MIMWAL/wiki/ConvertNumberToList-Function
+[MultiplyFunction]: https://github.com/Microsoft/MIMWAL/wiki/Multiply-Function
+[DivideFunction]: https://github.com/Microsoft/MIMWAL/wiki/Divide-Function
+[ModFunction]: https://github.com/Microsoft/MIMWAL/wiki/Mod-Function
diff --git a/src/VersionInfo.cs b/src/VersionInfo.cs
index 0cde2e4..56aa0ea 100644
--- a/src/VersionInfo.cs
+++ b/src/VersionInfo.cs
@@ -22,7 +22,7 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary
/// Build Number (MMDD)
/// Revision (if any on the same day)
///
- internal const string Version = "2.17.1012.0";
+ internal const string Version = "2.18.0318.0";
///
/// File Version information for the assembly consists of the following four values:
@@ -31,6 +31,6 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary
/// Build Number (MMDD)
/// Revision (if any on the same day)
///
- internal const string FileVersion = "2.17.1012.0";
+ internal const string FileVersion = "2.18.0318.0";
}
}
\ No newline at end of file
diff --git a/src/WAL.sln b/src/WAL.sln
index 8c492c6..5c3278d 100644
--- a/src/WAL.sln
+++ b/src/WAL.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2013
-VisualStudioVersion = 12.0.31101.0
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowActivityLibrary", "WorkflowActivityLibrary\WorkflowActivityLibrary.csproj", "{E2F7C594-3E4A-42DF-B293-7CB418DAB0DA}"
EndProject
@@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{9B89
ProjectSection(SolutionItems) = preProject
Scripts\CaptureTrace.cmd = Scripts\CaptureTrace.cmd
Scripts\CompileLanguagePack.cmd = Scripts\CompileLanguagePack.cmd
+ Scripts\EncryptConnectionString.ps1 = Scripts\EncryptConnectionString.ps1
Scripts\EncryptData.ps1 = Scripts\EncryptData.ps1
Scripts\Register.ps1 = Scripts\Register.ps1
Scripts\RunPSLoggingSample.ps1 = Scripts\RunPSLoggingSample.ps1
diff --git a/src/WorkflowActivityLibrary/Common/EventIdentifier.cs b/src/WorkflowActivityLibrary/Common/EventIdentifier.cs
index 98c0aa3..8157560 100644
--- a/src/WorkflowActivityLibrary/Common/EventIdentifier.cs
+++ b/src/WorkflowActivityLibrary/Common/EventIdentifier.cs
@@ -1238,6 +1238,26 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
///
public const int ExpressionFunctionDateTimeFromString = 11682;
+ ///
+ /// The event identifier for ExpressionFunction ConvertNumberToList events
+ ///
+ public const int ExpressionFunctionConvertNumberToList = 11683;
+
+ ///
+ /// The event identifier for ExpressionFunction Multiply events
+ ///
+ public const int ExpressionFunctionMultiply = 11684;
+
+ ///
+ /// The event identifier for ExpressionFunction Divide events
+ ///
+ public const int ExpressionFunctionDivide = 11685;
+
+ ///
+ /// The event identifier for ExpressionFunction Mod events
+ ///
+ public const int ExpressionFunctionMod = 11686;
+
///
/// The event identifier for LookupEvaluator Constructor events
///
@@ -3058,6 +3078,61 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
///
public const int ExpressionFunctionDateTimeFromStringInvalidFunctionParametersError = 41682;
+ ///
+ /// The event identifier for ExpressionFunction ConvertNumberToList events
+ ///
+ public const int ExpressionFunctionConvertNumberToListInvalidFunctionParameterCountError = 41683;
+
+ ///
+ /// The event identifier for ExpressionFunction ConvertNumberToList events
+ ///
+ public const int ExpressionFunctionConvertNumberToListInvalidFirstFunctionParameterTypeError = 41683;
+
+ ///
+ /// The event identifier for ExpressionFunction Multiply events
+ ///
+ public const int ExpressionFunctionMultiplyInvalidFunctionParameterCountError = 41684;
+
+ ///
+ /// The event identifier for ExpressionFunction Multiply events
+ ///
+ public const int ExpressionFunctionMultiplyInvalidFirstFunctionParameterTypeError = 41684;
+
+ ///
+ /// The event identifier for ExpressionFunction Multiply events
+ ///
+ public const int ExpressionFunctionMultiplyInvalidSecondFunctionParameterTypeError = 41684;
+
+ ///
+ /// The event identifier for ExpressionFunction Divide events
+ ///
+ public const int ExpressionFunctionDivideInvalidFunctionParameterCountError = 41685;
+
+ ///
+ /// The event identifier for ExpressionFunction Divide events
+ ///
+ public const int ExpressionFunctionDivideInvalidFirstFunctionParameterTypeError = 41685;
+
+ ///
+ /// The event identifier for ExpressionFunction Divide events
+ ///
+ public const int ExpressionFunctionDivideInvalidSecondFunctionParameterTypeError = 41685;
+
+ ///
+ /// The event identifier for ExpressionFunction Mod events
+ ///
+ public const int ExpressionFunctionModInvalidFunctionParameterCountError = 41686;
+
+ ///
+ /// The event identifier for ExpressionFunction Mod events
+ ///
+ public const int ExpressionFunctionModInvalidFirstFunctionParameterTypeError = 41686;
+
+ ///
+ /// The event identifier for ExpressionFunction Mod events
+ ///
+ public const int ExpressionFunctionModInvalidSecondFunctionParameterTypeError = 41686;
+
///
/// The event identifier for LookupEvaluator Constructor events
///
diff --git a/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs b/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs
index 366fe6e..50a6d2f 100644
--- a/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs
+++ b/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs
@@ -134,6 +134,9 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
case "CONVERTFROMBASE64":
return this.ConvertFromBase64();
+ case "CONVERTNUMBERTOLIST":
+ return this.ConvertNumberToList();
+
case "CONVERTSIDTOSTRING":
return this.ConvertSidToString();
@@ -189,6 +192,9 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
case "DATETIMESUBTRACT":
return this.DateTimeSubtract();
+ case "DIVIDE":
+ return this.Divide();
+
case "EQ":
return this.Eq();
@@ -246,6 +252,12 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
case "MID":
return this.Mid();
+ case "MOD":
+ return this.Mod();
+
+ case "MULTIPLY":
+ return this.Multiply();
+
case "NORMALIZESTRING":
return this.NormalizeString();
@@ -694,6 +706,63 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
}
}
+ ///
+ /// This function is used to divide the first integer value by the second integer value.
+ /// Function Syntax: Divide(first:integer, second:integer)
+ ///
+ /// The integer quotient of the division of the first integer value by the second integer value.
+ private long Divide()
+ {
+ Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionDivide, "Evaluation Mode: '{0}'.", this.mode);
+
+ try
+ {
+ if (this.parameters.Count != 2)
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 2, this.parameters.Count));
+ }
+
+ Type parameterType = typeof(long);
+ object parameter = this.parameters[0];
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ parameter = this.parameters[1];
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidSecondFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ long result;
+ if (this.mode != EvaluationMode.Parse)
+ {
+ long first = Convert.ToInt64(this.parameters[0], CultureInfo.InvariantCulture);
+ long second = Convert.ToInt64(this.parameters[1], CultureInfo.InvariantCulture);
+
+ if (second == 0)
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterError2, this.function, 2));
+ }
+
+ result = first / second;
+
+ Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionDivide, "Divide('{0}', '{1}') returned '{2}'.", this.parameters[0], this.parameters[1], result);
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return result;
+ }
+ finally
+ {
+ Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionDivide, "Evaluation Mode: '{0}'.", this.mode);
+ }
+ }
+
///
/// This function is used to determine the equivalence between two objects or values, returns true if they are equal.
/// Function Syntax: Eq(value:object, value:object, boolean:CompareCase)
@@ -3037,6 +3106,115 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
}
}
+ ///
+ /// This function is used to calculate the remainder after dividing the first integer with the second integer.
+ /// Function Syntax: Mod(first:integer, second:integer)
+ ///
+ /// The remainder after dividing the first integer with the second integer.
+ private long Mod()
+ {
+ Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionMod, "Evaluation Mode: '{0}'.", this.mode);
+
+ try
+ {
+ if (this.parameters.Count != 2)
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 2, this.parameters.Count));
+ }
+
+ Type parameterType = typeof(long);
+ object parameter = this.parameters[0];
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ parameter = this.parameters[1];
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidSecondFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ long result;
+ if (this.mode != EvaluationMode.Parse)
+ {
+ long first = Convert.ToInt64(this.parameters[0], CultureInfo.InvariantCulture);
+ long second = Convert.ToInt64(this.parameters[1], CultureInfo.InvariantCulture);
+
+ if (second == 0)
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterError2, this.function, 2));
+ }
+
+ result = first % second;
+
+ Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionMod, "Mod('{0}', '{1}') returned '{2}'.", this.parameters[0], this.parameters[1], result);
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return result;
+ }
+ finally
+ {
+ Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionMod, "Evaluation Mode: '{0}'.", this.mode);
+ }
+ }
+
+ ///
+ /// This function is used to multiply two integer values.
+ /// Function Syntax: Multiply(first:integer, second:integer)
+ ///
+ /// The result of the multiplication of the two integer values.
+ private long Multiply()
+ {
+ Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionMultiply, "Evaluation Mode: '{0}'.", this.mode);
+
+ try
+ {
+ if (this.parameters.Count != 2)
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionMultiplyInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 2, this.parameters.Count));
+ }
+
+ Type parameterType = typeof(long);
+ object parameter = this.parameters[0];
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionMultiplyInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ parameter = this.parameters[1];
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionMultiplyInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidSecondFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ long result;
+ if (this.mode != EvaluationMode.Parse)
+ {
+ long first = Convert.ToInt64(this.parameters[0], CultureInfo.InvariantCulture);
+ long second = Convert.ToInt64(this.parameters[1], CultureInfo.InvariantCulture);
+
+ result = first * second;
+
+ Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionMultiply, "Multiply('{0}', '{1}') returned '{2}'.", this.parameters[0], this.parameters[1], result);
+ }
+ else
+ {
+ result = 0;
+ }
+
+ return result;
+ }
+ finally
+ {
+ Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionMultiply, "Evaluation Mode: '{0}'.", this.mode);
+ }
+ }
+
///
/// This function is used to normalize the first string, first by replacing the character substitutions specfied in the second string
/// and then removing all diacritics using the .NET string normalization function.
@@ -4372,6 +4550,55 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common
}
}
+ ///
+ /// This function is used to convert a a number to a list of numbers which can be used to define an Iteration.
+ /// Function Syntax: ConvertNumberToList(count:integer)
+ ///
+ /// A list of numbers starting from 1 to the specified input number.
+ private List ConvertNumberToList()
+ {
+ Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionConvertNumberToList, "Evaluation Mode: '{0}'.", this.mode);
+
+ try
+ {
+ if (this.parameters.Count != 1)
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionConvertNumberToListInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 1, this.parameters.Count));
+ }
+
+ Type parameterType = typeof(int);
+ object parameter = this.parameters[0];
+
+ if (!this.VerifyType(parameter, parameterType))
+ {
+ throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionConvertNumberToListInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name));
+ }
+
+ List result = null;
+
+ if (this.mode != EvaluationMode.Parse)
+ {
+ int count = Convert.ToInt32(parameter, CultureInfo.InvariantCulture);
+ if (count > 0)
+ {
+ result = new List(count);
+ for (int i = 1; i <= count; ++i)
+ {
+ result.Add(i);
+ }
+ }
+
+ Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionConvertNumberToList, "ConvertNumberToList('{0}') returned '{1}'.", this.parameters[0], result);
+ }
+
+ return result;
+ }
+ finally
+ {
+ Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionConvertNumberToList, "Evaluation Mode: '{0}'.", this.mode);
+ }
+ }
+
///
/// This function is used to convert a byte array containing a security identifier to a string.
/// Function Syntax: ConvertSidToString(sid:binary)
diff --git a/src/WorkflowActivityLibrary/Messages.Designer.cs b/src/WorkflowActivityLibrary/Messages.Designer.cs
index 437abf8..d518866 100644
--- a/src/WorkflowActivityLibrary/Messages.Designer.cs
+++ b/src/WorkflowActivityLibrary/Messages.Designer.cs
@@ -358,7 +358,7 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary {
}
///
- /// Looks up a localized string similar to The function '{0}' expects list at position {1} to be of length '{2}'. It has a length of '{3}'..
+ /// Looks up a localized string similar to The function '{0}' expects parameter at position {1} to be non-zero..
///
internal static string ExpressionFunction_InvalidFunctionParameterError2 {
get {
diff --git a/src/WorkflowActivityLibrary/Messages.resx b/src/WorkflowActivityLibrary/Messages.resx
index 4a98132..dad3368 100644
--- a/src/WorkflowActivityLibrary/Messages.resx
+++ b/src/WorkflowActivityLibrary/Messages.resx
@@ -370,7 +370,7 @@
The function '{0}' expects parameter at position {1} to be of type '{2}' or '{3}'. It was supplied a '{4}' parameter.
- The function '{0}' expects list at position {1} to be of length '{2}'. It has a length of '{3}'.
+ The function '{0}' expects parameter at position {1} to be non-zero.
The function '{0}' expects first parameter to be of type '{1}' or '{2}' or '{3}'. It was supplied a '{4}' parameter.