Posted By

d3developer on 01/29/11


Tagged


Versions (?)

@wesnolte CvsToSObject Parser


 / Published in: Other
 

  1. /*
  2. * Make sure your class is using the latest API version. Some features in this class
  3. * will only work with API v19 or higher.
  4. */
  5.  
  6. public class CsvToSObjectParser {
  7. private final String RESOURCE_NAME = 'object_csv';
  8.  
  9. private List<String> lines = new List<String>();
  10.  
  11. // Map instead of list since I need the .remove() method AND
  12. // Map instead of set since DML can't be performed on set of SObject
  13. private Map objsToInsert = new Map();
  14.  
  15. // A map to associate our external Ids as defined in the CSV with SObject Ids.
  16. // This helps the code associate related objects. Using two similar maps
  17. // since this one will hold ALL records (think reference-Map) but the one
  18. // above holds a running list of uncommited records (think action-Map)
  19. private Map extIdMap = new Map();
  20.  
  21. public StaticResource theStaticResource{get;set;}
  22.  
  23. public CsvToSObjectParser(){
  24. fetchResource(RESOURCE_NAME);
  25. }
  26.  
  27. public CsvToSObjectParser(String resourceName){
  28. fetchResource(resourceName);
  29. }
  30.  
  31. // Run over the lines in the files
  32. public List parseCsv(){
  33. String bodyText = theStaticResource.body.toString();
  34.  
  35. // Break the body into it's constituent lines
  36. List bodyLines = bodyText.split('\n');
  37.  
  38. for(String line: bodyLines){
  39. // Ignore comment and empty lines
  40. if(line.trim().length() == 0){
  41. continue;
  42. }
  43. System.debug('Key-value pair: '+line);
  44.  
  45. SObject s = munch(line);
  46.  
  47. }
  48.  
  49. List objs = objsToInsert.values();
  50.  
  51. return objs;
  52. }
  53.  
  54. // Robotic muncher. Eats CSV lines and poops
  55. // SObjects.
  56. private SObject munch(String s){
  57. SObject obj;
  58.  
  59. // Rearrange the CSV line into a list of string values
  60. List keyValuePairs = s.split(',');
  61.  
  62. String eId;
  63.  
  64. for(String pairString: keyValuePairs){
  65. // Some boilerplate splitting
  66. List<String> pairs = pairString.split(':');
  67.  
  68. String key = pairs[0].trim(); // Don't forget to Trim!
  69. String value = pairs[1].trim(); // Waste not, want not.
  70.  
  71. // Reserved keyword in the CSV markup - used
  72. // to denote the object name
  73. if(key == 'object'){
  74. obj = createSObject(value);
  75. // Reserved keyword - denotes the parent record Id
  76. } else if(key == 'relatedTo'){
  77.  
  78. // More boilerplate
  79. List referenceFields = value.split('#');
  80. String fieldName = referenceFields[0];
  81. String extId = referenceFields[1];
  82.  
  83. // Find the parent record. Now here we violate the
  84. // 'No DML in a loop' golden rule because the parent
  85. // record Id is required for the association. There is
  86. // way to get around this by using a few lists and a map
  87. // or two. I don't deem it necessary since I have direct
  88. // control over the number of records in the sample file,
  89. // but it'll make a fun exercise for y'all in your spare
  90. // time
  91. SObject parentObj = extIdMap.get(extId);
  92. if(parentObj.id == null){
  93. insert parentObj;
  94. objsToInsert.remove(extId);
  95. }
  96.  
  97. obj.put(fieldName, parentObj.id);
  98. // Reserved keyword - used to associate my CSV record
  99. // Id and the salesforce record Id
  100. } else if( key == 'extId' ){
  101. eId = value;
  102. // Everything else i.e. the real field values
  103. } else {
  104. obj.put(key, value);
  105. }
  106.  
  107. }
  108.  
  109. objsToInsert.put(eId, obj);
  110. extIdMap.put(eId, obj);
  111.  
  112. return obj;
  113. }
  114.  
  115. // Helper that instantiates a generic SObject
  116. private SObject createSObject(String objectName){
  117. Schema.SObjectType t = Schema.getGlobalDescribe().get(objectName);
  118. SObject s = t.newSObject();
  119. return s;
  120. }
  121.  
  122. private void fetchResource(String resourceName){
  123. try{
  124.  
  125. theStaticResource = [SELECT id, Body FROM StaticResource WHERE name = :resourceName];
  126.  
  127. }catch(System.QueryException e){
  128. System.debug(e);
  129. // You should always let the admins/devs know if
  130. // something unexpected happened.
  131. // e.g. ExceptionUtils.mail(Administrator);
  132. }
  133. }
  134. }
  135.  

Report this snippet  

You need to login to post a comment.