[SalesForce] Iterate over queried lookup fields

Example:

Opportunity Opp = [SELECT Name, Status__c, Zone__c, Invoice__r.Amount__c, Invoice__r.Date__c FROM Opportunity WHERE ID ='006a12nlfoenlew'];

I need to iterate over each field and see if the values are not null. If I want to check only Opportunity fields, I would do this:

Set<String> strFields = new Set<String>{'Name','Status__c','Zone__c'};

for(String s: strFields ){

//This prints the value of each field(included in the set) for the current Opportunity.
System.Debug(logginglevel.error,'*****'+Opportunity.get(s));

}

But, I need to get the values in lookup objects also. If I repeat the same,

Set<String> strFields = new Set<String>{'Invoice__r.Amount__c', 'Invoice__r.Date__c'};

for(String s: strFields ){

//This would throw "System.SObjectException: Invalid field Invoice__r.Amount__c for Opportunity" error.

System.Debug(logginglevel.error,'*****'+Opportunity.get(s));

}

Update: Even though the example I've give is very simple, In the code I'm working on, I've around 40 fields across 5 different look ups, ranging from 3-5 level deep relationships (Ex: Invoice__r.Task__r.Account.Contact.FirstName). I'm querying Opportunity(the base object) and I need to make sure the FirstName on contact is not null.

Is there a way I can iterate over, and get value in each field including lookup fields that are being queried?

Best Answer

You cannot call cross-object get. Take a look at the FieldReference class. It's open source, so you can just copy it into your org. Then you could do:

for (String invoiceField : invoiceFields)
    system.debug(FieldReference.build(invoiceField).getFrom(opportunity);

What you want probably cannot be accomplished in a clean way without recursive logic. If you want to do so without a helper class, you could do something along the lines of:

public with sharing class CrossObject
{
    public static Object get(SObject record, String field)
    {
        if (record == null) return null;
        if (!field.contains('.')) return record.get(field);
        record = record.getSObject(field.substringBefore('.'));
        field = field.substringAfter('.');
        return get(record, field);
    }
}