Created
December 19, 2017 21:09
-
-
Save anonymous/32e14c2002c5f79896ba33cef7236f1a to your computer and use it in GitHub Desktop.
Update to include checkboxes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Apex doesn't expose dependent picklist info directly, but it's possible to expose. | |
* Approach: | |
* * Schema.PicklistEntry doesn't expose validFor tokens, but they are there, and can be accessed by serializing to JSON | |
* (and then for convenience, deserializing back into an Apex POJO) | |
* * validFor tokens are converted from base64 representations (e.g. gAAA) to binary (100000000000000000000) | |
* each character corresponds to 6 bits, determined by normal base64 encoding rules. | |
* * The binary bits correspond to controlling values that are active - e.g. in the example above, this dependent option | |
* is available for the first controlling field only. | |
* | |
* by Benj Kamm, 2017 | |
* CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0/us/) | |
*/ | |
public class DependentPicklistUtil { | |
public static Map<String, List<String>> getDependentOptionsImpl(Schema.SObjectField theField, Schema.SObjectField ctrlField) { | |
// validFor property cannot be accessed via a method or a property, | |
// so we need to serialize the PicklistEntry object and then deserialize into a wrapper. | |
system.debug(ctrlField.getDescribe().getType()); | |
List<Schema.PicklistEntry> contrEntries = new List<Schema.PicklistEntry>(); | |
// Set up the return container - Map<ControllingValue, List<DependentValues>> | |
Map<String, List<String>> objResults = new Map<String, List<String>>(); | |
List<String> controllingValues = new List<String>(); | |
//Here we check the type, because dependent picklists can be based off of checkboxes, or other picklists. | |
//If the controlling field is a checkbox, add 'Unchecked and 'Checked' values to objResults, and controllingValues. | |
//If it is a picklist, continue the code as it did normally. | |
if(String.valueOf(ctrlField.getDescribe().getType()) == 'BOOLEAN'){ | |
objResults.put('Unchecked', new List<String>()); | |
objResults.put('Checked', new List<String>()); | |
controllingValues.add('Unchecked'); | |
controllingValues.add('Checked'); | |
} | |
else if(String.valueOf(ctrlField.getDescribe().getType()) == 'PICKLIST'){ | |
contrEntries = ctrlField.getDescribe().getPicklistValues(); | |
for (Schema.PicklistEntry ple : contrEntries) { | |
String label = ple.getLabel(); | |
objResults.put(label, new List<String>()); | |
controllingValues.add(label); | |
} | |
} | |
List<PicklistEntryWrapper> depEntries = | |
DependentPicklistUtil.wrapPicklistEntries(theField.getDescribe().getPicklistValues()); | |
system.debug(depEntries); | |
for (PicklistEntryWrapper plew : depEntries) { | |
system.debug(plew); | |
String label = plew.label; | |
String validForBits = base64ToBits(plew.validFor); | |
system.debug(validForBits); | |
for (Integer i = 0; i < validForBits.length(); i++) { | |
// For each bit, in order: if it's a 1, add this label to the dependent list for the corresponding controlling value | |
String bit = validForBits.mid(i, 1); | |
system.debug(bit); | |
system.debug(i); | |
if (bit == '1') { | |
objResults.get(controllingValues.get(i)).add(label); | |
} | |
} | |
} | |
return objResults; | |
} | |
// Convert decimal to binary representation (alas, Apex has no native method :-( | |
// eg. 4 => '100', 19 => '10011', etc. | |
// Method: Divide by 2 repeatedly until 0. At each step note the remainder (0 or 1). | |
// These, in reverse order, are the binary. | |
public static String decimalToBinary(Integer val) { | |
String bits = ''; | |
while (val > 0) { | |
Integer remainder = Math.mod(val, 2); | |
val = Integer.valueOf(Math.floor(val / 2)); | |
bits = String.valueOf(remainder) + bits; | |
} | |
return bits; | |
} | |
// Convert a base64 token into a binary/bits representation | |
// e.g. 'gAAA' => '100000000000000000000' | |
public static String base64ToBits(String validFor) { | |
if (String.isEmpty(validFor)) return ''; | |
String validForBits = ''; | |
for (Integer i = 0; i < validFor.length(); i++) { | |
String thisChar = validFor.mid(i, 1); | |
Integer val = base64Chars.indexOf(thisChar); | |
String bits = decimalToBinary(val).leftPad(6, '0'); | |
validForBits += bits; | |
} | |
return validForBits; | |
} | |
private static final String base64Chars = '' + | |
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + | |
'abcdefghijklmnopqrstuvwxyz' + | |
'0123456789+/'; | |
private static List<PicklistEntryWrapper> wrapPicklistEntries(List<Schema.PicklistEntry> PLEs) { | |
return (List<PicklistEntryWrapper>) | |
JSON.deserialize(JSON.serialize(PLEs), List<PicklistEntryWrapper>.class); | |
} | |
public class PicklistEntryWrapper { | |
public String active {get; set;} | |
public String defaultValue {get; set;} | |
public String label {get; set;} | |
public String value {get; set;} | |
public String validFor {get; set;} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment