Sunday 28 July 2013

Custom Cloning of Object using dynamic SOQL

If you want to clone custom object along with its child objects then standard won't work. Standard cloning only clone the object record itself and does not clone its child objects.

In order to fulfil that requirement you have create custom clone button and invoke a webservice. Javascript which needs to be written to call webservice is not included in this example.

Standard Clone method only copy the fields which are queried from object and as you know fields may change during developmemt so in order to make a solution flexible and not dependent on fields we can make dynamic SOQL for quering the fields.

The below example will clone object (Clone_Object__c) record along with its child (Clone_Object_Child__c) record and redirect the user to new cloned record without having dependency of fields.

Code Snippet
 // Class is global because of webservice  
 global class CloneClass {  
      // Returns a dynamic SOQL statement for the whole object, includes only creatable fields since we will be inserting a cloned result of this query  
      public static string getCreatableFieldsSOQL(String objectName, String whereClause){  
           String selects = '';  
           if (whereClause == null || whereClause == ''){ return null; }  
           // Get a map of field name and field token  
           Map<String, Schema.SObjectField> fMap = Schema.getGlobalDescribe().get(objectName.toLowerCase()).getDescribe().Fields.getMap();  
           list<string> selectFields = new list<string>();  
           if (fMap != null){  
                for (Schema.SObjectField ft : fMap.values()){ // loop through all field tokens (ft)  
                     Schema.DescribeFieldResult fd = ft.getDescribe(); // describe each field (fd)  
                     if (fd.isCreateable()){ // field is creatable  
           if (!selectFields.isEmpty()){  
                for (string s:selectFields){  
                     selects += s + ',';  
                if (selects.endsWith(',')){selects = selects.substring(0,selects.lastIndexOf(','));}  
           return 'SELECT ' + selects + ' FROM ' + objectName + ' WHERE ' + whereClause;  

      // Clone method and redirect the user to cloned record.  
      public String clone(String cloneObjId){  
           String soql = CloneClass.getCreatableFieldsSOQL('Clone_Object__c','id=\''+cloneObjId+'\''); // Static method is called by class  
           Clone_Object__c cloneObj = (Clone_Object__c')Database.query(soql);  
           Clone_Object__c newcloneObj = cloneObj.clone(false, true);  
           newcloneObj.Name = 'Clone-'+ cloneObj.Name;  
           insert newcloneObj;  
           List<Clone_Object_Child__c> lstcloneObjChild = new List<Clone_Object_Chld__c'>();  
           String soqlCloneObjChild = CloneClass.getCreatableFieldsSOQL('Clone_Object_Child__c'','Clone_Object__c'=\''+cloneObjId+'\'');  
           List<Clone_Object_Child__c> lstcloneObjChild = (List<Clone_Object_Child__c'>)Database.query(soqlCloneObjChild);  
           for(Clone_Object_Child__c cloneObjChild : lstcloneObjChild){  
                Clone_Object_Child__c newcloneObjChild = cloneObjChild.clone(false);  
                newcloneObjChild.Clone_Object__c =;  
                newcloneObjChild.Is_default__c = false;  
           insert lstcloneObjChild;  
           return String.valueOf( new PageReference('/'+newcloneObj.Id+'/e').getUrl() + '?retURL='+newcloneObj.Id); //This lands on the new cloned record n Edit Mode.   

      // Webservice which is called by custom button  
      webservice static String deepClone(String aid){  
           Clone_Object__c cloneObj = [Select Id,Name, FROM Clone_Object__c' WHERE Id =: aid]; // aid : Id of record which we want to clone  
           CloneClass cloneClassObj = new CloneClass(cloneObj);  
           String p = cloneClassObj.clone(aid); // Calling class clone method and passing Id of record  
           return p;  

No comments:

Post a Comment