Object Type Comparison Using Apex

Every developer will, at some point, need to check if a generic SObject is a type of another concrete SObject type.

Before I get started I’d like to give a shout out to Salesforce Girl, who’s blog inspired this.

A common place where this is used is the owner of a custom object or the who.id and what.id of objects that contain polymorphic keys like Task. One would be inclined to use the Apex instanceof keyword to perform this test. The problem with this is instanceof only compares a concrete object to a class.. This won’t work when comparing a generic SObject to something else.

Let’s look at an example using a custom object I’ve created called Project:

Project__c = [SELECT id, ownerId FROM Project__c][0];

 

We want to check if the Project’s owner is a User or Group prior to performing further operations on the result. How can we accomplish this? Here’s one way:

SObject comp;
try{
    comp = (Group)Group.SObjectType.newSObject(project.ownerId);
}catch(System.SObjectException e){
    //we don't have a group we have a user
    comp = (User)User.SObjectType.newSObject(project.ownerId);
}
// do something with comp

On line three we are attempting to create a new Group object using the ownerId. If the ownerId is an invalid group id, an exception will be thrown. We’re handling this in the catch block and since the only alternative is that ownerId is a valid id for a user we’re compensating in the exception and creating a new User object in line 6.

We can easily verify this with:

	System.debug(comp.getSObjectType());

This works where our options are binary, as in this example, but it’s not optimal and it doesn’t offer much for reusability. What if we also wanted to check the whoId of any related tasks of our project? Our code could get very messy in a hurry. Extra credit if you’ve asked what happens if line 6 throws an exception.

By the way, If you try this using instanceof you would get an error mentioning incompatible types and apocalyptic prophecies.

So how do we make this better? Well, one way is to make the comparison more reusable. Another is to make it more generic to handle broader use cases. Let’s create a new class that we can call to handle the comparison for us.

public class ObjectHelper{
	public static boolean compare(SObject compare, String checkType){
		try{
Schema.SObjectType targetType = Schema.getGlobalDescribe().get(checkType);
			if(targetType == null){
				return false;
			}else if( compare.getSObjectType() == targetType){
				return true;
			}else{
				return false;
			}
		}catch(Exception e){
			//handle exception
		             return false;
		}
		return false;
	}
}

Here we pass in arguments for the SObject we want to compare and the type we want to compare against. In line four we get the SObjectType information for the object we want to compare to. Line five is pretty self-explanatory. Line seven we compare the SObject type against the type we are comparing to and return true if they are the same. We return false if there were no exceptions and the types are not the same. Now we can use our new class with the same problem.

Project__c project = [select id, ownerId from project__c][0];
Schema.SObjectType oType = project.ownerId.getSObjectType();
SObject myObj = oType.newSObject(project.ownerId);
If( ObjectHelper.compare(myObj, 'User')){
	//do something with the User
} else {
	//do something with Group
}

You can grab the Gist for this to play with more.

In this post I focused on a single custom object but you could use this same approach any time you want to compare a generic SObject to another type. I’ve proposed one way to do this. Can you think of a better one? If so please comment.

Follow me on Twitter @ryanjupton

Published
May 28, 2013
Topics:

Leave your comments...

Object Type Comparison Using Apex