Return to Snippet

Revision: 40303
at January 29, 2011 07:15 by d3developer


Initial Code
/*
* Make sure your class is using the latest API version. Some features in this class
* will only work with API v19 or higher.
*/

public class CsvToSObjectParser {
    private final String RESOURCE_NAME = 'object_csv';

    private List<String> lines = new List<String>();

    // Map instead of list since I need the .remove() method AND
    // Map instead of set since DML can't be performed on set of SObject
    private Map objsToInsert = new Map();

    // A map to associate our external Ids as defined in the CSV with SObject Ids.
    // This helps the code associate related objects. Using two similar maps
    // since this one will hold ALL records (think reference-Map) but the one
    // above holds a running list of uncommited records (think action-Map)
    private Map extIdMap = new Map();

    public StaticResource theStaticResource{get;set;}

    public CsvToSObjectParser(){
        fetchResource(RESOURCE_NAME);
    }

    public CsvToSObjectParser(String resourceName){
        fetchResource(resourceName);
    }

    // Run over the lines in the files
    public List parseCsv(){
        String bodyText = theStaticResource.body.toString();

        // Break the body into it's constituent lines
        List bodyLines = bodyText.split('\n');

        for(String line: bodyLines){
            // Ignore comment and empty lines
            if(line.trim().length() == 0){
                continue;
            }
            System.debug('Key-value pair: '+line);

            SObject s = munch(line);

        }

        List objs = objsToInsert.values();

        return objs;
    }

    // Robotic muncher. Eats CSV lines and poops
    // SObjects.
    private SObject munch(String s){
        SObject obj;

        // Rearrange the CSV line into a list of string values
        List keyValuePairs = s.split(',');

        String eId;

        for(String pairString: keyValuePairs){
            // Some boilerplate splitting
            List<String> pairs = pairString.split(':');

            String key = pairs[0].trim(); // Don't forget to Trim!
            String value = pairs[1].trim(); // Waste not, want not.

            // Reserved keyword in the CSV markup - used
            // to denote the object name
            if(key == 'object'){
                obj = createSObject(value);
            // Reserved keyword - denotes the parent record Id
            } else if(key == 'relatedTo'){

                // More boilerplate
                List referenceFields = value.split('#');
                String fieldName = referenceFields[0];
                String extId = referenceFields[1];

                // Find the parent record. Now here we violate the
                // 'No DML in a loop' golden rule because the parent
                // record Id is required for the association. There is
                // way to get around this by using a few lists and a map
                // or two. I don't deem it necessary since I have direct
                // control over the number of records in the sample file,
                // but it'll make a fun exercise for y'all in your spare
                // time
                SObject parentObj = extIdMap.get(extId);
                if(parentObj.id == null){
                    insert parentObj;
                    objsToInsert.remove(extId);
                }

                obj.put(fieldName, parentObj.id);
            // Reserved keyword - used to associate my CSV record
            // Id and the salesforce record Id
            } else if( key == 'extId' ){
                eId = value;
            // Everything else i.e. the real field values
            } else {
                obj.put(key, value);
            }

        }

        objsToInsert.put(eId, obj);
        extIdMap.put(eId, obj);

        return obj;
    }

    // Helper that instantiates a generic SObject
    private SObject createSObject(String objectName){
        Schema.SObjectType t = Schema.getGlobalDescribe().get(objectName);
        SObject s = t.newSObject();
        return s;
    }

    private void fetchResource(String resourceName){
        try{

            theStaticResource = [SELECT id, Body FROM StaticResource WHERE name = :resourceName];

        }catch(System.QueryException e){
            System.debug(e);
            // You should always let the admins/devs know if
            // something unexpected happened.
            // e.g. ExceptionUtils.mail(Administrator);
        }
    }
}

Initial URL


Initial Description


Initial Title
@wesnolte CvsToSObject Parser 

Initial Tags


Initial Language
Other