Monday, October 15, 2012



As Salesforce is becoming more and more advanced with every release we developer are trying to cope up with the new features released.
Salesforce are releasing awesome features with every release. One of the most remarkable feature is fieldsets.

Fieldsets takes away the most annoying problem of visualforce pages i.e. it makes the pages dynamic!!. Yes Dynamic. The let of configure the fields that
appear in your visualforce page.

How to use fieldsets in your visualforce page.??

<apex:page controller="AccountCon">  
   <apex:form>  
     <apex:pageblock>  
       <apex:pageblocksection columns="1">  
         <apex:repeat value="{!$ObjectType.Account.FieldSets.AccountFieldSet}" var="f">  
             <apex:inputfield value="{!accObj[f]}">  
         </apex:inputfield>  
       </apex:repeat>  
     </apex:pageblocksection>  
   </apex:pageblock>  
  </apex:form>  
 </apex:page>  

public class AccountCon(){  
  public Account accObj{get;set;}  
  public AccountCon(){  
  accObj = [SELECT id,Name FROM Account LIMIT 1];  
  }  
 }  


Well easy enough?
But there lies a problem with fieldsets. In the above example you can see that a static query brings out data from salesforce objects. It will work
just perfect, until and unless some new field that is not included in query is introduced in the query. Once such field is included the code will throw an
exception.

Solution??
Make your query as dynamic as fieldsets!!
To do this I have devised a util class that dynamically generates query using fieldset/fieldsets. Just pass the object name and fieldset name this
will generate a dynamic query according to the parameters passed. Use the returned string to query the data.

Show Me The Code!!
Below is the util class that can be used to generate dynamic query from fieldsets.


 /*  
 *This Class contains utility methods that are used by different classes  
 *in the Org  
 **/  
 public class AVCommonUtils{  
   Map<String, Schema.SObjectType> globalDescribe;   
   public AvCommonUtils(){  
     globalDescribe=Schema.getGlobalDescribe();  
   }  
   /*This method return queries form a single fieldset  
   public String generateQueryFromFieldSet(String sObjectName,String fieldSet,Set<String> additionalFields,String whereClause){  
     return generateQueryFromFieldSets(sObjectName,new Set<String>{fieldSet},additionalFields,whereClause);   
   }  
   /*  
   *This method generates query according to passed in object and fieldsets(plural) name  
   **/  
   public String generateQueryFromFieldSets(String sObjectName,Set<String> fieldSets,Set<String> additionalFields,String whereClause){  
     Set<String> fields = new Set<String>{'Id'};  
     String query='SELECT Id';  //initial query  
     if(additionalFields!=null)  
     for( String fs : additionalFields ) {            
       //add only unique fields  
       if(!fields.contains(fs)){  
         //maintain a set of fields so that only unique fields are added in query  
         fields.add(fs);  
         query = query+','+fs;  
       }      
     }  
     //describe the provided sObject  
     Schema.DescribeSObjectResult res=globalDescribe.get(sObjectName).getDescribe();  
     //get the fields set map  
     Map<String, Schema.FieldSet> fieldSetMap= res.fieldSets.getMap();  
     //iterate through provided fieldsets and generate query  
     for(String fieldSetName : fieldSets){  
       Schema.FieldSet fs = fieldSetMap.get(fieldSetName);  
       for( Schema.FieldSetMember fsm : fs.getFields() ) {            
         //add only unique fields  
         if(!fields.contains(fsm.getFieldPath())){  
           //maintain a set of fields so that only unique fields are added in query  
           fields.add(fsm.getFieldPath());  
           query = query+','+fsm.getFieldPath();  
         }      
       }  
     }  
     query = (whereClause == '' || whereClause ==null)   
             ? (query + ' FROM '+sObjectName)   
             : (query + ' FROM '+sObjectName + ' WHERE ' + whereClause);  
     return query;  
   }  
 }  


How to use the util class??
Let us rewrite the above controller "AccountCon" using the util class.

 public class AccountCon(){   
  public Account accObj{get;set;}   
  public AccountCon(){   
      AVCommonUtils util = new AVCommonUtils();  
      String query = util.generateQueryFromFieldSet('Account','AccountFieldSet',null,'LIMIT 1');  
       accObj = database.query(query);    
  }   
  }   


Well the util classs has two methods.

  1. generateQueryFromFieldSet : This method generates query from only one fieldset
  2. generateQueryFromFieldSets: This method takes in a set of fieldset name to generate query.