Salesforce.com interface to directly access Salesforce.com
Dependencies: HTTPClient-SSL MbedJSONValue
Dependents: df-2014-salesforce-hrm-k64f
Fork of SalesforceInterface by
Revision 16:3d160f224084, committed 2014-09-23
- Comitter:
- ansond
- Date:
- Tue Sep 23 20:26:24 2014 +0000
- Parent:
- 15:89044c68ad36
- Child:
- 17:6c774354b599
- Commit message:
- added external ID support
Changed in this revision
SalesforceInterface.cpp | Show annotated file Show diff for this revision Revisions of this file |
SalesforceInterface.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/SalesforceInterface.cpp Tue Sep 23 17:35:34 2014 +0000 +++ b/SalesforceInterface.cpp Tue Sep 23 20:26:24 2014 +0000 @@ -11,7 +11,7 @@ * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * - * THE SOFTWARE IS PROVtokenED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, @@ -298,9 +298,9 @@ } // READ: a specific record in Salesforce.com - MbedJSONValue SalesforceInterface::readRecord(char *object_name,char *record_id) { + MbedJSONValue SalesforceInterface::readRecord(char *object_name,char *record_id,char *record_value) { ALLOC_BUFFER(output_buffer); - char *reply = this->readRecord(object_name,record_id,output_buffer,MAX_BUFFER_LENGTH); + char *reply = this->readRecord(object_name,record_id,record_value,output_buffer,MAX_BUFFER_LENGTH); MbedJSONValue response; if (reply != NULL && strlen(reply) > 0) parse(response,reply); return response; @@ -311,6 +311,11 @@ return this->updateRecord(object_name,record_id,(char *)record.serialize().c_str()); } + // UPSERT: update/insert an External ID record in Salesforce.com + bool SalesforceInterface::upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,MbedJSONValue &record) { + return this->upsertRecord(object_name,external_id_field_name,external_id_field_value,(char *)record.serialize().c_str()); + } + // CREATE: a record in Salesforce.com char *SalesforceInterface::createRecord(char *object_name,char *json_data,char *output_buffer,int output_buffer_length) { // parameter check @@ -347,7 +352,7 @@ } // READ: a specific record in Salesforce.com - char *SalesforceInterface::readRecord(char *object_name,char *record_id,char *output_buffer,int output_buffer_length) { + char *SalesforceInterface::readRecord(char *object_name,char *record_id,char *record_value,char *output_buffer,int output_buffer_length) { // parameter check if (object_name != NULL && strlen(object_name) > 0 && record_id != NULL && strlen(record_id) > 0 && output_buffer != NULL && output_buffer_length > 0) { // first we have to ensure that we have valid salesforce token @@ -366,6 +371,12 @@ str_url += "/"; str_url += record_id; + // add the record value (if present) + if (record_value != NULL && strlen(record_value) > 0) { + str_url += "/"; + str_url += record_value; + } + // DEBUG DEBUG("readRecord: URL: %s",str_url.c_str()); @@ -434,6 +445,62 @@ } return false; } + + // UPSERT: update/insert a specific External record in Salesforce.com + bool SalesforceInterface::upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,char *json_data) { + // parameter check + if (object_name != NULL && strlen(object_name) > 0 && json_data != NULL && strlen(json_data) > 0) { + // first we have to ensure that we have valid salesforce token + if (this->haveSalesforceToken()) { + // get the sobjects url + ALLOC_BUFFER(url); + char *sf_url = this->getSalesforceURL("sobjects",url,MAX_BUFFER_LENGTH); + if (sf_url != NULL && strlen(sf_url) > 0) { + // convert to string + string str_url(sf_url); + + // add object name that we want to create a record in + str_url += object_name; + + // add the external field name token + str_url += "/"; + str_url += external_id_field_name; + + // add the external field value token (if not NULL) + if (external_id_field_value != NULL && strlen(external_id_field_value) > 0) { + str_url += "/"; + str_url += external_id_field_value; + } + + // HTTPClient does not support PATCH, so we have to use POST with a special added parameter + str_url += "?_HttpMethod=PATCH"; + + // DEBUG + DEBUG("upsertRecord: URL: %s DATA: %s",str_url.c_str(),json_data); + + // now invoke with POST with JSON data type + ALLOC_SML_BUFFER(output_buffer); + char *reply = this->invoke(str_url.c_str(),json_data,strlen(json_data)+1,output_buffer,MAX_SMALL_BUFFER_LENGTH); + + // DEBUG + DEBUG("upsertRecord: http status=%d",this->httpResponseCode()); + + // return our status + if (this->httpResponseCode() == 204) return true; + return false; + } + } + else { + // dont have a valid salesforce token + this->logger()->log("upsertRecord: error - no valid salesforced token was found..."); + } + } + else { + // invalid or NULL parameters + this->logger()->log("upsertRecord: error - invalid or NULL parameters..."); + } + return false; + } // DELETE: a specific record in Salesforce.com bool SalesforceInterface::deleteRecord(char *object_name,char *record_id) {
--- a/SalesforceInterface.h Tue Sep 23 17:35:34 2014 +0000 +++ b/SalesforceInterface.h Tue Sep 23 20:26:24 2014 +0000 @@ -11,7 +11,7 @@ * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * - * THE SOFTWARE IS PROVtokenED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, @@ -87,268 +87,330 @@ * Example Project: http://mbed.org/users/ansond/code/df-2014-salesforce-testharness-k64f/ * * @code - * #include "Definitions.h" // definitions including platform specifics... - * #include "ErrorHandler.h" - * - * // include salesforce.com credentials - * #include "sf_creds.h" - * - * // our Serial port - * #include "BufferedSerial.h" - * BufferedSerial pc(USBTX, USBRX); - * - * // Ethernet - * #include "EthernetInterface.h" - * EthernetInterface ethernet; - * - * // HTTP - * #include "HTTPClient.h" - * HTTPClient http; - * - * // Salesforce.com Interface - * #include "SalesforceInterface.h" - * - * // test case persistence - * char *object_name = NULL; - * char *account_name = NULL; - * char *updated_account_name = NULL; - * DEFINE_SML_BUFFER(record_id); - * - * // *************** Test Cases ************************ - * - * void Test_getSalesforceToken(ErrorHandler *logger,SalesforceInterface *sf) { - * logger->log("\r\n\r\nGetting Salesforce Token..."); - * logger->turnLEDPurple(); - * - * // get the salesforce token - * char *id = sf->getSalesforceToken(); - * if (id != NULL && strlen(id) > 0) - * logger->log("Saleforce token: %s",id); - * else - * logger->log("Unable to get Saleforce token"); - * logger->turnLEDGreen(); - * } - * - * void Test_query(ErrorHandler *logger,SalesforceInterface *sf,char *query_str) { - * logger->log("\r\n\r\nExecuting test query: %s",query_str); - * logger->turnLEDPurple(); - * if (query_str != NULL && strlen(query_str) > 0) { - * ALLOC_BUFFER(response); - * char *answer = sf->query(query_str,response,MAX_BUFFER_LENGTH); - * if (answer != NULL) logger->log("query result: %s",answer); - * else logger->log("query - NULL result"); - * } - * else { - * logger->log("Unable to perform query as we do not have our salesforce token"); - * } - * logger->turnLEDGreen(); - * } - * - * void Test_create(ErrorHandler *logger,SalesforceInterface *sf) { - * logger->log("\r\n\r\nExecuting create()"); - * logger->turnLEDPurple(); - * - * // create a new record - * MbedJSONValue new_record; - * new_record["name"] = account_name; - * - * // DEBUG - * logger->log("Create: new record: %s",new_record.serialize().c_str()); - * - * // create... - * MbedJSONValue response = sf->createRecord(object_name,new_record); - * - * // display the result - * char *result = (char *)response.serialize().c_str(); - * if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) { - * // save off the token if we succeeded - * logger->log("Create: result: %s",result); - * logger->log("Create: http_code=%d",sf->httpResponseCode()); - * RESET_SML_BUFFER(record_id); - * strcpy(record_id,(char *)response["id"].get<std::string>().c_str()); - * } - * else { - * // failure - * logger->log("Create: FAILED http_code=%d",sf->httpResponseCode()); - * } - * logger->turnLEDGreen(); - * } - * - * void Test_read(ErrorHandler *logger,SalesforceInterface *sf) { - * logger->log("\r\n\r\nExecuting read()"); - * logger->turnLEDPurple(); - * - * // DEBUG - * logger->log("Read: reading: %s from %s",record_id,object_name); - * - * // read... - * MbedJSONValue response = sf->readRecord(object_name,record_id); - * - * // display the result - * char *result = (char *)response.serialize().c_str(); - * if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) { - * // save off the token if we succeeded - * logger->log("Read: result: %s",result); - * logger->log("Read: http_code=%d",sf->httpResponseCode()); - * } - * else { - * // failure - * logger->log("Read: FAILED http_code=%d",sf->httpResponseCode()); - * } - * - * logger->turnLEDGreen(); - * } - * - * void Test_update(ErrorHandler *logger,SalesforceInterface *sf) { - * logger->log("\r\n\r\nExecuting update()"); - * logger->turnLEDPurple(); - * - * // update am existing record - assume "name" is the proper key for the record you wish to update... - * MbedJSONValue changed_record; - * changed_record["name"] = updated_account_name; - * - * // DEBUG - * logger->log("Update: updated record: %s",changed_record.serialize().c_str()); - * - * // update... - * bool updated = sf->updateRecord(object_name,record_id,changed_record); - * - * // display the result - * if (updated) { - * // SUCCESS - * logger->log("Update: successful! http_code=%d",sf->httpResponseCode()); - * } - * else { - * // failure - * logger->log("Update: FAILED http_code=%d",sf->httpResponseCode()); - * } - * logger->turnLEDGreen(); - * } - * - * void Test_delete(ErrorHandler *logger,SalesforceInterface *sf) { - * logger->log("\r\n\r\nExecuting delete()"); - * logger->turnLEDPurple(); - * - * // DEBUG - * logger->log("Delete: deleting: %s from %s",record_id,object_name); - * - * // delete... - * bool deleted = sf->deleteRecord(object_name,record_id); - * - * // display the result - * if (deleted) { - * // SUCCESS - * logger->log("Delete: successful! http_code=%d",sf->httpResponseCode()); - * } - * else { - * // failure - * logger->log("Delete: FAILED http_code=%d",sf->httpResponseCode()); - * } - * - * logger->turnLEDGreen(); - * } - * - * void Test_reset_auth(ErrorHandler *logger,SalesforceInterface *sf) { - * logger->log("\r\n\r\nForcing API to reset OAUTH token and Salesforce Token..."); - * logger->turnLEDPurple(); - * sf->resetSalesforceToken(); - * logger->turnLEDGreen(); - * } - * - * // *************** Test Cases ************************ - * - * // Main Task... - * void mainTask(void const *v) { - * - * // create our object instances - * ErrorHandler logger(&pc,NULL); - * SalesforceInterface *sf = NULL; - * - * // announce - * logger.log("\r\n\r\nARM Salesforce Interface TestHarness v%s",APP_VERSION); - * logger.turnLEDBlue(); - * - * // initialize Ethernet - * logger.log("Initializing Ethernet..."); - * ethernet.init(); - * - * // get a DHCP address and bring the network interface up - * logger.log("Getting IP Address..."); - * logger.turnLEDOrange(); - * if (ethernet.connect() == 0) { - * // log our IP address (DHCP) - * logger.log("IP Address: %s",ethernet.getIPAddress()); - * - * // allocate the Salesforce.com interface - * logger.log("Allocating Saleforce.com interface..."); - * sf = new SalesforceInterface(&logger,&http); - * - * // set our Salesforce.com credentials - * sf->setCredentials(username,password,client_id,client_secret); - * - * // *************** BEGIN TEST CASES ***************** - * - * // configuration for the test cases - * object_name = "Account"; // use the account object - * account_name = "ARM"; // add this record (name) - * updated_account_name = "ARM Holdings"; // update the existing record's name to this - * RESET_SML_BUFFER(record_id); // buffer for the record's token - * - * // Perform a Create - * Test_create(&logger,sf); - * - * // Perform a Read - * Test_read(&logger,sf); - * - * // Perform a Query - * Test_query(&logger,sf,"SELECT Id,Name FROM Account LIMIT 5"); - * - * // Perform an Update - * Test_update(&logger,sf); - * - * // Perform a second Read to visually confirm the update above... - * Test_read(&logger,sf); - * - * // force the API to re-acquire the OAUTH token and Salesforce Token - * Test_reset_auth(&logger,sf); - * - * // Perform a Read (should re-acquire the OAUTH token and Salesforce Token) - * Test_read(&logger,sf); - * - * // Perform a Delete - * Test_delete(&logger,sf); - * - * // reset the record token buffer - * // RESET_SML_BUFFER(record_id); - * - * // Perform a Read - should error out - * Test_read(&logger,sf); - * - * // reset the record token buffer - * RESET_SML_BUFFER(record_id); - * - * // *************** BEGIN TEST CASES ***************** - * - * // entering main loop - * logger.log("All tests complete...\r\nExiting..."); - * logger.turnLEDBlue(); - * exit(0); - * } - * else { - * logger.log("No Network... Exiting..."); - * logger.turnLEDRed(); - * exit(1); - * } - * - * } - * - * // main entry - * int main() { - * Thread workerTask(mainTask, NULL, osPriorityNormal, STACK_SIZE); - * while (true) { - * Thread::wait(10*WAIT_TIME_MS); - * } - * } + + #include "Definitions.h" // definitions including platform specifics... + #include "ErrorHandler.h" + + // include salesforce.com credentials + #include "sf_creds.h" + + // our Serial port + #include "BufferedSerial.h" + BufferedSerial pc(USBTX, USBRX); + + // Ethernet + #include "EthernetInterface.h" + EthernetInterface ethernet; + + // HTTP + #include "HTTPClient.h" + HTTPClient http; + + // Salesforce.com Interface + #include "SalesforceInterface.h" + + // test case persistence + char *object_name = NULL; + char *account_name = NULL; + char *updated_account_name = NULL; + char *external_id_field_name = NULL; + char *external_id_field_value = NULL; + DEFINE_SML_BUFFER(record_id); + + // *************** Test Cases ************************ + + void Test_getSalesforceToken(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nGetting Salesforce Token..."); + logger->turnLEDPurple(); + + // get the salesforce token + char *id = sf->getSalesforceToken(); + if (id != NULL && strlen(id) > 0) + logger->log("Saleforce token: %s",id); + else + logger->log("Unable to get Saleforce token"); + logger->turnLEDGreen(); + } + + void Test_query(ErrorHandler *logger,SalesforceInterface *sf,char *query_str) { + logger->log("\r\n\r\nExecuting test query: %s",query_str); + logger->turnLEDPurple(); + if (query_str != NULL && strlen(query_str) > 0) { + ALLOC_BUFFER(response); + char *answer = sf->query(query_str,response,MAX_BUFFER_LENGTH); + if (answer != NULL) logger->log("query result: %s",answer); + else logger->log("query - NULL result"); + } + else { + logger->log("Unable to perform query as we do not have our salesforce token"); + } + logger->turnLEDGreen(); + } + + void Test_create(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nExecuting create()"); + logger->turnLEDPurple(); + + // create a new record + MbedJSONValue new_record; + new_record["name"] = account_name; + + // DEBUG + logger->log("Create: new record: %s",new_record.serialize().c_str()); + + // create... + MbedJSONValue response = sf->createRecord(object_name,new_record); + + // display the result + char *result = (char *)response.serialize().c_str(); + if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) { + // save off the token if we succeeded + logger->log("Create: result: %s",result); + logger->log("Create: http_code=%d",sf->httpResponseCode()); + RESET_SML_BUFFER(record_id); + strcpy(record_id,(char *)response["id"].get<std::string>().c_str()); + } + else { + // failure + logger->log("Create: FAILED http_code=%d",sf->httpResponseCode()); + } + logger->turnLEDGreen(); + } + + void Test_read(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nExecuting read()"); + logger->turnLEDPurple(); + + // DEBUG + logger->log("Read: reading: %s from %s",record_id,object_name); + + // read... + MbedJSONValue response = sf->readRecord(object_name,record_id); + + // display the result + char *result = (char *)response.serialize().c_str(); + if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) { + // save off the token if we succeeded + logger->log("Read: result: %s",result); + logger->log("Read: http_code=%d",sf->httpResponseCode()); + } + else { + // failure + logger->log("Read: FAILED http_code=%d",sf->httpResponseCode()); + } + + logger->turnLEDGreen(); + } + + void Test_read_by_external_id_and_value(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nExecuting Read(externalID)..."); + logger->turnLEDPurple(); + + // DEBUG + logger->log("Read: reading: %s from %s with value %s",object_name,external_id_field_name,external_id_field_value); + + // read (external ID)... + MbedJSONValue response = sf->readRecord(object_name,external_id_field_name,external_id_field_value); + + // display the result + char *result = (char *)response.serialize().c_str(); + if (result != NULL && strlen(result) > 0 && strcmp(result,"null") != 0) { + // save off the token if we succeeded + logger->log("Read(externalID): result: %s",result); + logger->log("Read(externalID): http_code=%d",sf->httpResponseCode()); + } + else { + // failure + logger->log("Read(externalID): FAILED http_code=%d",sf->httpResponseCode()); + } + + logger->turnLEDGreen(); + } + + void Test_update(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nExecuting update()"); + logger->turnLEDPurple(); + + // update am existing record - assume "name" is the proper key for the record you wish to update... + MbedJSONValue changed_record; + changed_record["name"] = updated_account_name; + + // DEBUG + logger->log("Update: updated record: %s",changed_record.serialize().c_str()); + + // update... + bool updated = sf->updateRecord(object_name,record_id,changed_record); + + // display the result + if (updated) { + // SUCCESS + logger->log("Update: successful! http_code=%d",sf->httpResponseCode()); + } + else { + // failure + logger->log("Update: FAILED http_code=%d",sf->httpResponseCode()); + } + logger->turnLEDGreen(); + } + + void Test_upsert(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nExecuting upsert()"); + logger->turnLEDPurple(); + + // update am existing record - assume "name" is the proper key for the record you wish to update... + MbedJSONValue changed_record; + changed_record["name"] = updated_account_name; + + // DEBUG + logger->log("Upsert: upserted record: %s",changed_record.serialize().c_str()); + + // Upsert... + bool updated = sf->upsertRecord(object_name,external_id_field_name,external_id_field_value,changed_record); + + // display the result + if (updated) { + // SUCCESS + logger->log("Upsert: successful! http_code=%d",sf->httpResponseCode()); + } + else { + // failure + logger->log("Upsert: FAILED http_code=%d",sf->httpResponseCode()); + } + logger->turnLEDGreen(); + } + + void Test_delete(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nExecuting delete()"); + logger->turnLEDPurple(); + + // DEBUG + logger->log("Delete: deleting: %s from %s",record_id,object_name); + + // delete... + bool deleted = sf->deleteRecord(object_name,record_id); + + // display the result + if (deleted) { + // SUCCESS + logger->log("Delete: successful! http_code=%d",sf->httpResponseCode()); + } + else { + // failure + logger->log("Delete: FAILED http_code=%d",sf->httpResponseCode()); + } + + logger->turnLEDGreen(); + } + + void Test_reset_auth(ErrorHandler *logger,SalesforceInterface *sf) { + logger->log("\r\n\r\nForcing API to reset OAUTH token and Salesforce Token..."); + logger->turnLEDPurple(); + sf->resetSalesforceToken(); + logger->turnLEDGreen(); + } + + // *************** Test Cases ************************ + + // Main Task... + void mainTask(void const *v) { + + // create our object instances + ErrorHandler logger(&pc,NULL); + SalesforceInterface *sf = NULL; + + // announce + logger.log("\r\n\r\nARM Salesforce Interface Testharness v%s",APP_VERSION); + logger.turnLEDBlue(); + + // initialize Ethernet + logger.log("Initializing Ethernet..."); + ethernet.init(); + + // get a DHCP address and bring the network interface up + logger.log("Getting IP Address..."); + logger.turnLEDOrange(); + if (ethernet.connect() == 0) { + // log our IP address (DHCP) + logger.log("IP Address: %s",ethernet.getIPAddress()); + + // allocate the Salesforce.com interface + logger.log("Allocating Saleforce.com interface..."); + sf = new SalesforceInterface(&logger,&http); + + // set our Salesforce.com credentials + sf->setCredentials(username,password,client_id,client_secret); + + // *************** BEGIN TEST CASES ***************** + + // configuration for the test cases + object_name = "Account"; // use the account object + account_name = "ARM"; // add this record (name) + updated_account_name = "ARM Holdings"; // update the existing record's name to this + external_id_field_name = "Device_c"; // External ID field name + external_id_field_value = "ABC123"; // External ID field value + RESET_SML_BUFFER(record_id); // buffer for the record's token + + // Perform a Create + Test_create(&logger,sf); + + // Perform a Read + Test_read(&logger,sf); + + // Perform a Query + Test_query(&logger,sf,"SELECT Id,Name FROM Account LIMIT 5"); + + // Perform an Update + Test_update(&logger,sf); + + // Perform a second Read to visually confirm the update above... + Test_read(&logger,sf); + + // Perform an Upsert + Test_update(&logger,sf); + + // Perform a read of the external ID'ed specified by a given value + Test_read_by_external_id_and_value(&logger,sf); + + // force the API to re-acquire the OAUTH token and Salesforce Token + Test_reset_auth(&logger,sf); + + // Perform a Read (should re-acquire the OAUTH token and Salesforce Token) + Test_read(&logger,sf); + + // Perform a Delete + Test_delete(&logger,sf); + + // reset the record token buffer + // RESET_SML_BUFFER(record_id); + + // Perform a Read - should error out + Test_read(&logger,sf); + + // reset the record token buffer + RESET_SML_BUFFER(record_id); + + // *************** BEGIN TEST CASES ***************** + + // entering main loop + logger.log("All tests complete...\r\nExiting..."); + logger.turnLEDBlue(); + exit(0); + } + else { + logger.log("No Network... Exiting..."); + logger.turnLEDRed(); + exit(1); + } + } + + // main entry + int main() { + Thread workerTask(mainTask, NULL, osPriorityNormal, STACK_SIZE); + while (true) { + Thread::wait(10*WAIT_TIME_MS); + } + } + * @endcode * */ @@ -439,25 +501,36 @@ /** Salesforce.com API record read method to read a record within a salesforce.com object - @param object_name name of the salesforce.com object to create the record in (i.e. "Account") - @param record_id salesforce.com token of the record instance to read + @param object_name name of the salesforce.com object to read the record in (i.e. "Account") + @param record_id salesforce.com id of the record instance to read + @param record_value salesforce.com id value of the record instance to read (for external ID usage - default is NULL for non-external IDs) @return MbedJSONValue structure with the results of the read operation in JSON format */ - MbedJSONValue readRecord(char *object_name,char *record_id); + MbedJSONValue readRecord(char *object_name,char *record_id,char *record_value = NULL); /** Salesforce.com API record update method to update a record within a salesforce.com object - @param object_name name of the salesforce.com object to create the record in (i.e. "Account") - @param record_id salesforce.com token of the record instance to read + @param object_name name of the salesforce.com object to update the record in (i.e. "Account") + @param record_id salesforce.com id of the record instance to read @param record MbedJSONValue instance with updated data for the record @return true - success, false - failure */ bool updateRecord(char *object_name,char *record_id,MbedJSONValue &record); /** + Salesforce.com API record upsert (update/insert) method to update a record within a salesforce.com object for External IDs + @param object_name name of the salesforce.com External object to upsert the record in (i.e. "FooBar_c") + @param external_id_field_name salesforce.com id of the External record instance to upsert + @param external_id_field_value salesforce.com id value of the External record instance to upsert + @param record MbedJSONValue instance with updated data for the record + @return true - success, false - failure + */ + bool upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,MbedJSONValue &record); + + /** Salesforce.com API record delete method to delete a record within a salesforce.com object - @param object_name name of the salesforce.com object to create the record in (i.e. "Account") - @param record_id salesforce.com token of the record instance to delete + @param object_name name of the salesforce.com object to delete the record in (i.e. "Account") + @param record_id salesforce.com id of the record instance to delete @return true - success, false - failure */ bool deleteRecord(char *object_name,char *record_id); @@ -477,10 +550,13 @@ char *createRecord(char *object_name,char *json_data,char *output_buffer,int output_buffer_length); // READ: a specific record in Salesforce.com - char *readRecord(char *object_name,char *record_id,char *output_buffer,int output_buffer_length); + char *readRecord(char *object_name,char *record_id,char *record_value,char *output_buffer,int output_buffer_length); // UPDATE: a specific record in Salesforce.com bool updateRecord(char *object_name,char *record_id,char *json_data); + + // UPSERT: update/insert a specific External record in Salesforce.com + bool upsertRecord(char *object_name,char *external_id_field_name,char *external_id_field_value,char *json_data); // raw invocation of REST calls into Salesforce.com char *invoke(const char *url,char *output_buffer,int output_buffer_length); // defaults to GET