diff --git a/src/classes/CollectionUtils.cls b/src/classes/CollectionUtils.cls new file mode 100644 index 0000000..cb48d3d --- /dev/null +++ b/src/classes/CollectionUtils.cls @@ -0,0 +1,10 @@ +/************************************************************************************************* +* This file is part of the Nebula Framework project, released under the MIT License. * +* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * +*************************************************************************************************/ +public class CollectionUtils { + + public static Boolean isNullOrEmpty(List listOfThings) { + return listOfThings == null || listOfThings.isEmpty(); + } +} \ No newline at end of file diff --git a/src/classes/CollectionUtils.cls-meta.xml b/src/classes/CollectionUtils.cls-meta.xml new file mode 100644 index 0000000..cbddff8 --- /dev/null +++ b/src/classes/CollectionUtils.cls-meta.xml @@ -0,0 +1,5 @@ + + + 38.0 + Active + diff --git a/src/classes/DML.cls b/src/classes/DML.cls index 0fb1af1..c2fac01 100644 --- a/src/classes/DML.cls +++ b/src/classes/DML.cls @@ -17,9 +17,9 @@ public virtual class DML implements IDML { } public virtual SObject doUpsert(SObject record) { - // Salesforce will only allow upsert calls for SObjects if a declared-type list is passed in. - // This is fine for the bulk method, where we can assume the caller is passing in an explicit list, but for a single record, - // the only way to successfully perform the upsert is to dynamically spin up a list of the SObject's type + //Salesforce will only allow upsert calls for SObjects if a declared-type list is passed in. + //This is fine for the bulk method, where we can assume the caller is passing in an explicit list, but for a single record, + //the only way to successfully perform the upsert is to dynamically spin up a list of the SObject's type String listType = 'List<' + record.getSObjectType() + '>'; List castRecords = (List)Type.forName(listType).newInstance(); castRecords.add(record); diff --git a/src/classes/DMLMock.cls b/src/classes/DMLMock.cls index e261993..51edb8c 100644 --- a/src/classes/DMLMock.cls +++ b/src/classes/DMLMock.cls @@ -3,7 +3,7 @@ * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * *************************************************************************************************/ public virtual class DMLMock implements IDML { - + // DML public SObject doInsert(SObject record) { return this.doInsert(new List{record})[0]; } public List doInsert(List recordList) { TestingUtils.generateIds(recordList); @@ -32,10 +32,11 @@ public virtual class DMLMock implements IDML { public void doDelete(SObject record) { this.doDelete(new List{record}); } public void doDelete(List recordList) { - if(recordList != null) TestingUtils.deletedRecords.addAll(recordList); + if(!CollectionUtils.IsNullOrEmpty(recordList)) { + TestingUtils.deletedRecords.addAll(recordList); + } } public void doHardDelete(SObject record) { this.doHardDelete(new List{record}); } public void doHardDelete(List recordList) { this.doDelete(recordList); } - } \ No newline at end of file diff --git a/src/classes/DMLMock_Tests.cls b/src/classes/DMLMock_Tests.cls index a4b61de..b0de864 100644 --- a/src/classes/DMLMock_Tests.cls +++ b/src/classes/DMLMock_Tests.cls @@ -1,10 +1,5 @@ -/************************************************************************************************* -* This file is part of the Nebula Framework project, released under the MIT License. * -* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * -*************************************************************************************************/ @isTest private class DMLMock_Tests { - static IDML dmlRepo = new DMLMock(); static Schema.Contact con = createContact(); @@ -85,5 +80,4 @@ private class DMLMock_Tests { return con; } - } \ No newline at end of file diff --git a/src/classes/DML_Tests.cls b/src/classes/DML_Tests.cls index 9bd280b..42494fd 100644 --- a/src/classes/DML_Tests.cls +++ b/src/classes/DML_Tests.cls @@ -1,10 +1,5 @@ -/************************************************************************************************* -* This file is part of the Nebula Framework project, released under the MIT License. * -* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * -*************************************************************************************************/ @isTest private class DML_Tests { - static IDML dml = new DML(); static Contact contact = createContact(); @@ -90,5 +85,4 @@ private class DML_Tests { return contact; } - } \ No newline at end of file diff --git a/src/classes/Exceptions.cls b/src/classes/Exceptions.cls index 70b180e..71a27e6 100644 --- a/src/classes/Exceptions.cls +++ b/src/classes/Exceptions.cls @@ -4,6 +4,7 @@ *************************************************************************************************/ public without sharing class Exceptions { + public class DescribeException extends Exception {} public class InvalidOperationException extends Exception {} public class RecordTypeException extends Exception {} public class SObjectTriggerHandlerException extends Exception {} diff --git a/src/classes/IQueryFilter.cls b/src/classes/IQueryFilter.cls index 10f7e4b..9ce2b5d 100644 --- a/src/classes/IQueryFilter.cls +++ b/src/classes/IQueryFilter.cls @@ -1,7 +1,3 @@ -/************************************************************************************************* -* This file is part of the Nebula Framework project, released under the MIT License. * -* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * -*************************************************************************************************/ public interface IQueryFilter { String getValue(); diff --git a/src/classes/QueryBuilder.cls b/src/classes/QueryBuilder.cls index a26e075..da9af1d 100644 --- a/src/classes/QueryBuilder.cls +++ b/src/classes/QueryBuilder.cls @@ -19,16 +19,16 @@ public without sharing class QueryBuilder extends NebulaCore implements IQueryBu private final Map sobjectTypeFieldMap; public QueryBuilder(Schema.SObjectType sobjectType, Schema.FieldSet fieldSet, List sobjectFieldList) { - this.sobjectType = sobjectType; - this.sobjectFieldList = sobjectFieldList; - this.fieldSet = fieldSet; - this.sobjectTypeFieldMap = this.sobjectType.getDescribe().fields.getMap(); + this.sobjectType = sobjectType; + this.sobjectFieldList = sobjectFieldList; + this.fieldSet = fieldSet; + this.forUpdate = false; this.queryFields = new Set(); - this.childRelationshipQueries = new List(); - this.whereClauseList = new List(); this.orderByList = new List(); - this.forUpdate = false; + this.sobjectTypeFieldMap = this.sobjectType.getDescribe().fields.getMap(); + this.whereClauseList = new List(); + this.childRelationshipQueries = new List(); this.addCommonQueryFields(); this.addFieldSetMembers(); diff --git a/src/classes/QueryDateLiteral_Tests.cls b/src/classes/QueryDateLiteral_Tests.cls index 244db7e..a1fd388 100644 --- a/src/classes/QueryDateLiteral_Tests.cls +++ b/src/classes/QueryDateLiteral_Tests.cls @@ -5,7 +5,7 @@ @isTest public class QueryDateLiteral_Tests { - private static Integer n_number = 5; + private static integer n_number = 5; @isTest static void it_should_return_yesterday_string() { diff --git a/src/classes/SObjectFieldDescriber_Tests.cls b/src/classes/SObjectFieldDescriber_Tests.cls index d8f47df..1b744d8 100644 --- a/src/classes/SObjectFieldDescriber_Tests.cls +++ b/src/classes/SObjectFieldDescriber_Tests.cls @@ -2,6 +2,7 @@ * This file is part of the Nebula Framework project, released under the MIT License. * * See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * *************************************************************************************************/ + @isTest private class SObjectFieldDescriber_Tests { diff --git a/src/classes/SObjectRepositoryMocks.cls b/src/classes/SObjectRepositoryMocks.cls index ce71a8a..5fd2a54 100644 --- a/src/classes/SObjectRepositoryMocks.cls +++ b/src/classes/SObjectRepositoryMocks.cls @@ -89,23 +89,41 @@ public class SObjectRepositoryMocks { } private void createMockObjects() { - // We would expect that for the Ids passed in, there will be a corresponding number of records returned of the exact same - // SObjectType as their Ids. + //We would expect that for the Ids passed in, there will be a corresponding number of records returned of the exact same + //SObjectType as their Ids. this.records = new List(); - for(Id recordId : this.recordIdList) { - SObjectType objType = recordId.getSObjectType(); + for(Id thing : this.recordIdList) { + SObjectType objType = thing.getSObjectType(); SObject record = (SObject)Type.forName(String.valueOf(objType)).newInstance(); - record.put('Id', recordId); + record.put('Id', thing); this.records.add(record); } } private List returnListOfSObjects() { - if(this.records == null) return new List(); + if(CollectionUtils.isNullOrEmpty(this.records)) return new List(); return this.records; } + + private SObjectType getSObjectType(Schema.SObjectField field) { + //There is supposed to be a built in Salesforce getDescribe() result for Schema.SObjectField, getReferenceTo() + //that should return a list of objects that field is associated with, but it has been broken for several years. + //This is a solution that was proposed on the Salesforce stack exchange and is the only work-around to a native lookup + //that I have been able to find. + Integer fieldHash = ((Object)field).hashCode(); + + // Build a map of hashcodes for each fieldDescribe taken from Schema Global Describe + Map globalDescribe = Schema.getGlobalDescribe(); + Map fieldHashCodeToSObjectTypeMap = new Map(); + for (String sobjname: globalDescribe.keySet()) { + for (Schema.SObjectField sobjField : globalDescribe.get(sObjName).getDescribe().fields.getMap().values()) + fieldHashCodeToSObjectTypeMap.put(((Object) sObjField).hashCode(), globalDescribe.get(sobjName)); + } + + return fieldHashCodeToSObjectTypeMap.get(fieldHash); + } } } \ No newline at end of file diff --git a/src/classes/SObjectTriggerHandler.cls b/src/classes/SObjectTriggerHandler.cls index 2ad10fc..6995175 100644 --- a/src/classes/SObjectTriggerHandler.cls +++ b/src/classes/SObjectTriggerHandler.cls @@ -6,18 +6,22 @@ public abstract class SObjectTriggerHandler extends NebulaCore implements ISObje private static Map> hashCodesForProcessedRecords = new Map>(); - @testVisible private enum TriggerContext { + @testVisible + private enum TriggerContext { BEFORE_INSERT, BEFORE_UPDATE, BEFORE_DELETE, AFTER_INSERT, AFTER_UPDATE, AFTER_DELETE, AFTER_UNDELETE } - @testVisible private TriggerContext context; // The current context of the trigger + @testVisible + private TriggerContext context; // The current context of the trigger private Integer hashCode; // The hash code for the current records private Boolean isTestMode; private Boolean isTriggerExecuting; // Checks if the code was called by a trigger - @testVisible private List recordList, oldRecordList; - @testVisible private Map recordMap, oldRecordMap; + @testVisible + private List recordList, oldRecordList; + @testVisible + private Map recordMap, oldRecordMap; public SObjectTriggerHandler() { this(false); diff --git a/src/classes/SObjectTriggerHandler_Tests.cls b/src/classes/SObjectTriggerHandler_Tests.cls index 1e059b1..6d418d0 100644 --- a/src/classes/SObjectTriggerHandler_Tests.cls +++ b/src/classes/SObjectTriggerHandler_Tests.cls @@ -1,10 +1,5 @@ -/************************************************************************************************* -* This file is part of the Nebula Framework project, released under the MIT License. * -* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * -*************************************************************************************************/ @isTest private class SObjectTriggerHandler_Tests { - private class LeadTriggerHandlerTest extends SObjectTriggerHandler { public LeadTriggerHandlerTest() { super(true); @@ -24,7 +19,6 @@ private class SObjectTriggerHandler_Tests { } static List leadList = new List(); - static void setupData() { for(Integer i = 0; i < 5; i++) { Lead lead = new Lead( @@ -98,5 +92,4 @@ private class SObjectTriggerHandler_Tests { // Test.stopTest(); // } - } \ No newline at end of file diff --git a/src/classes/SObjectTypeDescriber.cls b/src/classes/SObjectTypeDescriber.cls index 51672cf..98236fd 100644 --- a/src/classes/SObjectTypeDescriber.cls +++ b/src/classes/SObjectTypeDescriber.cls @@ -1,7 +1,3 @@ -/************************************************************************************************* -* This file is part of the Nebula Framework project, released under the MIT License. * -* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * -*************************************************************************************************/ public without sharing class SObjectTypeDescriber { public Schema.SObjectType SObjectType {get; private set;} diff --git a/src/classes/SObjectTypeDescriber_Tests.cls b/src/classes/SObjectTypeDescriber_Tests.cls index afc814a..b607748 100644 --- a/src/classes/SObjectTypeDescriber_Tests.cls +++ b/src/classes/SObjectTypeDescriber_Tests.cls @@ -1,7 +1,3 @@ -/************************************************************************************************* -* This file is part of the Nebula Framework project, released under the MIT License. * -* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. * -*************************************************************************************************/ @isTest private class SObjectTypeDescriber_Tests { @@ -46,8 +42,10 @@ private class SObjectTypeDescriber_Tests { Schema.SObjectType expectedSObjectType = Schema.Lead.SObjectType; Test.startTest(); + SObjectTypeDescriber sobjectTypeDescriber = new SObjectTypeDescriber(expectedSObjectType); System.assertEquals(expectedSObjectType, sobjectTypeDescriber.SObjectType); + Test.stopTest(); } @@ -56,7 +54,9 @@ private class SObjectTypeDescriber_Tests { SObjectTypeDescriber sobjectTypeDescriber = new SObjectTypeDescriber(Schema.Lead.SObjectType); Test.startTest(); + System.assertEquals(true, sobjectTypeDescriber.validateSObjectFieldExists(Schema.Lead.Id)); + Test.stopTest(); } @@ -65,7 +65,9 @@ private class SObjectTypeDescriber_Tests { SObjectTypeDescriber sobjectTypeDescriber = new SObjectTypeDescriber(Schema.Lead.SObjectType); Test.startTest(); + System.assertEquals(false, sobjectTypeDescriber.validateSObjectFieldExists(Schema.Task.Id)); + Test.stopTest(); } diff --git a/src/classes/TestingUtils.cls b/src/classes/TestingUtils.cls index 6baa897..b572c38 100644 --- a/src/classes/TestingUtils.cls +++ b/src/classes/TestingUtils.cls @@ -27,7 +27,7 @@ public class TestingUtils { } public static SObject setReadOnlyField(SObject sobj, SObjectField fieldName, String value) { - return setReadOnlyField(sobj, new Map{fieldName => value}); + return setReadOnlyField(sobj,new Map{fieldName => value}); } public static SObject setReadOnlyField(SObject sobj, Map changesToFields) { @@ -44,5 +44,4 @@ public class TestingUtils { return (SObject)JSON.deserialize(serializedRecord, SObject.class); } - } \ No newline at end of file