Converting uppercased 18-digit Id to valid Id
I ported Daniel Ballinger's answer here to Apex
:
static String CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345';
static List<Boolean> getBitPattern(String c)
{
Integer index = CHARS.indexOf(c.toUpperCase());
List<Boolean> result = new List<Boolean>();
for (Integer bitNumber = 0; bitNumber < 5; bitNumber++)
result.add((index & (1 << bitNumber)) != 0);
return result;
}
static String repairCasing(String input)
{
if (String.isBlank(input) || input.length() != 18) return input;
List<Boolean> toUpper = new List<Boolean>();
toUpper.addAll(getBitPattern(String.valueOf(input.substring(15, 16))));
toUpper.addAll(getBitPattern(String.valueOf(input.substring(16, 17))));
toUpper.addAll(getBitPattern(String.valueOf(input.substring(17, 18))));
String output = '';
for (Integer i = 0; i < 15; i++)
{
String c = String.valueOf(input.substring(i, i+1));
output += toUpper[i] ? c.toUpperCase() : c.toLowerCase();
}
output += input.substring(15, 18).toUpperCase();
return output;
}
I tested it and it worked:
Id value1 = Id.valueOf('00129000007Kbn7AAC');
Id value2 = Id.valueOf('00129000007KBN7AAC');
system.assertEquals(value1, repairCasing(value2));
Parallel to Adrian's response I also cooked up my own version for reference;
public static Id correctCapitalizedId(String input) {
String keyString = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345', result = '';
Integer i = 0, s = 15;
if (input.length() != 18) {
return null;
}
for (String seq : input.split('(?<=\\G.{5})')) {
Integer chk = keyString.indexOf(input.mid(s++,1));
i = 0;
for (String chr : seq.split('')) {
result += seq.length() != 5 ? '' : (chk & (i == 0 ? ++i : (i*=2))) == 0 ? chr.toLowerCase() : chr;
}
}
return Id.valueOf(result);
}