Apex Language Features
#100 - sObject Type
Implement the method isTypeAccount()
, which accepts a sObject as input and returns a true
if type of input is Account object else it should return as false
.
Given the following test code:
Account acc = new Account(name='Apple');
Boolean result = isTypeAccount(acc);
result
should be equal to true
public Boolean isTypeAccount(sObject record) {
if (record instanceof Account) {
return true;
}
return false;
}
public Boolean isTypeAccount(sObject record)
{
String sobjectType = record?.getSObjectType().getDescribe().getName();
return (sobjectType == 'Account');
}
#93 - Convert 15-digit ID to 18-digit ID
Implement the method convert15to18DigitId()
, which accepts a String of length 15 digit and returns a new String with 18 digit salesforce Id. If the input string length is not equal to 15 digits, then return -1
.
Given the following test code:
String fifteenDigit = '0SO90000000PBDu';
String eighteenDigit = convert15to18DigitId(fifteenDigit);
eighteenDigit should be equal to ‘0SO90000000PBDuGAO’
Note:
Use case 1: You have exported a Salesforce report with Ids. These Ids are 15 characters. You want to ensure that these Ids are not altered by Excel, you need to manage them with 18 characters.
Use case 2: You need to compare Ids but your comparison mechanism is not case sensitive. You will have to extend them to 18 characters
public String convert15to18DigitId(String fifteenDigit)
{
if (fifteenDigit?.length()==15) {
return (Id)fifteenDigit;
}
return '-1';
}
#97 - Handle Exception
Implement the method divide
which takes two integers a
and b
as input, divides a
by b
using the /
operator, and returns the result. If any exception occurs, the method should return the exception message.
Given the following test code:
String result = divide(10,0);
result should be Divide by 0
;
Given the following test code:
String result = divide(100, 18);
result should be 5
;. The result of integer division 100/19
is 5
with a remainder of 10
.
public String divide(Integer a, Integer b){
try {
String result = String.valueOf(a/b);
return result;
}
catch(Exception ex) {
return ex.getMessage();
}
}
#102 - Throw An Exception
Implement the method checkAccounts
, which accepts a list of accounts as an input and returns a list of accounts. The method should behave as follows:
- If all accounts in the list have
BillingCity
present, the method should return the original list. - If the passed list is null the method should throw the built-in
IllegalArgumentException
with messageaccounts should not be null
- If any of the accounts in the list do not have a
BillingCity
present, the method should throw the customAccountException
exception. Do not create new exception class - use theAccountException
class that has already been created for you.
Given the following test code:
List<Account> accounts = new List<Account>();
accounts.add(new Account(name ='Salesforce', BillingCity ='Boston'));
accounts.add(new Account(name ='Microsoft'));
The method callcheckAccounts(accounts);
should fail, throwing an AccountException.
public List<Account> checkAccounts(List<Account> accounts)
{
if (accounts == null) {
throw new IllegalArgumentException('accounts should not be null');
}
for (Account a : accounts) {
if (a.BillingCity == null) {
throw new AccountException('Invalid BillingCity');
}
}
return accounts;
}
//do not remove the following custom-defined exception
public class AccountException extends Exception {}
#94 - Safe Navigation Operator
Implement the method getAccountBillingCityWithSafeNavigation
, which accepts a list of accounts as an input and returns the BillingCity
in upper case of the first account in the list. Use the Safe Navigation (?.
) to ensure null
is returned in case the BillingCity
is null
.
Given the following test code:
List<Account> acts = new ListList<Account>();
acts.add(new Account(Name = 'Acme', BillingCity = 'Chicago'));
acts.add(new Account(Name = 'Dove', BillingCity = 'Boston'));
String result = getAccountBillingCityWithSafeNavigation(acts);
result should be ‘CHICAGO’
public String getAccountBillingCityWithSafeNavigation(List<Account> accounts){
String billingCity = accounts[0].BillingCity?.toUpperCase();
return billingCity;
}
#103 - Dynamic Field Values
Implement the method getFieldsValue
, which accepts the following inputs:
- An account
acc
- A list of strings
fields
, with each string in the list representing a valid field on the account object. - The method should return a list of values from the account record for fields listed in the list fields in the correct order.
Given the following test code:
Account acc = new Account(
Name = 'Salesforce',
BillingCity = 'Boston',
AnnualRevenue=10000, Rating='Hot');
List fields = new List{'Industry','Name','Rating'};
List result = getFieldsValue(acc, fields);
result should be [null, 'Salesforce', 'Hot']
public List<String> getFieldsValue(Account acc, List<String> fields) {
List<String> results = new List<String>();
for (String field : fields) {
String result = String.valueOf(acc.get(field));
results.add(result);
}
return results;
}
#95 - Serialize sObjects
Implement the method getAccountsInJSONFormat()
, a list of accounts and returns a list of accounts in string JSON format.
Given the following test code:
List<Account> accounts = new ListList<Account>();
accounts.add(new Account(Name = 'Acme', BillingCity = 'Chicago'));
accounts.add(new Account(Name = 'Dove', BillingCity = 'Boston'));
String result = getAccountsInJSONFormat(accounts);
result should be equals to
'[ {"attributes":
{"type":"Account"},
"Name":"Acme",
"BillingCity":"Chicago"},
{"attributes":
{"type":"Account"},
"Name":"Dove",
"BillingCity":"Boston"} ]';
public String getAccountsInJSONFormat(List<Account> accounts){
String JSONString = JSON.serialize(accounts);
return JSONString;
}
#101 - List of sObjects
Implement the method getListOfsObject()
, which accepts two parameters, a list of accounts, and a list of contacts, as an input and returns a list of sObjects. If both lists are empty or null, return an empty list of sObject.
Given the following test code:
List<Account> accounts = new List<Account>();
accounts.add(new Account(name ='Salesforce'));
accounts.add(new Account(name ='Microsoft'));
List<Contact> contacts= new List<Contact>();
contacts.add(new Contact(lastName = 'Benioff'));
contacts.add(new Contact(lastName = 'Taylor'));
List result = getListOfsObject(accounts,contacts);
result should be (Account:{Name=Salesforce}, Account:{Name=Microsoft}, Contact:{LastName=Benioff}, Contact:{LastName=Taylor})
Note: Adding different types into a list of sObjects can be used to perform operations on multiple object types in a single DML operation.
public List<sObject> getListOfsObject(List<Account> accounts, List<Contact> contacts) {
List<sObject> sobjects = new List<sObject>();
if (accounts != null) {
for (Account account : accounts) {
sobjects.add(account);
}
}
if (contacts != null) {
for (Contact contact : contacts) {
sobjects.add(contact);
}
}
return sobjects;
}
#96 - Deserialize sObjects
Implement the method getAccountsFromJSONString
, which takes a JSON string of a list of accounts as an input and returns a list of accounts. If the input string is empty or null, return null.
Given the following test code:
String inputJSON = '[
{
"attributes": {
"type":"Account",
"url":"/services/data/v55.0/sobjects/Account/00158000002zBhUAAU"
},
"Id" : "00158000002zBhUAAU",
"Name":"Customer1"
},
{
"attributes": {
"type":"Account",
"url":"/services/data/v55.0/sobjects/Account/00158000002zBhWAAU"
},
"Id":"00158000002zBhWAAU",
"Name":"Customer2"
}
]';
List<Account> result = getAccountsFromJSONString(inputJSON);
accounts.add(new Account(Name = 'Dove', BillingCity = 'Boston'));
result should be list of accounts (Account:{Id=00158000002zBhUAAU, Name=Customer1}, Account:{Id=00158000002zBhWAAU, Name=Customer2}
)
public List<Account> getAccountsFromJSONString(String inputJSON){
if (String.isBlank(inputJSON)) {
return null;
} else {
return (List<Account>) JSON.deserialize (inputJSON, List<Account>.class);
}
}
#106 - Context User
Implement the method getContextUserInformation()
, which returns a Map of the current logged in user’s (context user’s) UserName
, ProfileId
, EmailId
, and Type
as keys and their field values as corresponding values in the map.
Given the following sample code:
Map<String,String> userMap = getContextUserInformation();
The returned map should contain the following information:
Key | Value |
---|---|
EmailId | [email protected] |
ProfileId | 00e5g000021MG3eAAG |
Type | Standard |
UserName | [email protected] |
Note: These values will be different for every user as they depend on the running user.
public Map<String,String> getContextUserInformation() {
return new Map<String, String> {
'EmailId' => UserInfo.getUserEmail(),
'ProfileId'=> UserInfo.getProfileId(),
'Type' => UserInfo.getUserType(),
'UserName' => UserInfo.getUserName()
};
}
#105 - Trigger Validation
Implement the method validateInsert
, which accepts a newly inserted list of opportunities as an input and adds errors to the opportunity fields as follows: if the opportunity record’s StageName
is Closed Won
and the Description
is null or empty, add an error on the Description
field of that record with the error message set to Description should not be empty for Closed Won opportunity.
Please see the code snippet below for an example of how such a method can be used for custom validation in a before trigger:
Trigger OpportunityTrigger on Opportunity (before insert){
if (Trigger.isBefore){
OpportunityTriggerHandler handler =
new OpportunityTriggerHandler();
List<Opportunity> opportunities =
handler.validateInsert(Trigger.new);
}
}
Given the following test code:
List<Opportunity> oppList = new List<Opportunity>();
oppList.add(new Opportunity(
StageName = 'Closed Lost', Description = 'Testing'));
oppList.add(new Opportunity(
StageName = 'Closed Won'));
oppList.add(new Opportunity(
StageName = 'Closed Won',Description ='Testing'));
oppList.add(new Opportunity(
StageName = 'Qualification'));
validateInsert(oppList);
oppList
should now contain 1 error message on 2nd record of the list with proper error message on the Description field.
public void validateInsert(List<Opportunity> opportunities){
String msg = 'Description should not be empty for Closed Won opportunity.';
for(Opportunity opp : opportunities) {
if((opp.StageName == 'Closed Won') &&
(opp.Description == '' || opp.Description == null)){
opp.Description.addError(msg);
}
}
}
#98 - Sort List of sObjects
Implement the method getAccounts()
, function, which accepts a list of accounts as input and returns a new list of accounts sorted in descending order based on the Annual Revenue field.
Given the following test code:
List<Account> accounts = new List<Account>();
accounts.add(new Account(Name='Accenture', AnnualRevenue = 30));
accounts.add(new Account(Name='TCS',AnnualRevenue = 10));
accounts.add( new Account( Name='Apple', AnnualRevenue = 100) );
List<Account> result = getAccounts(accounts);
result = (Account:{Name=Apple, AnnualRevenue=100}, Account:{Name=Accenture, AnnualRevenue=30}, Account:{Name=TCS, AnnualRevenue=10})
public List<Account> getAccounts(List<Account> accounts) {
if(accounts == null) {
return null;
}
List<AccountWrapper> accList = new List<AccountWrapper>();
for(Account acc : accounts) {
accList.add(new AccountWrapper(acc));
}
accList.sort();
for(Integer i=0; i<accounts.size(); i++) {
accounts[i] = accList[i].acc;
}
return accounts;
}
public class AccountWrapper implements Comparable {
public Account acc;
public AccountWrapper(Account acc) {
this.acc = acc;
}
public Integer compareTo(Object compareTo) {
AccountWrapper aw = (AccountWrapper) compareTo;
if (aw.acc.AnnualRevenue > this.acc.AnnualRevenue) {
return 1;
}
return -1;
}
}