55public class SobjectQueryBuilder extends Soql {
66
77 private String displayFieldApiName ;
8+ private List <String > polymorphicFieldStatements ;
89 private List <String > childRelationshipQueries ;
910 private Boolean forReference , forUpdate , forView , includeLabels , includeFormattedValues ;
1011
1112 public SobjectQueryBuilder (Schema.SobjectType sobjectType ) {
1213 super (sobjectType , true );
1314
14- this .displayFieldApiName = this .getDisplayFieldApiName (this .sobjectType );
15- this .childRelationshipQueries = new List <String >();
16- this .forReference = false ;
17- this .forUpdate = false ;
18- this .forView = false ;
19- this .includeLabels = false ;
20- this .includeFormattedValues = false ;
15+ this .displayFieldApiName = this .getDisplayFieldApiName (this .sobjectType );
16+ this .polymorphicFieldStatements = new List <String >();
17+ this .childRelationshipQueries = new List <String >();
18+ this .forReference = false ;
19+ this .forUpdate = false ;
20+ this .forView = false ;
21+ this .includeLabels = false ;
22+ this .includeFormattedValues = false ;
2123
2224 this .addDefaultFields ();
2325 }
@@ -79,6 +81,53 @@ public class SobjectQueryBuilder extends Soql {
7981 return this .addFields (queryFields , fieldCategory );
8082 }
8183
84+ public SobjectQueryBuilder addPolymorphicFields (Schema.SobjectField polymorphicRelationshipField ) {
85+ return addPolymorphicFields (polymorphicRelationshipField , new Map <Schema .SobjectType , List <Schema .SobjectField >>());
86+ }
87+
88+ public SobjectQueryBuilder addPolymorphicFields (Schema.SobjectField polymorphicRelationshipField , Map <Schema .SobjectType , List <Schema .SobjectField >> fieldsBySobjectType ) {
89+ Map <Schema .SobjectType , List <Soql .QueryField >> queryFieldsBySobjectType = new Map <Schema .SobjectType , List <Soql .QueryField >>();
90+ for (Schema .SobjectType sobjectType : fieldsBySobjectType .keySet ()) {
91+ List <Soql .QueryField > queryFields = new List <Soql .QueryField >();
92+ for (Schema .SobjectField field : fieldsBySobjectType .get (sobjectType )) {
93+ queryFields .add (new Soql .QueryField (field ));
94+ }
95+ queryFieldsBySobjectType .put (sobjectType , queryFields );
96+ }
97+ return this .addPolymorphicFields (polymorphicRelationshipField , queryFieldsBySobjectType );
98+ }
99+
100+ public SobjectQueryBuilder addPolymorphicFields (Schema.SobjectField polymorphicRelationshipField , Map <Schema .SobjectType , List <Soql .QueryField >> queryFieldsBySobjectType ) {
101+ String polymorphicFieldStatement = queryFieldsBySobjectType .isEmpty () ? ' ' : ' TYPEOF ' + polymorphicRelationshipField .getDescribe ().getRelationshipName ();
102+ for (Schema .SobjectType sobjectType : queryFieldsBySobjectType .keySet ()) {
103+ List <String > fieldNames = new List <String >();
104+ for (Soql .QueryField queryField : queryFieldsBySobjectType .get (sobjectType )) {
105+ fieldNames .addAll (this .getFieldsToQuery (queryField , Soql .FieldCategory .ACCESSIBLE ));
106+ }
107+ fieldNames .sort ();
108+ polymorphicFieldStatement += ' WHEN ' + sobjectType + ' THEN ' + String .join (fieldNames , ' , ' );
109+ }
110+
111+ // The Name object contains the list of all possible polymorphic fields in the org
112+ List <String > supportedPolymorphicFieldNames = new List <String >();
113+ for (Schema .SobjectField field : Schema .Name .SobjectType .getDescribe ().fields .getMap ().values ()) {
114+ supportedPolymorphicFieldNames .addAll (this .getFieldsToQuery (new QueryField (field ), Soql .FieldCategory .ACCESSIBLE ));
115+ }
116+ supportedPolymorphicFieldNames .sort ();
117+ if (! queryFieldsBySobjectType .isEmpty ()) polymorphicFieldStatement += ' ELSE ' ;
118+ else if (queryFieldsBySobjectType .isEmpty ()) {
119+ String supportedPolymorphicFieldPrefix = queryFieldsBySobjectType .isEmpty () ? ' Who.' : ' ' ;
120+ for (Integer i = 0 ; i < supportedPolymorphicFieldNames .size (); i ++ ) {
121+ supportedPolymorphicFieldNames [i ] = supportedPolymorphicFieldPrefix + supportedPolymorphicFieldNames [i ];
122+ }
123+ }
124+ polymorphicFieldStatement += String .join (supportedPolymorphicFieldNames , ' , ' );
125+ if (! queryFieldsBySobjectType .isEmpty ()) polymorphicFieldStatement += ' END' ;
126+
127+ this .polymorphicFieldStatements .add (polymorphicFieldStatement );
128+ return this .setHasChanged ();
129+ }
130+
82131 public SobjectQueryBuilder includeLabels () {
83132 this .includeLabels = true ;
84133 return this .setHasChanged ();
@@ -209,10 +258,15 @@ public class SobjectQueryBuilder extends Soql {
209258 if (this .query != null && ! this .hasChanged ) return this .query ;
210259
211260 String queryFieldString = this .getQueryFieldString ();
261+
262+ String polymorphicFieldsString = String .join (this .polymorphicFieldStatements , ' , ' );
263+ String polymorphicFieldsDelimiter = ! String .isEmpty (queryFieldString ) && ! String .isEmpty (polymorphicFieldsString ) ? ' , ' : ' ' ;
264+
212265 String childRelationshipsQueryFieldString = this .getChildRelationshipsQueryFieldString ();
213- String childRelationshipDelimiter = ! String .isEmpty (queryFieldString ) && ! String .isEmpty (childRelationshipsQueryFieldString ) ? ' , ' : ' ' ;
266+ String childRelationshipDelimiter = ! String .isEmpty (queryFieldString ) && ! String .isEmpty (childRelationshipsQueryFieldString ) ? ' , ' : ' ' ;
214267
215268 this .query = ' SELECT ' + queryFieldString
269+ + polymorphicFieldsDelimiter + polymorphicFieldsString
216270 + childRelationshipDelimiter + childRelationshipsQueryFieldString
217271 + ' FROM ' + this .sobjectType
218272 + super .doGetUsingScopeString ()
@@ -330,7 +384,7 @@ public class SobjectQueryBuilder extends Soql {
330384 return null ;
331385 }
332386
333- private String getParentObjectNameField (Schema.DescribeFieldResult fieldDescribe ) {
387+ private String getParentSobjectNameField (Schema.DescribeFieldResult fieldDescribe ) {
334388 String relationshipName = fieldDescribe .getRelationshipName ();
335389 Schema .SobjectType parentSobjectType = fieldDescribe .getReferenceTo ()[0 ];
336390 String nameField = this .getDisplayFieldApiName (parentSobjectType );
@@ -341,7 +395,6 @@ public class SobjectQueryBuilder extends Soql {
341395 }
342396
343397 private List <String > getFieldsToQuery (Soql.QueryField queryField , Soql.FieldCategory fieldCat ) {
344- // List<String> fieldsToReturn = super.doGetFieldsToQuery(queryField, fieldCat);
345398 List <String > fieldsToReturn = new List <String >();
346399
347400 if (fieldCat == null ) return fieldsToReturn ;
@@ -367,15 +420,15 @@ public class SobjectQueryBuilder extends Soql {
367420 }
368421
369422 // If the field is a lookup, then we need to get the name field from the parent object
370- if (queryField .getDescribe ().getType ().name () == ' Reference ' ) {
423+ if (queryField .getDescribe ().getType ().name () == ' REFERENCE ' ) {
371424 if (queryField .getDescribe ().isNamePointing ()) {
372425 String fieldPath = queryField .getFieldPath ();
373426 Integer indx = fieldPath .lastIndexOf (queryField .getDescribe ().getName ());
374427 String parentTypeFieldPath = fieldPath .substring (0 , indx ) + queryField .getDescribe ().getRelationshipName () + ' .Type' ;
375428 fieldsToReturn .add (parentTypeFieldPath );
376429 }
377430
378- String parentNameField = this .getParentObjectNameField (queryField .getDescribe ());
431+ String parentNameField = this .getParentSobjectNameField (queryField .getDescribe ());
379432 if (parentNameField != null ) {
380433 fieldsToReturn .add (parentNameField );
381434 // Record type names can be translated, so include the translation
0 commit comments