diff --git a/docs/utils/Array.md b/docs/utils/Array.md new file mode 100644 index 0000000..36e6765 --- /dev/null +++ b/docs/utils/Array.md @@ -0,0 +1,43 @@ +# fflib-apex-extensions + +## Utils - Array + +### Method reference + +`public static List cloneAndSort(List unsortedIntegers)` + +`public static List cloneAndSort(List unsorted)` + +`public static Object firstValue(List objects)` + +`public static Boolean isEmpty(List objects)` + +`public static Boolean isEmpty(List sObjects)` + +`public static Boolean isNotEmpty(List objects)` + +`public static Boolean isNotEmpty(List sObjects)` + +`public static Object lastValue(List objects)` + +`public static List lowerCase(List strings)` + +`public static Datetime maxDatetime(List input)` + +`public static Object max(List input)` + +`public static Datetime minDatetime(List input)` + +`public static Object min(List input)` + +`public static List objectToString(List objects)` + +`public static List objectToString(Set objects)` + +`public static Set objectToIds(Set objects)` + +`public static List reverse(List objects)` + +`public static List reverse(List sObjects)` + +`public static List upperCase(List strings)` diff --git a/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtils.cls b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtils.cls new file mode 100644 index 0000000..0468257 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtils.cls @@ -0,0 +1,339 @@ +/** + * File Name: Array + * Description: + * + * @author : architect ir. Wilhelmus G.J. Velzeboer + * + * Copyright (c), W.G.J. Velzeboer, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above author notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +public class ArrayUtils +{ + /* private constructor to prevent instantiation */ + private ArrayUtils() {} + + /** + * Creates a clone from the provided list and returns the sorted list + * + * @param unsortedIntegers List of unsorted Integers + * + * @return Sorted list or Integers + */ + public static List cloneAndSort(List unsortedIntegers) + { + return (List) cloneAndSort((List) unsortedIntegers); + } + + /** + * Creates a clone from the provided list and returns the sorted list + * + * @param unsorted List of unsorted Objects + * + * @return Sorted list + */ + public static List cloneAndSort(List unsorted) + { + List result = unsorted.clone(); + result.sort(); + return result; + } + + /** + * Gets the first value of the list + * + * @param objects List of objects + * + * @return The first value of the list. Returns null, is the provided list is null or empty + */ + public static Object firstValue(List objects) + { + if (isEmpty(objects)) return null; + + return objects.get(0); + } + + /** + * Validates if a list is empty + * + * @param objects The list to validate + * + * @return Returns true of the list is either null or empty + */ + public static Boolean isEmpty(List objects) + { + return (null == objects || objects.isEmpty()); + } + + /** + * Validates if a list is empty + * + * @param sObjects The list to validate + * + * @return Returns true of the list is either null or empty + */ + public static Boolean isEmpty(List sObjects) + { + return (null == sObjects || sObjects.isEmpty()); + } + + /** + * Validates if a list is not empty + * + * @param objects The list to validate + * + * @return Returns true of the list is not null or not empty + */ + public static Boolean isNotEmpty(List objects) + { + return !isEmpty(objects); + } + + /** + * Validates if a list is not empty + * + * @param sObjects The list to validate + * + * @return Returns true of the list is not null or not empty + */ + public static Boolean isNotEmpty(List sObjects) + { + return !isEmpty(sObjects); + } + + /** + * Get the last value in the list + * + * @param objects List of objects + * + * @return The last value of the list. Returns null, is the provided list is null or empty + */ + public static Object lastValue(List objects) + { + if (isEmpty(objects)) return null; + + return objects.get(objects.size() - 1); + } + + /** + * Converts all Strings in the list to lowercase, + * null values are ignored and removed from the list + * + * @param strings The List of String to convert + * + * @return Returns the List with only lowercase values + */ + public static List lowerCase(List strings) + { + List result = new List(); + if (isEmpty(strings)) return result; + + for (String str : strings) + { + if (null == str) continue; + + result.add(str.toLowerCase()); + } + return result; + } + + /** + * Sorts the list with Datetime values and return the highest value in the list + * + * @param input List of Datetime values + * + * @return Highest Datetime value of the given input. Returns null when the input is empty or null. + */ + public static Datetime maxDatetime(List input) + { + if (isEmpty(input)) return null; + + return (Datetime) max((List) input); + } + + /** + * Sorts the list and return the highest value in the list + * + * @param input List of values + * + * @return Highest value of the given input. Returns null when the input is empty or null. + */ + public static Object max(List input) + { + if (isEmpty(input)) return null; + + return lastValue(cloneAndSort(input)); + } + + /** + * Sorts the list with Datetime values and return the oldest value in the list + * + * @param input List of Datetime values + * + * @return Oldest Datetime value of the given input. Returns null when the input is empty or null. + */ + public static Datetime minDatetime(List input) + { + if (isEmpty(input)) return null; + + return (Datetime) min((List) input); + } + + /** + * Sorts the list and return the lowest value in the list + * + * @param input List of values + * + * @return Lowest value of the given input. Returns null when the input is empty or null. + */ + public static Object min(List input) + { + if (isEmpty(input)) return null; + + List result = cloneAndSort(input); + return firstValue(result); + } + + /** + * Casts a list of objects to a list of their literal string version + * + * @param objects List of objects to convert + * + * @return Returns a list of Strings with the literal conversion of the object + */ + public static List objectToString(List objects) + { + List result = new List(); + if (isEmpty(objects)) return result; + + for (Object obj : objects) + { + result.add(String.valueOf(obj)); + } + return result; + } + + /** + * Casts a Set of objects to a list of their literal string version + * + * @param objects Set of objects to convert + * + * @return Returns a list of Strings with the literal conversion of the object + */ + public static List objectToString(Set objects) + { + return objectToString(new List(objects)); + } + + /** + * Casts a Set of Objects to a list of Ids + * Non Id objects are ignored + * + * @param objects Set of objects to convert + * + * @return Returns a list of Strings with the literal conversion of the object + */ + public static Set objectToIds(Set objects) + { + Set results = new Set(); + for (Object obj : objects) + { + if (!(obj instanceof Id)) continue; + + results.add((Id) obj); + } + return results; + } + + /** + * Reverse the order of a list of objects + * + * @param objects List of Objects + * + * @return Returns a list of objects in reserve order + */ + public static List reverse(List objects) + { + if (isEmpty(objects)) return objects; + + Integer i = 0; + Integer j = objects.size() - 1; + Object tmp; + while (j > i) + { + tmp = objects[j]; + objects[j] = objects[i]; + objects[i] = tmp; + j--; + i++; + } + return objects; + } + + /** + * Reverse the order of a list of SObjects + * + * @param sObjects List of SObjects + * + * @return Returns a list of SObjects in reserve order + */ + public static List reverse(List sObjects) + { + if (isEmpty(sObjects)) return sObjects; + + Integer i = 0; + Integer j = sObjects.size() - 1; + SObject tmp; + while (j > i) + { + tmp = sObjects[j]; + sObjects[j] = sObjects[i]; + sObjects[i] = tmp; + j--; + i++; + } + return sObjects; + } + + /** + * Converts all String of the list into uppercase + * null values are ignored + * + * @param strings The list of Strings to convert + * + * @return Returns the List with uppercase Strings + */ + public static List upperCase(List strings) + { + List result = new List(); + if (isEmpty(strings)) return result; + + for (String str : strings) + { + if (null == str) continue; + + result.add(str.toUpperCase()); + } + return result; + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtils.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtils.cls-meta.xml new file mode 100644 index 0000000..d75b058 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtils.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active + diff --git a/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtilsTest.cls b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtilsTest.cls new file mode 100644 index 0000000..d9f358f --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtilsTest.cls @@ -0,0 +1,252 @@ +/** + * File Name: ArrayTest + * Description: + * + * @author: architect ir. Wilhelmus G.J. Velzeboer | wvelzebo@its.jnj.com + */ +@IsTest(IsParallel=true) +private class ArrayUtilsTest +{ + + @IsTest + static void testObjectToString() + { + System.assertEquals( + new List {'123', '456', '789'}, + ArrayUtils.objectToString( + new List {123, 456, 789} + ) + ); + } + + @IsTest + static void testObjectStringToString() + { + System.assertEquals( + new List {'123', '456', '789'}, + ArrayUtils.objectToString( + new List {'123', '456', '789'} + ) + ); + } + + @IsTest + static void itShouldReturnEmptyListOnEmptyObjectToString() + { + System.assertEquals( + new List(), + ArrayUtils.objectToString( + new List() + ) + ); + } + + @IsTest + static void itShouldConvertSetToListOfString() + { + System.assertEquals( + new List {'1', '2', '3'}, + ArrayUtils.objectToString( + new Set {1, 2, 3} + ) + ); + } + + @IsTest + static void itShouldConvertSetObjectToSetOfIds() + { + Id idA = fflib_IDGenerator.generate(Account.SObjectType); + Id idB = fflib_IDGenerator.generate(Account.SObjectType); + System.assertEquals( + new Set {idA, idB}, + ArrayUtils.objectToIds( + new Set + { + (Object) idA, + (Object) idB + } + ) + ); + } + + @IsTest + static void itShouldReturnReversedObjectList() + { + System.assertEquals( + new List + { + (Object) 'C', + (Object) 'B', + (Object) 'A' + }, + ArrayUtils.reverse( + new List + { + (Object) 'A', + (Object) 'B', + (Object) 'C' + } + ) + ); + } + + @IsTest + static void itShouldReturnReversedSObjectList() + { + System.assertEquals( + new List + { + (SObject) new Account(Name = 'C'), + (SObject) new Account(Name = 'B'), + (SObject) new Account(Name = 'A') + }, + ArrayUtils.reverse( + new List + { + (SObject) new Account(Name = 'A'), + (SObject) new Account(Name = 'B'), + (SObject) new Account(Name = 'C') + } + ) + ); + } + + @IsTest + static void itShouldConvertListOfStringsIntoUpperCase() + { + System.assertEquals( + new List + { + 'TEST A', + 'TEST B', + 'TEST C' + }, + ArrayUtils.upperCase( + new List + { + 'test a', + 'test b', + 'test c' + } + ) + ); + } + + @IsTest + static void testLowerCase() + { + System.assertEquals( + new List {'abc', 'def'}, + ArrayUtils.lowerCase( + new List {'ABC', 'DEF'} + ) + ); + } + + @IsTest + static void testIsEmpty() + { + List aNull = null; + System.assertEquals(true, ArrayUtils.isEmpty(aNull)); + System.assertEquals(true, ArrayUtils.isEmpty(new List {})); + System.assertEquals(false, ArrayUtils.isEmpty(new List {'a'})); + System.assertEquals(false, ArrayUtils.isEmpty(new List {'a', 'b'})); + System.assertEquals(true, ArrayUtils.isEmpty(new List {})); + System.assertEquals(false, ArrayUtils.isEmpty(new List {1})); + System.assertEquals(false, ArrayUtils.isEmpty(new List {1, 2})); + } + + @IsTest + static void testIsNotEmpty() + { + List aNull = null; + System.assertEquals(false, ArrayUtils.isNotEmpty(aNull)); + System.assertEquals(false, ArrayUtils.isNotEmpty(new List {})); + System.assertEquals(true, ArrayUtils.isNotEmpty(new List {'a'})); + System.assertEquals(true, ArrayUtils.isNotEmpty(new List {'a', 'b'})); + System.assertEquals(false, ArrayUtils.isNotEmpty(new List {})); + System.assertEquals(true, ArrayUtils.isNotEmpty(new List {1})); + System.assertEquals(true, ArrayUtils.isNotEmpty(new List {1, 2})); + System.assertEquals(false, ArrayUtils.isNotEmpty(new List {})); + System.assertEquals(true, ArrayUtils.isNotEmpty(new List {new Account(Name = 'test')})); + } + + @IsTest + static void itShouldReturnMostRecentDatetime() + { + // GIVEN - a list of unsorted Datetime values + List datetimes = generateDateTimes(); + + // WHEN - we request the maxDatetime + Datetime maxDatetime = ArrayUtils.maxDatetime(datetimes); + + // THEN - the highest Datetime should be returned + System.assertEquals(datetimes.get(1), maxDatetime); + } + + @IsTest + static void itShouldReturnOldestDatetime() + { + // GIVEN - a list of unsorted Datetime values + List datetimes = generateDateTimes(); + + // WHEN - we request the maxDatetime + Datetime maxDatetime = ArrayUtils.minDatetime(datetimes); + + // THEN - the highest Datetime should be returned + System.assertEquals(datetimes.get(4), maxDatetime); + } + + @IsTest + static void itShouldHandleNullInputsForMaxDatatime() + { + System.assertEquals( + null, ArrayUtils.maxDatetime(new List()), + 'maxDatetime method was unable to handle an empty list as input' + ); + System.assertEquals( + null, ArrayUtils.maxDatetime(null), + 'maxDatetime method was unable to handle null as input' + ); + } + + @IsTest + static void itShouldCloneAndSortTheList() + { + // GIVEN - a list of unsorted numbers + List unsorted = new List + { + 1, 30, 2, 76, -7 + }; + + // WHEN - we request the a cloned and sorted list + List sorted = ArrayUtils.cloneAndSort(unsorted); + System.assertNotEquals(unsorted, sorted, 'The original object was modified, something went wrong with the cloning'); + System.assertEquals(new List {-7, 1, 2, 30, 76}, sorted, 'Incorrect sorted list returned'); + } + + @IsTest + static void itShouldReturnTheLastValueInTheList() + { + // GIVEN - a list of unsorted values + List objects = new List {1, 2, 3, 9, 4, 7, 8}; + + // WHEN - we request the last value + Object result = ArrayUtils.lastValue(objects); + + // THEN - the highest Datetime should be returned + System.assertEquals(8, result, 'Did not return the last value in the list of objects'); + } + + private static List generateDateTimes() + { + return new List + { + Datetime.newInstance(2020, 01, 01, 07, 59, 7), + Datetime.newInstance(2020, 02, 01, 07, 40, 7), + Datetime.newInstance(2020, 02, 01, 07, 00, 7), + Datetime.newInstance(2019, 02, 01, 07, 59, 7), + Datetime.newInstance(2018, 07, 07, 07, 7, 7) + }; + } +} \ No newline at end of file diff --git a/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtilsTest.cls-meta.xml b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtilsTest.cls-meta.xml new file mode 100644 index 0000000..d75b058 --- /dev/null +++ b/sfdx-source/apex-extensions/main/default/classes/utils/ArrayUtilsTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 51.0 + Active +