Showing posts with label Schema. Show all posts
Showing posts with label Schema. Show all posts

Tuesday, March 19, 2013

Apex, check object by Id. Ver 3.0

This is new version of method that I mentioned in my previous topics: 'Apex, check object by Id' and 'Apex, check object by Id. Update.'. Earlier, if Id.valueOf( objectIdString ) == null we had an error 'FATAL_ERROR System.StringException: Invalid id'. To avoid this error I use 'instanceof'. So now will not have any errors, even if we do not have such object in system like 'objectTypeNameString' or it will be null.
public static Boolean isIdsObjectTypeEqualToStringObjectType( String objectIdString, 
                 String objectTypeNameString ){
 
 return ( ( objectIdString instanceof Id )  
             && Id.valueOf( objectIdString ).getSObjectType().getDescribe().getName().equals( objectTypeNameString ) );
}
Test class will be the same.

Enjoy.

Sunday, December 23, 2012

Check if object is shareable through the S2S connection.

Today while building the page for S2S connection and record management, I have faced with issue of the necessity to filter object types that are available for sharing. It's inconvenient that PartnerNetworkConnection object does not have information what exact objects are published/subscribed in connection. While investigating this issues, I found out that the objects that can be shared have two similar fields: ConnectionSentId and ConnectionReceivedId. So to form a list of object types that are available for sharing we need to go through all objects and check up if their fieldset contains these fields. As in the example:
Map<String, Schema.SObjectType> globalDescrideMap = Schema.getGlobalDescribe();
List<Schema.SObjectType> objectsForConnectionList = new List<Schema.SObjectType>();

for( Schema.SObjectType objectItem : globalDescrideMap.values() ){
    if( objectItem.getDescribe().fields.getMap().get('ConnectionSentId') ) != null ){
        objectsForConnectionList.add( objectItem );
    }
}
But in our case we have more than 100 objects that are available for sharing and this code gets an error:
System.LimitException: Too many fields describes: 101
Thus we can create one example of the object and try to add these fields. If the object can be shared we will have the error that this field is not writeable:
System.SObjectException: Field ConnectionSentId is not editable
In case this object is not shareable the error will be:
System.SObjectException: Invalid field ConnectionSentId for Training_Class_Attendee__History
This is the code sample:
Map<String, Schema.SObjectType> globalDescrideMap = Schema.getGlobalDescribe();
List<Schema.SObjectType> objectsForConnectionList = new List<Schema.SObjectType>();

for( Schema.SObjectType objectItem : globalDescrideMap.values() ){
 try{
        SObject currentObject = objectItem.newSObject();
  currentObject.put( 'ConnectionSentId', null);
    }catch( SObjectException soExpt ){
        if( soExpt.getMessage() == 'Field ConnectionSentId is not editable' )
            objectsForConnectionList.add( objectItem );
    }
}
If you have any better solution for this issue, please comment.
Enjoy.

Friday, November 23, 2012

Apex, check object by Id. Update.

This is update to my previous topic 'Apex, check object by Id'. In Apex version 26 I found a better solution than go though the List of Schema. Id now have method called getSObjectType(). We can use it to get name of the object. And compare it to existing one. getSObjectType() gives us Schema.SObjectType.
public static Boolean isIdsObjectTypeEqualToStringObjectType( String objectIdString,
                                                              String objectTypeNameString ){
    Boolean isEqual = false;

    if( Id.valueOf( objectIdString ).getSObjectType().getDescribe().getName().equals( objectTypeNameString ) ){
    // getSObjectType().getDescribe().getName() gives us String that we can compare to incoming object type.
        isEqual = true;
    }
    return isEqual;
}
Test class will be the same.

Enjoy.

Sunday, October 28, 2012

Apex, check object by Id.

