diff --git a/src/main/java/com/salesforce/dataloader/action/visitor/BulkLoadVisitor.java b/src/main/java/com/salesforce/dataloader/action/visitor/BulkLoadVisitor.java index 6555e6f0..43cbc70b 100644 --- a/src/main/java/com/salesforce/dataloader/action/visitor/BulkLoadVisitor.java +++ b/src/main/java/com/salesforce/dataloader/action/visitor/BulkLoadVisitor.java @@ -59,6 +59,7 @@ import com.salesforce.dataloader.dao.DataReader; import com.salesforce.dataloader.dao.DataWriter; import com.salesforce.dataloader.dao.csv.CSVFileReader; +import com.salesforce.dataloader.dyna.RelationshipField; import com.salesforce.dataloader.exception.DataAccessObjectException; import com.salesforce.dataloader.exception.DataAccessObjectInitializationException; import com.salesforce.dataloader.exception.LoadException; @@ -280,7 +281,27 @@ private static void addFieldToBatchRequestHeader(PrintStream serverRequestOutput if (!first) { serverRequestOutput.print(','); } - serverRequestOutput.print(sfdcColumn.replace(':', '.')); + // Make sure that relationship field header is in the formats + // specified at https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/datafiles_csv_rel_field_header_row.htm + // Format for Polymorphic relations: ObjectType:RelationshipName.IndexedFieldName + // Format for single parent type relations: RelationshipName.IndexedFieldName + String sfdcColumnForBulk = sfdcColumn; + if (RelationshipField.isRelationshipFieldMapping(sfdcColumn)) { + RelationshipField relField = new RelationshipField(sfdcColumn, true); + if (relField.getParentObjectName() == null) { + if (relField.getParentFieldName() == null) { + sfdcColumnForBulk = relField.getRelationshipName(); + } else { + sfdcColumnForBulk = relField.getRelationshipName() + + "." + relField.getParentFieldName(); + } + } else { + sfdcColumnForBulk = relField.getParentObjectName() + + ":" + relField.getRelationshipName() + + "." + relField.getParentFieldName(); + } + } + serverRequestOutput.print(sfdcColumnForBulk); cols.add(sfdcColumn); addedCols.add(sfdcColumn); } diff --git a/src/main/java/com/salesforce/dataloader/dyna/RelationshipField.java b/src/main/java/com/salesforce/dataloader/dyna/RelationshipField.java index 8392261c..bce1f3cd 100644 --- a/src/main/java/com/salesforce/dataloader/dyna/RelationshipField.java +++ b/src/main/java/com/salesforce/dataloader/dyna/RelationshipField.java @@ -58,7 +58,7 @@ public RelationshipField(String parentObjectName, String relationshipName) { } // fieldName param can be in one of the following formats: - // format 1: alphanumeric string without any ':' or '#' in it. Represents name of child's non-polymorphic relationship field + // format 1: alphanumeric string without any ':' or '-' in it. Represents name of child's non-polymorphic relationship field // format 1 => it is name of a non-polymorphic relationship field in child object. // // format 2: alphanumeric string with a ':' in it @@ -67,7 +67,7 @@ public RelationshipField(String parentObjectName, String relationshipName) { // - this is the new format for keys of the hashmap referenceEntitiesDescribeMap // interpretation 2 (legacy format): : // - // format 3: alphanumeric string with a single ':' and a single '#' in it + // format 3: alphanumeric string with a single ':' and a single '-' in it // format 3 => it is name of a field in child object with reference to an idlookup field in parent object // // Given 2 interpretations of format 2, an additional parameter, 'isFieldName', is required. @@ -92,12 +92,12 @@ public RelationshipField(String fieldName, boolean hasParentIdLookupFieldName) { relationshipName = fieldNameParts[0]; parentObjectName = fieldNameParts[1]; } - } else { // Should not happen - no ':' char in name, may have '#' char + } else { // Should not happen - no ':' char in name, may have '-' char if (parentFieldName == null) { // no ':' and no '.' in name - logger.error("field name " + fieldName + " does not have ':' or '.' char" ); + logger.error("field name " + fieldName + " does not have ':' or '-' char" ); } else { - // '#' char in name but no ':' - logger.error("field name " + fieldName + " has '.' but does not have ':' char" ); + // '-' char in name but no ':' + logger.error("field name " + fieldName + " has '-' but does not have ':' char" ); } } } else { // format 1 or format 2, interpretation 1 @@ -163,6 +163,19 @@ static public String formatAsString(String parentObjectName, String relationship + parentIDLookupFieldName; } + static public boolean isRelationshipFieldMapping(String fieldName) { + if (fieldName == null || fieldName.isBlank()) { + return false; + } + if (fieldName.contains(NEW_FORMAT_PARENT_IDLOOKUP_FIELD_SEPARATOR_CHAR)) { + if (fieldName.contains(NEW_FORMAT_RELATIONSHIP_NAME_SEPARATOR_CHAR)) { + return true; + } + } else if (fieldName.contains(OLD_FORMAT_PARENT_IDLOOKUP_FIELD_SEPARATOR_CHAR)) { + return true; + } + return false; + } /* (non-Javadoc) * @see java.lang.Object#toString() diff --git a/src/test/java/com/salesforce/dataloader/PartnerConnectionForTest.java b/src/test/java/com/salesforce/dataloader/PartnerConnectionForTest.java index 918829d4..0d21dc9d 100644 --- a/src/test/java/com/salesforce/dataloader/PartnerConnectionForTest.java +++ b/src/test/java/com/salesforce/dataloader/PartnerConnectionForTest.java @@ -167,7 +167,7 @@ public void deleteSfdcRecords(String entityName, String whereClause, entitySpecificClause = TESTFIELD_WHERE_CLAUSE; break; } - if (!whereClause.contains(entitySpecificClause)) { + if (whereClause == null || !whereClause.contains(entitySpecificClause)) { if (whereClause == null || whereClause.isBlank()) { whereClause = entitySpecificClause; } else { diff --git a/src/test/java/com/salesforce/dataloader/client/PartnerClientTest.java b/src/test/java/com/salesforce/dataloader/client/PartnerClientTest.java index f9c3d486..019ffc16 100644 --- a/src/test/java/com/salesforce/dataloader/client/PartnerClientTest.java +++ b/src/test/java/com/salesforce/dataloader/client/PartnerClientTest.java @@ -480,29 +480,6 @@ private void doUpsertContact(boolean upsertFk) throws Exception { } } - private void doUpsert(String entity, Map sforceMapping) throws Exception { - // now convert to a dynabean array for the client - // setup our dynabeans - BasicDynaClass dynaClass = setupDynaClass(entity); - - DynaBean sforceObj = dynaClass.newInstance(); - - // This does an automatic conversion of types. - BeanUtils.copyProperties(sforceObj, sforceMapping); - - List beanList = new ArrayList(); - beanList.add(sforceObj); - - // get the client and make the insert call - PartnerClient client = new PartnerClient(getController()); - UpsertResult[] results = client.loadUpserts(beanList); - for (UpsertResult result : results) { - if (!result.getSuccess()) { - Assert.fail("Upsert returned an error: " + result.getErrors()[0].getMessage()); - } - } - } - /** * Basic failing - forgetting the external id or foreign key external id */ @@ -651,68 +628,4 @@ private String getRandomAccountId() throws ConnectionException { return records[0].getId(); } - - /** - * Make sure to set external id field - */ - private String setExtIdField(String extIdField) { - getController().getConfig().setValue(Config.EXTERNAL_ID_FIELD, extIdField); - return extIdField; - } - - /** - * Get a random account external id for upsert testing - * - * @param entity - * TODO - * @param whereClause - * TODO - * @param prevValue - * Indicate that the value should be different from the specified - * value or null if uniqueness not required - * @return String Account external id value - */ - private Object getRandomExtId(String entity, String whereClause, Object prevValue) throws ConnectionException { - - // insert couple of accounts so there're at least two records to work with - upsertSfdcRecords(entity, 2); - - // get the client and make the query call - String extIdField = getController().getConfig().getString(Config.EXTERNAL_ID_FIELD); - PartnerClient client = new PartnerClient(getController()); - // only get the records that have external id set, avoid nulls - String soql = "select " + extIdField + " from " + entity + " where " + whereClause + " and " + extIdField - + " != null"; - if (prevValue != null) { - soql += " and " - + extIdField - + "!= " - + (prevValue.getClass().equals(String.class) ? ("'" + prevValue + "'") : String - .valueOf(prevValue)); - } - QueryResult result = client.query(soql); - SObject[] records = result.getRecords(); - assertNotNull("Operation should return non-null values", records); - assertTrue("Operation should return 1 or more records", records.length > 0); - assertNotNull("Records should have non-null field: " + extIdField + " values", records[0] - .getField(extIdField)); - - return records[0].getField(extIdField); - } - - private BasicDynaClass setupDynaClass(String entity) throws ConnectionException { - getController().getConfig().setValue(Config.ENTITY, entity); - PartnerClient client = getController().getPartnerClient(); - if (!client.isLoggedIn()) { - client.connect(); - } - - getController().setFieldTypes(); - getController().setReferenceDescribes(); - DynaProperty[] dynaProps = SforceDynaBean.createDynaProps(getController().getPartnerClient().getFieldTypes(), getController()); - BasicDynaClass dynaClass = SforceDynaBean.getDynaBeanInstance(dynaProps); - SforceDynaBean.registerConverters(getController().getConfig()); - return dynaClass; - } - } diff --git a/src/test/java/com/salesforce/dataloader/process/CsvProcessTest.java b/src/test/java/com/salesforce/dataloader/process/CsvProcessTest.java index 7d4ffd89..bebb831c 100644 --- a/src/test/java/com/salesforce/dataloader/process/CsvProcessTest.java +++ b/src/test/java/com/salesforce/dataloader/process/CsvProcessTest.java @@ -31,6 +31,7 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; @@ -88,15 +89,64 @@ public static Collection getParameters() { */ @Test public void testInsertAccountCsv() throws Exception { - runProcess(getTestConfig(OperationInfo.insert, false), 100); + Map configMap = getTestConfig(OperationInfo.insert, false); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } + runProcess(configMap, 100); } + /** + * Tests the insert operation on Account - Positive test. + */ + @Test + public void testInsertTaskWithContactAsWhoCsv() throws Exception { + Map configMap = getTestConfig(OperationInfo.insert, false); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } + Map sforceMapping = new HashMap(); + sforceMapping.put("Email", "contactFor@PolymorphicMappingOfTask.com"); + sforceMapping.put("Subject", "Contact to test Polymorphic mapping of Who relationship on Task"); + sforceMapping.put("FirstName", "newFirstName" + System.currentTimeMillis()); + sforceMapping.put("LastName", "newLastName" + System.currentTimeMillis()); + // Title is set for easier test data cleanup + sforceMapping.put("Title", CONTACT_TITLE_PREFIX + System.currentTimeMillis()); + + String extIdField = setExtIdField(DEFAULT_CONTACT_EXT_ID_FIELD); + Object extIdValue = getRandomExtId("Contact", CONTACT_WHERE_CLAUSE, null); + sforceMapping.put(extIdField, extIdValue); + + String oldExtIdField = getController().getConfig().getString(Config.EXTERNAL_ID_FIELD); + setExtIdField(extIdField); + doUpsert("Contact", sforceMapping); + setExtIdField(oldExtIdField); + configMap.put(Config.ENTITY, "Task"); + runProcess(configMap, 1); + } + /** * Tests update operation with input coming from a CSV file. Relies on the id's in the CSV on being in the database */ @Test public void testUpdateAccountCsv() throws Exception { - runProcess(getUpdateTestConfig(false, null, 100), 100); + Map configMap = getUpdateTestConfig(false, null, 100); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } + runProcess(configMap, 100); } /** @@ -104,8 +154,16 @@ public void testUpdateAccountCsv() throws Exception { */ @Test public void testUpsertAccountCsv() throws Exception { + Map configMap = getUpdateTestConfig(true, DEFAULT_ACCOUNT_EXT_ID_FIELD, 50); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } // manually inserts 50 accounts, then upserts 100 accounts (50 inserts and 50 updates) - runUpsertProcess(getUpdateTestConfig(true, DEFAULT_ACCOUNT_EXT_ID_FIELD, 50), 50, 50); + runUpsertProcess(configMap, 50, 50); } /** @@ -121,7 +179,14 @@ public void testUpsertAccountCsv() throws Exception { */ @Test public void testConstantMappingInCsv() throws Exception { - + Map configMap = getTestConfig(OperationInfo.insert, false); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } // The use case is as follows: // This company in this scenario only does business in the state of CA, therefore billing and shipping // addresses are hard coded to that. @@ -131,8 +196,7 @@ public void testConstantMappingInCsv() throws Exception { final String industryValue = "Aerospace"; // insert the values - Map argumentMap = getTestConfig(OperationInfo.insert, false); - for (SObject acct : retrieveAccounts(runProcess(argumentMap, 2), "Industry", "BillingState", "ShippingState")) { + for (SObject acct : retrieveAccounts(runProcess(configMap, 2), "Industry", "BillingState", "ShippingState")) { assertEquals("Incorrect value for industry returned", industryValue, acct.getField("Industry")); @@ -153,6 +217,15 @@ public void testConstantMappingInCsv() throws Exception { */ @Test public void testDescriptionAsConstantMappingInCsv() throws Exception { + Map configMap = getTestConfig(OperationInfo.insert, getTestDataDir() + + "/constantMappingInCsv.csv", false); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } // The use case is as follows: // This company in this scenario only does business in the state of CA, therefore billing and shipping // addresses are hard coded to that. @@ -161,9 +234,8 @@ public void testDescriptionAsConstantMappingInCsv() throws Exception { final String descriptionValue = "Some Description"; // insert the values - Map argumentMap = getTestConfig(OperationInfo.insert, getTestDataDir() - + "/constantMappingInCsv.csv", false); - Controller controller = runProcess(argumentMap, 2); + + Controller controller = runProcess(configMap, 2); for (SObject acct : retrieveAccounts(controller, "Description", "BillingState", "ShippingState")) { assertEquals("Incorrect value for billing state returned", stateValue, acct.getField("BillingState")); assertEquals("Incorrect value for shipping state returned", stateValue, acct.getField("ShippingState")); @@ -180,7 +252,15 @@ public void testDescriptionAsConstantMappingInCsv() throws Exception { */ @Test public void testFieldAndConstantFieldClash() throws Exception { - + Map configMap = getTestConfig(OperationInfo.insert, + getTestDataDir() + "/constantMappingInCsvClashing.csv", false); + if (isSettingEnabled(configMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(configMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(configMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(configMap, Config.NO_COMPRESSION) + ) { + return; + } // The use case is as follows: // This company in this scenario only does business in the state of CA, therefore billing and shipping // addresses are hard coded to that. @@ -190,9 +270,7 @@ public void testFieldAndConstantFieldClash() throws Exception { final String industryValue = "Aerospace"; // insert the values - Map argumentMap = getTestConfig(OperationInfo.insert, - getTestDataDir() + "/constantMappingInCsvClashing.csv", false); - for (SObject acct : retrieveAccounts(runProcess(argumentMap, 2), "Industry", "BillingState", "ShippingState")) { + for (SObject acct : retrieveAccounts(runProcess(configMap, 2), "Industry", "BillingState", "ShippingState")) { assertEquals("Incorrect value for industry returned", industryValue, acct.getField("Industry")); @@ -324,6 +402,10 @@ public void testCreateAttachment() throws Exception { final Map argMap = getTestConfig(OperationInfo.insert, fileName, false); argMap.put(Config.ENTITY, "Attachment"); + if (isSettingEnabled(argMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO)) { + return; + } + // this feature does not work when bulk api is enabled but the zip content type is not final boolean bulkApi = isBulkAPIEnabled(argMap); final boolean zipContent = isSettingEnabled(argMap, Config.BULK_API_ZIP_CONTENT); @@ -383,9 +465,15 @@ private void _doTestHtmlFormattingInInsert(boolean preserveWhitespaceInRichText) // insert the values Map argumentMap = getTestConfig(OperationInfo.insert, getTestDataDir() + "/accountsForInsert.csv", - getTestDataDir() + "/nonMappedFieldsPermittedInDLTransactionMap.sdl", false); + if (isSettingEnabled(argumentMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(argumentMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(argumentMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(argumentMap, Config.NO_COMPRESSION) + ) { + return; + } argumentMap.put(Config.LOAD_PRESERVE_WHITESPACE_IN_RICH_TEXT, Boolean.toString(preserveWhitespaceInRichText)); @@ -473,7 +561,13 @@ public void testTimezoneNotTruncated() throws Exception { //find the csv file Map argumentMap = getTestConfig(OperationInfo.insert, getTestDataDir() + "/timeZoneFormatTesting.csv", false); - + if (isSettingEnabled(argumentMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(argumentMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(argumentMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(argumentMap, Config.NO_COMPRESSION) + ) { + return; + } //insert into the account on the custom fields specified SObject[] returnedAccounts = retrieveAccounts(runProcess(argumentMap, numberOfRows), dateField); @@ -522,6 +616,13 @@ public void testOneToManySforceFieldsMappingInCsv() throws Exception { // insert the values Map argumentMap = getTestConfig(OperationInfo.insert, getTestDataDir() + "/oneToManySforceFieldsMappingInCsv.csv", false); + if (isSettingEnabled(argumentMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(argumentMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(argumentMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(argumentMap, Config.NO_COMPRESSION) + ) { + return; + } Controller controller = runProcess(argumentMap, 2); for (SObject acct : retrieveAccounts(controller, "Name", "Description", "BillingState", "ShippingState")) { if ("ABC Corp".equals(acct.getField("Name"))) { @@ -540,8 +641,16 @@ public void testOneToManySforceFieldsMappingInCsv() throws Exception { @Test public void testEmptyFirstRowFieldValueInCsv() throws Exception { + Map argumentMap = getUpdateTestConfig(false, null, 2); + if (isSettingEnabled(argumentMap, Config.BULK_API_ZIP_CONTENT) + || isSettingEnabled(argumentMap, Config.PROCESS_BULK_CACHE_DATA_FROM_DAO) + || isSettingEnabled(argumentMap, Config.BULK_API_SERIAL_MODE) + || isSettingEnabled(argumentMap, Config.NO_COMPRESSION) + ) { + return; + } // update 2 records - Controller controller = runProcess(getUpdateTestConfig(false, null, 2), 2); + Controller controller = runProcess(argumentMap, 2); for (SObject acct : retrieveAccounts(controller, "Name", "Website")) { String websiteVal = (String)acct.getField("Website"); diff --git a/src/test/java/com/salesforce/dataloader/process/ProcessTestBase.java b/src/test/java/com/salesforce/dataloader/process/ProcessTestBase.java index fd20ad4a..40073ce5 100644 --- a/src/test/java/com/salesforce/dataloader/process/ProcessTestBase.java +++ b/src/test/java/com/salesforce/dataloader/process/ProcessTestBase.java @@ -32,6 +32,10 @@ import java.util.*; import org.apache.logging.log4j.Logger; +import org.apache.commons.beanutils.BasicDynaClass; +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.beanutils.DynaBean; +import org.apache.commons.beanutils.DynaProperty; import org.apache.logging.log4j.LogManager; import org.junit.Assert; @@ -39,11 +43,13 @@ import com.salesforce.dataloader.action.OperationInfo; import com.salesforce.dataloader.action.progress.ILoaderProgress; import com.salesforce.dataloader.client.HttpClientTransport; +import com.salesforce.dataloader.client.PartnerClient; import com.salesforce.dataloader.config.Config; import com.salesforce.dataloader.controller.Controller; import com.salesforce.dataloader.dao.DataAccessObjectFactory; import com.salesforce.dataloader.dao.csv.CSVFileReader; import com.salesforce.dataloader.dao.csv.CSVFileWriter; +import com.salesforce.dataloader.dyna.SforceDynaBean; import com.salesforce.dataloader.exception.*; import com.salesforce.dataloader.exception.UnsupportedOperationException; import com.salesforce.dataloader.model.Row; @@ -951,4 +957,92 @@ protected Map getTestConfig() { configArgsMap.put(Config.CLI_OPTION_RUN_MODE, Config.RUN_MODE_BATCH_VAL); return configArgsMap; } + + + protected UpsertResult[] doUpsert(String entity, Map sforceMapping) throws Exception { + // now convert to a dynabean array for the client + // setup our dynabeans + BasicDynaClass dynaClass = setupDynaClass(entity); + + DynaBean sforceObj = dynaClass.newInstance(); + + // This does an automatic conversion of types. + BeanUtils.copyProperties(sforceObj, sforceMapping); + + List beanList = new ArrayList(); + beanList.add(sforceObj); + + // get the client and make the insert call + PartnerClient client = new PartnerClient(getController()); + UpsertResult[] results = client.loadUpserts(beanList); + for (UpsertResult result : results) { + if (!result.getSuccess()) { + Assert.fail("Upsert returned an error: " + result.getErrors()[0].getMessage()); + } + } + return results; + } + + /** + * Make sure to set external id field + */ + protected String setExtIdField(String extIdField) { + getController().getConfig().setValue(Config.EXTERNAL_ID_FIELD, extIdField); + return extIdField; + } + + /** + * Get a random account external id for upsert testing + * + * @param entity + * TODO + * @param whereClause + * TODO + * @param prevValue + * Indicate that the value should be different from the specified + * value or null if uniqueness not required + * @return String Account external id value + */ + protected Object getRandomExtId(String entity, String whereClause, Object prevValue) throws ConnectionException { + + // insert couple of accounts so there're at least two records to work with + upsertSfdcRecords(entity, 2); + + // get the client and make the query call + String extIdField = getController().getConfig().getString(Config.EXTERNAL_ID_FIELD); + PartnerClient client = new PartnerClient(getController()); + // only get the records that have external id set, avoid nulls + String soql = "select " + extIdField + " from " + entity + " where " + whereClause + " and " + extIdField + + " != null"; + if (prevValue != null) { + soql += " and " + + extIdField + + "!= " + + (prevValue.getClass().equals(String.class) ? ("'" + prevValue + "'") : String + .valueOf(prevValue)); + } + QueryResult result = client.query(soql); + SObject[] records = result.getRecords(); + assertNotNull("Operation should return non-null values", records); + assertTrue("Operation should return 1 or more records", records.length > 0); + assertNotNull("Records should have non-null field: " + extIdField + " values", records[0] + .getField(extIdField)); + + return records[0].getField(extIdField); + } + + protected BasicDynaClass setupDynaClass(String entity) throws ConnectionException { + getController().getConfig().setValue(Config.ENTITY, entity); + PartnerClient client = getController().getPartnerClient(); + if (!client.isLoggedIn()) { + client.connect(); + } + + getController().setFieldTypes(); + getController().setReferenceDescribes(); + DynaProperty[] dynaProps = SforceDynaBean.createDynaProps(getController().getPartnerClient().getFieldTypes(), getController()); + BasicDynaClass dynaClass = SforceDynaBean.getDynaBeanInstance(dynaProps); + SforceDynaBean.registerConverters(getController().getConfig()); + return dynaClass; + } } diff --git a/src/test/resources/testfiles/data/insertTaskWithContactAsWhoCsv.csv b/src/test/resources/testfiles/data/insertTaskWithContactAsWhoCsv.csv new file mode 100644 index 00000000..52a52f82 --- /dev/null +++ b/src/test/resources/testfiles/data/insertTaskWithContactAsWhoCsv.csv @@ -0,0 +1,2 @@ +Subject,Who:Contact-email +testPolymorphicLookup,contactFor@PolymorphicMappingOfTask.com \ No newline at end of file diff --git a/src/test/resources/testfiles/data/insertTaskWithContactAsWhoCsvMap.sdl b/src/test/resources/testfiles/data/insertTaskWithContactAsWhoCsvMap.sdl new file mode 100644 index 00000000..b5c4c95a --- /dev/null +++ b/src/test/resources/testfiles/data/insertTaskWithContactAsWhoCsvMap.sdl @@ -0,0 +1,3 @@ +#Mapping values +Subject=Subject +Who\:Contact-Email=Who\:Contact-Email \ No newline at end of file