Skip to content

Commit 7922dba

Browse files
authored
Set support for some of the collection functions (#141)
1 parent e12343f commit 7922dba

File tree

8 files changed

+267
-74
lines changed

8 files changed

+267
-74
lines changed

docs/src/markdoc/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const variables = {
77
tags,
88
nodes,
99
variables: {
10-
packageId: "04tRb000000yUJNIA2",
10+
packageId: "04tRb000000yvufIAA",
1111
componentPackageId: "04tRb000000sGz3IAE",
1212
urlPrefix: IS_PROD ? "/expression" : "",
1313
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
public with sharing class CollectionUtils {
2+
public static List<Object> toObjectList(Iterable<Object> values) {
3+
List<Object> objects = new List<Object>();
4+
for (Object s : values) {
5+
objects.add(s);
6+
}
7+
return objects;
8+
}
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3+
<apiVersion>60.0</apiVersion>
4+
<status>Active</status>
5+
</ApexClass>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@IsTest
2+
private class CollectionUtilsTest {
3+
@IsTest
4+
static void canConvertAnyIterableToAListOfObjects() {
5+
Set<String> testSet = new Set<String>{
6+
'a', 'b', 'c'
7+
};
8+
9+
List<Object> convertedList = CollectionUtils.toObjectList(testSet);
10+
11+
Assert.areEqual(3, convertedList.size());
12+
Assert.isTrue(convertedList.contains('a'));
13+
Assert.isTrue(convertedList.contains('b'));
14+
Assert.isTrue(convertedList.contains('c'));
15+
}
16+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3+
<apiVersion>60.0</apiVersion>
4+
<status>Active</status>
5+
</ApexClass>

expression-src/main/src/interpreter/std-lib/CollectionFunctions.cls

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,15 @@ public with sharing class CollectionFunctions {
9595
if (children == null) {
9696
return new List<Object>();
9797
}
98-
if (!(children instanceof List<Object>)) {
98+
if (!(children instanceof Iterable<Object>)) {
9999
throw new FunctionExecutionException(
100-
'Error executing "MAP" function: the first argument must evaluate to a list.'
100+
'Error executing "MAP" function: the first argument must evaluate to an iterable.'
101101
);
102102
}
103103

104+
List<Object> childrenAsList = CollectionUtils.toObjectList((Iterable<Object>) children);
105+
104106
// If the list of children is empty, return early
105-
List<Object> childrenAsList = (List<Object>) children;
106107
if (childrenAsList.isEmpty()) {
107108
return new List<Object>();
108109
}
@@ -147,14 +148,14 @@ public with sharing class CollectionFunctions {
147148
if (children == null) {
148149
return new List<Object>();
149150
}
150-
if (!(children instanceof List<Object>)) {
151+
if (!(children instanceof Iterable<Object>)) {
151152
throw new FunctionExecutionException(
152-
'Error executing "WHERE" function: the first argument must evaluate to a list.'
153+
'Error executing "WHERE" function: the first argument must evaluate to an iterable.'
153154
);
154155
}
155156

156157
// If the list of children is empty, return early
157-
List<Object> childrenAsList = (List<Object>) children;
158+
List<Object> childrenAsList = CollectionUtils.toObjectList((Iterable<Object>) children);
158159
if (childrenAsList.isEmpty()) {
159160
return new List<Object>();
160161
}
@@ -207,13 +208,13 @@ public with sharing class CollectionFunctions {
207208
Object listOfNumbers = evaluate(arguments.get(0));
208209

209210
// Verify that all elements in the list are numbers
210-
if (!(listOfNumbers instanceof List<Object>)) {
211+
if (!(listOfNumbers instanceof Iterable<Object>)) {
211212
throw new FunctionExecutionException(
212-
'Error executing "AVERAGE" function: the argument must evaluate to a list of numbers.'
213+
'Error executing "AVERAGE" function: the argument must evaluate to an iterable of numbers.'
213214
);
214215
}
215216

216-
List<Object> listOfNumbersAsList = (List<Object>) listOfNumbers;
217+
List<Object> listOfNumbersAsList = CollectionUtils.toObjectList((Iterable<Object>) listOfNumbers);
217218
// Sanitize nulls
218219
List<Object> sanitizedList = new List<Object>();
219220
for (Object maybeNull : listOfNumbersAsList) {
@@ -254,14 +255,14 @@ public with sharing class CollectionFunctions {
254255
public override Object call(List<Expr> arguments) {
255256
Object listOfValues = evaluate(arguments.get(0));
256257
// Must be a list or a map
257-
if (!(listOfValues instanceof List<Object>) && !(listOfValues instanceof Map<Object, Object>)) {
258+
if (!(listOfValues instanceof Iterable<Object>) && !(listOfValues instanceof Map<Object, Object>)) {
258259
throw new FunctionExecutionException(
259-
'Error executing "SIZE" function: the argument must evaluate to a list or a map.'
260+
'Error executing "SIZE" function: the argument must evaluate to an iterable or a map.'
260261
);
261262
}
262263

263-
if (listOfValues instanceof List<Object>) {
264-
return ((List<Object>) listOfValues).size();
264+
if (listOfValues instanceof Iterable<Object>) {
265+
return CollectionUtils.toObjectList((Iterable<Object>) listOfValues).size();
265266
} else {
266267
return ((Map<Object, Object>) listOfValues).size();
267268
}
@@ -283,14 +284,14 @@ public with sharing class CollectionFunctions {
283284
public override Object call(List<Expr> arguments) {
284285
// The argument must either be a list or a map
285286
Object value = evaluate(arguments.get(0));
286-
if (!(value instanceof List<Object>) && !(value instanceof Map<Object, Object>)) {
287+
if (!(value instanceof Iterable<Object>) && !(value instanceof Map<Object, Object>)) {
287288
throw new FunctionExecutionException(
288-
'Error executing "ISEMPTY" function: the argument must evaluate to a list or a map.'
289+
'Error executing "ISEMPTY" function: the argument must evaluate to an iterable or a map.'
289290
);
290291
}
291292

292-
if (value instanceof List<Object>) {
293-
return ((List<Object>) value).isEmpty();
293+
if (value instanceof Iterable<Object>) {
294+
return CollectionUtils.toObjectList((Iterable<Object>) value).isEmpty();
294295
} else {
295296
return ((Map<Object, Object>) value).isEmpty();
296297
}
@@ -312,12 +313,12 @@ public with sharing class CollectionFunctions {
312313
public override Object call(List<Expr> arguments) {
313314
Object listObj = evaluate(arguments.get(0)) ?? new List<Object>();
314315
Object item = evaluate(arguments.get(1));
315-
if (!(listObj instanceof List<Object>)) {
316+
if (!(listObj instanceof Iterable<Object>)) {
316317
throw new FunctionExecutionException(
317-
'Error executing "APPEND" function: the first argument must evaluate to a list.'
318+
'Error executing "APPEND" function: the first argument must evaluate to an iterable.'
318319
);
319320
}
320-
List<Object> result = new List<Object>((List<Object>) listObj);
321+
List<Object> result = CollectionUtils.toObjectList((Iterable<Object>) listObj);
321322
result.add(item);
322323
return result;
323324
}
@@ -451,9 +452,9 @@ public with sharing class CollectionFunctions {
451452
public override Object call(List<Expr> arguments) {
452453
// First argument is a list
453454
Object listObj = evaluate(arguments.get(0));
454-
if (!(listObj instanceof List<Object>)) {
455+
if (!(listObj instanceof Iterable<Object>)) {
455456
throw new FunctionExecutionException(
456-
'Error executing "SORT" function: the first argument must evaluate to a list.'
457+
'Error executing "SORT" function: the first argument must evaluate to an iterable.'
457458
);
458459
}
459460

@@ -497,7 +498,7 @@ public with sharing class CollectionFunctions {
497498
}
498499

499500
// If the list is empty, return early
500-
List<Object> listVal = (List<Object>) listObj;
501+
List<Object> listVal = CollectionUtils.toObjectList((Iterable<Object>) listObj);
501502
if (listVal.isEmpty()) {
502503
return listVal;
503504
}
@@ -701,9 +702,9 @@ public with sharing class CollectionFunctions {
701702
public override Object call(List<Expr> arguments) {
702703
// First argument is a list
703704
Object listObj = evaluate(arguments.get(0));
704-
if (!(listObj instanceof List<Object>)) {
705+
if (!(listObj instanceof Iterable<Object>)) {
705706
throw new FunctionExecutionException(
706-
'Error executing "REDUCE" function: the first argument must evaluate to a list.'
707+
'Error executing "REDUCE" function: the first argument must evaluate to an iterable.'
707708
);
708709
}
709710

@@ -714,7 +715,7 @@ public with sharing class CollectionFunctions {
714715
Object initialValue = evaluate(arguments.get(2));
715716

716717
// If the list is empty, return early
717-
List<Object> listVal = (List<Object>) listObj;
718+
List<Object> listVal = CollectionUtils.toObjectList((Iterable<Object>) listObj);
718719
if (listVal.isEmpty()) {
719720
return initialValue;
720721
}
@@ -835,17 +836,17 @@ public with sharing class CollectionFunctions {
835836
public override Object call(List<Expr> arguments) {
836837
// First argument is a list
837838
Object listObj = evaluate(arguments.get(0));
838-
if (!(listObj instanceof List<Object>)) {
839+
if (!(listObj instanceof Iterable<Object>)) {
839840
throw new FunctionExecutionException(
840-
'Error executing "ANY" function: the first argument must evaluate to a list.'
841+
'Error executing "ANY" function: the first argument must evaluate to an iterable.'
841842
);
842843
}
843844

844845
// Second argument is an expression
845846
Expr expr = arguments.get(1);
846847

847848
// If the list is empty, return early
848-
List<Object> listVal = (List<Object>) listObj;
849+
List<Object> listVal = CollectionUtils.toObjectList((Iterable<Object>) listObj);
849850
if (listVal.isEmpty()) {
850851
return false;
851852
}
@@ -887,14 +888,14 @@ public with sharing class CollectionFunctions {
887888
public override Object call(List<Expr> arguments) {
888889
// First argument is a list
889890
Object listObj = evaluate(arguments.get(0));
890-
if (!(listObj instanceof List<Object>)) {
891+
if (!(listObj instanceof Iterable<Object>)) {
891892
throw new FunctionExecutionException(
892-
'Error executing "SUM" function: the first argument must evaluate to a list.'
893+
'Error executing "SUM" function: the first argument must evaluate to an iterable.'
893894
);
894895
}
895896

896897
// If the list is empty, return early
897-
List<Object> listVal = (List<Object>) listObj;
898+
List<Object> listVal = CollectionUtils.toObjectList((Iterable<Object>) listObj);
898899
if (listVal.isEmpty()) {
899900
return 0;
900901
}
@@ -928,17 +929,17 @@ public with sharing class CollectionFunctions {
928929
public override Object call(List<Expr> arguments) {
929930
// First argument is a list
930931
Object listObj = evaluate(arguments.get(0));
931-
if (!(listObj instanceof List<Object>)) {
932+
if (!(listObj instanceof Iterable<Object>)) {
932933
throw new FunctionExecutionException(
933-
'Error executing "EVERY" function: the first argument must evaluate to a list.'
934+
'Error executing "EVERY" function: the first argument must evaluate to an iterable.'
934935
);
935936
}
936937

937938
// Second argument is an expression
938939
Expr expr = arguments.get(1);
939940

940941
// If the list is empty, return early
941-
List<Object> listVal = (List<Object>) listObj;
942+
List<Object> listVal = CollectionUtils.toObjectList((Iterable<Object>) listObj);
942943
if (listVal.isEmpty()) {
943944
return false;
944945
}

0 commit comments

Comments
 (0)