Some times we need to know if Id matches the object we need. This method returns true, if matches:
public static Boolean isIdsObjectTypeEqualToStringObjectType( String objectIdString,
                                                              String objectTypeNameString ){
    Map<String, Schema.SObjectType> globalDescrideMap = Schema.getGlobalDescribe();    
    Boolean isEqual = false;
            
    Map<String,String> keyPrefixMap = new Map<String,String>{};

    for( String objectItem : globalDescrideMap.keySet() ){
       Schema.DescribeSObjectResult objectDescribe =  globalDescrideMap.get(objectItem).getDescribe();
       keyPrefixMap.put( objectDescribe.getKeyPrefix(), objectDescribe.getName() );
    }
    
    if( keyPrefixMap.get( objectIdString.subString( 0, 3 ) ) == objectTypeNameString ) isEqual = true;
    
    return isEqual;
}
Recommend to to move initialization of globalDescrideMap to top of class. And of course test:
@isTest( seeAllData = false ) private static void testIsIdsObjectTypeEqualToStringObjectType(){
    Integer NUMBER_TO_INSERT = 5;
    List<Account> testAccountList = new List<Account>();
    List<Boolean> testEqualsList = new List<Boolean>();
    List<Boolean> testNotEqualsList = new List<Boolean>();
    String accountObjectType = Account.getsObjectType().getDescribe().getName();
    
    for( Integer i = 0; NUMBER_TO_INSERT > i; i++ )
        testAccountList.add( TestingUtils.createTestAccount( null ) );
        
    insert testAccountList;
    
    Test.startTest();
        for( Account accountItem : testAccountList )
            testEqualsList.add( BluewolfDevUtils.isIdsObjectTypeEqualToStringObjectType( ( String )accountItem.Id, accountObjectType ) );
        
        for( Account accountItem : testAccountList )
            testNotEqualsList.add( BluewolfDevUtils.isIdsObjectTypeEqualToStringObjectType( ( String )accountItem.Id, 'Account__c' ) );
    Test.stopTest();
    
    for( Boolean testEqualsItem : testEqualsList )
        System.assertEquals( true, testEqualsItem );
    
    for( Boolean testNotEqualsItem : testNotEqualsList )
        System.assertEquals( false, testNotEqualsItem );
}
Enjoy.

UTD: New method.

Salesforce: Unified object creator.

Everytime when we write test classes, we need to a create a big number of data to apply them to the methods that we are testing. We create a lot of methods leading to the creation of these or those objects. I have created the method leading to the creation of any type objects we need:
public with sharing class Utilities {
    /*
        Method for creating any Object
    */
    
    public static List<sObject> createObject(Integer numberToCreate, 
                                             Boolean doInsert, 
                                             Schema.SObjectType objectType, 
                                             Map<String, String> fieldsMap){    
        List<sObject> objectsList = new List<sObject>();
        List<String> objectFields = new List<String>();
        List<String> fieldsList = new List<String>();
        
        objectFields.addAll(objectType.getDescribe().fields.getMap().keySet());
        fieldsList.addAll(fieldsMap.keySet());
        
        if(numberToCreate > 0){
            for( Integer countOfObjects = 0; countOfObjects < numberToCreate; countOfObjects++ ){
                SObject currentObject = objectType.newSObject();
                
                for(String fieldFromList : fieldsList){
                    for(String fieldFromObject : objectFields){
                        if(fieldFromObject == fieldFromList){
                            currentObject.put(fieldFromList , fieldsMap.get(fieldFromList));
                        }
                    }
                }    

                objectsList.add(currentObject);
            }

            if ( doInsert ) insert objectsList;
        }
        
        return objectsList;
    }
}
Also I have added test class for it:
@isTest
private class TestUtilities {
    private static final Integer TEST_RECORD_COUNT = 10;
    
    static Map<String, String> fieldsMap;    
    static Schema.SObjectType objectType;
    static List<String> objectFields = new List<String>();
    static String query;
        
    private static void setup(){
        objectType = Account.getsObjectType();
        objectFields.addAll(objectType.getDescribe().fields.getMap().keySet());
        fieldsMap = new Map<String, String>{'Name' => 'Test',            //Fill in fields
                                            'BillingCountry' => 'Usa',    //IMPORTANT You need to fill in requaired fields
                                            'AccountSource' => 'Web'};
    }
    
    private static testmethod void testCreateObject(){
        List<sObject> testCreatedObjects;
        List<sObject> objectsFromDB;
        List<String> fieldsFromBD = new List<String>();
        
        setup();
        
        Test.startTest();
            testCreatedObjects = Utilities.createObject(TEST_RECORD_COUNT,
                                                           true,
                                                           objectType,
                                                           fieldsMap);
        Test.stopTest();
        
        query = 'SELECT Id';
        
        fieldsFromBD.addAll(fieldsMap.keySet());
        
        for(String fieldDB : fieldsFromBD){
            for(String fieldObject : objectFields){
                if(fieldDB == fieldObject){
                    query += ', ' + fieldDB;
                }
            }
        }
        
        query += ' FROM ' + objectType + ' WHERE Id IN : ' + 'testCreatedObjects' +  ' ';
        
        objectsFromDB = Database.query(query);        
        
        System.assertEquals( TEST_RECORD_COUNT , objectsFromDB.size() );
    }
}
You can also add compare of every field it test.

Enjoy.