121
Apex Code Beta Release: Salesforce Spring '07 Apex Code Language Reference Beta Release © Copyright 2000-2007 salesforce.com, inc. All rights reserved. Salesforce.com, the “no software” logo, and Team Edition are registered trademarks, and AppExchange,“Success On Demand,” and “The Business Web” are trademarks of salesforce.com, inc. All other trademarks mentioned in this document are the properties of their respective owners.

Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Embed Size (px)

Citation preview

Page 1: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Apex Code Beta Release: Salesforce Spring '07

Apex Code Language ReferenceBeta Release

© Copyright 2000-2007 salesforce.com, inc. All rights reserved. Salesforce.com, the “no software” logo, and Team Edition are registeredtrademarks, and AppExchange, “Success On Demand,” and “The Business Web” are trademarks of salesforce.com, inc. All other trademarks

mentioned in this document are the properties of their respective owners.

Page 2: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements
Page 3: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Table of Contents

Chapter 1: Introducing Apex Code...............................................................................................5What is Apex Code?......................................................................................................................................................6How Does Apex Code Work?.......................................................................................................................................7When Should I Use Apex Code Versus an S-Control or the Web Services API?.........................................................8What are the Limitations of Apex Code?......................................................................................................................8

Chapter 2: Apex Code Quick Start...............................................................................................9Obtaining a Developer Edition Account.....................................................................................................................10Writing Apex Code.....................................................................................................................................................10Walking Through a Sample Apex Code Application..................................................................................................10

Scenario...........................................................................................................................................................10Data Model......................................................................................................................................................10Business Rules.................................................................................................................................................12Examples..........................................................................................................................................................12Testing the Sample Application.......................................................................................................................21

Chapter 3: Apex Code Data Types, Variables, and Expressions....................................................22Data Types...................................................................................................................................................................23

Primitive Data Types.......................................................................................................................................23SObject Types..................................................................................................................................................24Lists.................................................................................................................................................................26Sets..................................................................................................................................................................28Maps................................................................................................................................................................28

Iterating Collections....................................................................................................................................................29Variables......................................................................................................................................................................30

Declaring Local Variables................................................................................................................................30Case Sensitivity................................................................................................................................................30Constants.........................................................................................................................................................31

Expressions..................................................................................................................................................................31Extending SObject and List Expressions.........................................................................................................32Expression Operators.......................................................................................................................................32SOQL Queries................................................................................................................................................38Comments.......................................................................................................................................................41

Chapter 4: Apex Code Flow Control...........................................................................................42Assignment Statements...............................................................................................................................................43Conditional (If-Else) Statements................................................................................................................................44Loops...........................................................................................................................................................................44

Do-While Loops.............................................................................................................................................45While Loops....................................................................................................................................................45For Loops........................................................................................................................................................46

Locking Statements.....................................................................................................................................................49

i

Table of Contents

Page 4: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Locking in a SOQL For Loop........................................................................................................................49Avoiding Deadlocks.........................................................................................................................................49

Data Manipulation Language (DML) Statements......................................................................................................49Insert Statements.............................................................................................................................................50Update Statements...........................................................................................................................................51Upsert Statements............................................................................................................................................52Delete Statements............................................................................................................................................54Merge Statements............................................................................................................................................55SObjects That Do Not Support DML Statements.........................................................................................55Bulk DML Exception Handling.....................................................................................................................56

Transaction Control Statements (Commit and Rollback)...........................................................................................56Method Invoking Statements......................................................................................................................................56Exception Statements..................................................................................................................................................57

Throw Statements...........................................................................................................................................57Try-Catch-Finally Statements.........................................................................................................................57Exception Types...............................................................................................................................................58Exception Variables..........................................................................................................................................60Exception Methods..........................................................................................................................................60

Chapter 5: Apex Code Methods..................................................................................................61System Static Methods................................................................................................................................................62Limits Methods...........................................................................................................................................................66List Methods...............................................................................................................................................................68Set Methods................................................................................................................................................................70Map Methods..............................................................................................................................................................72Double Methods..........................................................................................................................................................73SObject Methods........................................................................................................................................................74String Methods............................................................................................................................................................75Date Methods..............................................................................................................................................................77Datetime Methods......................................................................................................................................................78Exception Methods.....................................................................................................................................................80User-Defined Methods................................................................................................................................................80

Chapter 6: Packaging and Invoking Apex Code...........................................................................82Packages.......................................................................................................................................................................83

Package Syntax................................................................................................................................................83Defining a Package..........................................................................................................................................83The Public, Private, and Final Keywords.........................................................................................................84Package Variables and Static Initializers..........................................................................................................84WebService Methods.......................................................................................................................................85Namespace Prefixes..........................................................................................................................................85

Triggers........................................................................................................................................................................86Bulk Triggers...................................................................................................................................................87Syntax..............................................................................................................................................................87Trigger Context Variables................................................................................................................................88Common Bulk Trigger Idioms.........................................................................................................................89

ii

Table of Contents

Page 5: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Defining a Trigger...........................................................................................................................................90Triggers and Merge Statements.......................................................................................................................91Triggers and Order of Execution.....................................................................................................................91Trigger-Ignoring Operations...........................................................................................................................91Fields that Cannot Be Updated by Triggers....................................................................................................92Trigger Exceptions...........................................................................................................................................92

Anonymous Blocks......................................................................................................................................................93Invoking Apex Code in AJAX.....................................................................................................................................93

Chapter 7: Debugging Apex Code..............................................................................................95Debugging Apex Code API Calls...............................................................................................................................96The Debug Log...........................................................................................................................................................96Testing and Code Coverage.........................................................................................................................................97

Running Unit Test Methods............................................................................................................................99Code Coverage Statistics.................................................................................................................................99

Handling Uncaught Exceptions..................................................................................................................................99Execution Governors and Limits...............................................................................................................................100

Appendix A: Web Services API Calls for Apex Code..................................................................102executeanonymous.....................................................................................................................................................102ExecuteAnonymousResult.........................................................................................................................................102DebuggingHeader.....................................................................................................................................................103

Appendix B: Reserved Keywords..............................................................................................104

Appendix C: Quoting App Sample Code...................................................................................106oppLineTrigger.apex..................................................................................................................................................106oppTrigger.apex.........................................................................................................................................................106quoteLineTrigger.apex...............................................................................................................................................107quoteTrigger.apex......................................................................................................................................................108util.apex.....................................................................................................................................................................110

iii

Table of Contents

Page 6: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

iv

Table of Contents

Page 7: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 1

Introducing Apex Code

Over the past several years, salesforce.com has changed the way organizationsdo business by moving enterprise applications that were traditionally

In this chapter ...

• What is Apex Code? client-server-based into an on-demand, multi-tenant web environment. This• How Does Apex Code Work? environment, the Apex platform, allows organizations to run and customize

applications, such as Sales Force Automation and Service & Support, and buildnew custom applications based on particular business needs.

• When Should I Use Apex CodeVersus an S-Control or the WebServices API? While many customization options are available through the Apex platform web

interface, such as the ability to define new fields, objects, workflow, and approval• What are the Limitations of ApexCode? processes, developers can also use the Apex Web Services API to issue data

manipulation commands such as SELECT, INSERT, UPDATE, and DELETE, fromclient-side programs.

These client-side programs, typically written in Java, JavaScript, or .NET, grantorganizations more flexibility in their customizations. However, because thecontrolling logic for these client-side programs is not located on Apex platformservers, the clients are restricted by:

• The performance costs of making multiple round-trips to the salesforce.comsite to accomplish common business transactions

• The risk of data corruption if multiple records are manipulated within a singletransaction

To address these issues, and to revolutionize the way that developers createon-demand applications, salesforce.com now introduces Apex Code, the firstmulti-tenant, on-demand programming language for developers interested inbuilding the next generation of business applications.

5

Page 8: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

What is Apex Code?

Apex Code is a procedural scripting language that allows developers to execute flow and transaction control statements on theApex platform server in conjunction with calls to the Apex API. Using syntax that looks like Java and acts like database storedprocedures, Apex Code allows developers to add business logic to most system events, including button clicks, related recordupdates, and custom s-control display.

Figure 1: You can add Apex Code to most system events.

As a language, Apex Code is:

IntegratedApex Code provides built-in support for common Apex platform idioms, including:

• Data manipulation language (DML) calls, such as INSERT,UPDATE, and DELETE, that include built-inDmlException handling

• Inline Sforce Object Query Language (SOQL) queries that return arrays of SObject records• for loops that allow bulk processing of multiple records at a time• Locking syntax that prevents record update conflicts• Custom public Apex API calls that can be built from stored Apex Code methods

Easy to useApex Code is based on familiar Java idioms, such as variable and expression syntax, block and conditionalstatement syntax, loop syntax, object and array notation, pass by reference, and so on. Where Apex Codeintroduces new elements, it uses syntax and semantics that are easy to understand and encourage efficientuse of the Apex platform. Consequently, Apex Code produces code that is both succinct and easy to write.

Data focusedApex Code is designed to thread together multiple query and DML statements into a single unit of workon the Apex platform server, much as developers use database stored procedures to thread together multipletransaction statements on a database server. Note that like other database stored procedures, Apex Codedoes not attempt to provide general support for rendering elements in the user interface.

6

What is Apex Code?

Page 9: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

RigorousApex Code is a strongly-typed language that uses direct references to schema objects such as object andfield names. It fails quickly at compile time if any references are invalid, and stores all custom field, object,and package dependencies in metadata to ensure they are not deleted while required by active Apex Codescripts.

HostedApex Code is interpreted, executed, and controlled entirely by the Apex platform.

Multi-tenant awareLike the rest of the Apex platform, Apex Code runs in a multi-tenant environment. Consequently, theApex Code runtime engine is designed to guard closely against runaway scripts, preventing them frommonopolizing shared resources. Any scripts that violate these limits fail with easy-to-understand errormessages.

Automatically upgradeableApex Code never needs to be rewritten when other parts of the Apex platform are upgraded. Because thecompiled code is stored as metadata in the platform, it always gets automatically upgraded with the restof the system.

Easy to testApex Code provides built-in support for unit test creation and execution, including test results that indicatehow much code is covered, and which parts of your code could be more efficient. Salesforce.com ensuresthat scripts always work as expected by executing all unit tests stored in metadata prior to any platformupgrades.

How Does Apex Code Work?

All Apex Code runs entirely on-demand on the Apex platform, as shown in the following architecture diagram:

Figure 2: Apex Code code is compiled, stored, and run entirely on the Apex platform.

When a developer writes and saves an Apex Code script to the platform, the platform application server first compiles thecode into an abstract set of instructions that can be understood by the Apex Code runtime interpreter, and then saves thoseinstructions as metadata.

When an end-user triggers the execution of Apex Code, perhaps by clicking a button or accessing an s-control, the platformapplication server retrieves the compiled instructions from the metadata and sends them through the runtime interpreter beforereturning the result. The end-user observes no differences in execution time from standard platform requests.

7

How Does Apex Code Work?

Page 10: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

When Should I Use Apex Code Versus an S-Control or the Web Services API?

The Apex platform includes a number of ways for advanced administrators and developers to implement custom functionality.These include s-controls, the Apex Web Services API, and now Apex Code.

S-controls

Use an s-control when you want to add a visual element to the application user interface, such as a Java applet, an ActiveXcontrol, an Excel file, a custom button, or an HTML web page.

S-controls can optionally include calls to the API or custom Apex Code. However, any business logic that is included in ans-control only executes when a user accesses the control through the application web interface. S-controls cannot be executedthrough calls to the API.

For more information, see "About S-Controls" in the application online help.

Apex Web Services API

Use standard Apex Web Services API calls if you want to:

• Perform a search with a SOSL query• Add functionality to an s-control or a composite application that processes only one record at a time and does not require

any transactional control (commit or rollback)

For more information, see the Apex Web Services Developer's API Guide atwww.salesforce.com/developer/docs/api/Content/index.htm.

Apex Code

Use Apex Code if you want to:

• Process more than one record at a time efficiently, and with transactional correctness• Attach business logic to another operation, such as saving a record, so that it occurs whenever the operation is executed,

regardless of whether it originates in the user interface, an s-control, or from the web services API.

What are the Limitations of Apex Code?

Apex Code radically changes the way that developers create on-demand business applications, but it is not currently meant tobe a general purpose programming language. As of this release, Apex Code cannot be used to:

• Render elements in the user interface other than error messages• Change standard functionality—Apex Code can only prevent the functionality from happening, or add additional

functionality• Run Sforce Object Search Language (SOSL) statements• Send email• Include external callouts to third-party web services• Create temporary files• Spawn threads• Use network resources

8

When Should I Use Apex Code Versus an S-Control or the Web Services API?

Page 11: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 2

Apex Code Quick Start

To start developing with Apex Code, take the following steps:In this chapter ...

1. Obtain a Developer Edition account.• Obtaining a Developer EditionAccount 2. Determine where you want to write your code.

3. Walk through a sample Apex Code application.• Writing Apex Code• Walking Through a Sample Apex

Code Application

9

Page 12: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Obtaining a Developer Edition Account

If you are not already a member of the developer community, go to http://www.salesforce.com/signup/dev_signup.jsp andfollow the instructions for signing up for a Developer Edition account. Even if you already have an Enterprise Edition orUnlimited Edition account, it is strongly recommended that you use Developer Edition for developing, staging, and testingyour solutions against sample data to protect your organization’s live data. This is especially true for applications that will beinserting, updating, or deleting data (as opposed to simply reading data).

Writing Apex Code

You can write Apex Code in any of the following editing environments:

• Any text editor, such as Notepad• The Apex platform Web interface:

• For a trigger on a standard object, click Setup ➤ Customize ➤ <Std_Object_Name> ➤ Buttons & Links. In theTriggers related list, click New, and then enter your code in the Body text box.

• For a trigger on a custom object, click Setup ➤ Build ➤ Custom Objects, and click the name of the object. In theTriggers related list, click New, and then enter your code in the Body text box.

• For a package, click Setup ➤ Build ➤ Code. Click New, and then enter your code in the Body text box.

• Eclipse

An Eclipse plug-in, available at https://wiki.apexdevnet.com/index.php/Apex_Toolkit_for_Eclipse, includes basiccolor-coding, outline view, integrated unit testing, and auto-compilation on save with error message display. See the websitefor information on plug-in installation and usage.

Note: If you want to extend the Eclipse plug-in or develop an Apex Code IDE of your own, the web services APIincludes methods for compiling triggers and packages, and executing test methods. Contact your salesforce.comrepresentative for information.

Walking Through a Sample Apex Code Application

The sample application introduced and explained in this section includes traditional Salesforce functionality blended withApex Code. Many of the syntactic and semantic features of Apex Code, along with common idioms, are illustrated in thisapplication.

Scenario

The sample Apex Code application extends the opportunity management functionality of Salesforce with a simple quotingmodule.

When a salesperson attempts to sell into an account, the internal record of the products the salesperson is trying to sell isrecorded in an opportunity. When an actual offer is made to a customer, this object is referred to as a quote. A quote consistsof line items with prices and quantities, along with an overall total quote amount. An opportunity and its line items serve asa template for creating one or more quotes, only one of which can be the "primary" quote, the current offer to the customer.

Data Model

As illustrated in The Sample Quoting Application Data Model, the sample application uses the standard Opportunity andOpportunityLineItem objects, along with the Product2 master product object. OpportunityLineItem contains a referencefield (analogous to a foreign key) to the PricebookEntry object, and through this relationship, OpportunityLineItem also hasa relationship to Product2.

10

Obtaining a Developer Edition Account

Page 13: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

The sample application also uses two custom objects: Quote and QuoteLine. Quote has a lookup relationship to the Opportunityobject. That is, one Opportunity record can be associated with multiple quotes. The Quote object represents one completequote, and includes a Total field for its total monetary value. Quote, in turn, has a master-detail relationship to QuoteLine.The QuoteLine object represents a single product in the overall quote, and includes values for product color, unit price, andquantity, among others.

Note: Ideally, the Quote object would have a master-detail relationship to Opportunity, but this is not currentlyallowed on the Apex platform because master-detail relationships can be only one-level deep. The quoting applicationrequires a two-level master-detail relationship: Opportunity to Quote to QuoteLine.

Figure 3: The Sample Quoting Application Data Model

The fields in the Quote and QuoteLine custom objects include:

Table 1: Quote Fields

DescriptionField TypeField

The name of the quote, a standard field.stringName

The ID of the associated opportunity for this quotereferenceOpportunity

True if this quote is the primary quote, the current offer to the customerbooleanPrimary

The total value of the quote, calcuated as the sum of the associated quoteline items

currencyTotal

Table 2: QuoteLine Fields

DescriptionField TypeField

The identifying number of the quote line item that is assigned automaticallywhen each item is inserted. Note that this value cannot be set directly, and

stringName

cannot be modified after the quote line item is created. This is a standardfield.

The color of the product associated with the quote line item. The valuefor this field is copied from the product when the quote line item is created.

picklistColor

11

Walking Through a Sample Apex Code Application

Page 14: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionField TypeField

The ID of the associated product record for this quote line itemreferenceProduct

The number of units of the productintQuantity

The ID of the associated quote record for this quote line itemreferenceQuote

The total value of the quote line item, calcuated as the Unit Price timesQuantity

currencyTotal Price

The per unit price of the product associated with the quote line itemcurrencyUnit Price

To illustrate the movement of a field value from one record to another, the sample application additionally includes a customColor picklist field on the Product2 and OpportunityLineItem standard objects. On Product2, this value is meant to representthe "default" color, while the color on OpportunityLineItem is the color of the actual units being sold.

Business Rules

The sample application implements the following business rules:

1. When a new product line item is added to an opportunity, the sample application copies the product's custom Color fieldto the opportunity line item.This work is performed in addition to the updates to the opportunity line item's Unit Priceand Total Price fields that the platform already performs by default.

2. When a user wants to generate a quote from an opportunity, the quote's line items are automatically built from theopportunity's line items.

3. When the unit price or quantity of a quote line item changes, the change should be reflected in the total price of the quoteline item and its related quote.

4. A user should never be able to:

• Delete an opportunity if it has a quote• Delete a quote if it is the primary quote of an opportunity• Change the value of an existing quote's primary field to false, unless another quote is selected as the primary

5. When a quote is selected as the primary quote for an opportunity, no other quotes associated with the opportunity shouldbe marked as the primary quote.

The next section walks through the Apex Code that implements these business rules in detail.

Note: To make the code easy to follow, each example only includes the portions of the code that correspond to thebusiness rule being addressed. For the complete quoting application, see Quoting App Sample Code on page 106.

Examples

Example 1: Copying a Field Value

To implement the first business rule, the sample application needs to copy a product's custom Color field to an opportunityline item when the line item is added to an opportunity. This functionality is in addition to the updates to the opportunityline item's Unit Price and Total Price fields that the platform already performs by default.

Because this functionality should occur whenever a new opportunity line item is created, the sample application uses an ApexCode component called a trigger. A trigger is a piece of code that executes before or after records of a particular type areinserted, updated, or deleted from the Apex platform database. Every trigger runs with a set of context variables that provideaccess to the records that caused the trigger to fire. All triggers run in bulk, that is, they process several records at once.

12

Walking Through a Sample Apex Code Application

Page 15: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

In this instance, the sample application uses a before insert trigger when the OpportunityLineItem record is created sothat the trigger can assign a value to the color__c custom field before the line items are saved to the database:

trigger oppLineTrigger on OpportunityLineItem bulk (before insert) {

// Determine the distinct pricebook entries Set<Id> pbeIds = new Set<Id>(); for (OpportunityLineItem oli : Trigger.new) pbeIds.add(oli.pricebookentryid);

// Query the pricebook entries Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>( [select product2.color__c from pricebookentry where id in :pbeIds]);

// Now set the colors on the opportunity line items for (OpportunityLineItem oli : Trigger.new) oli.color__c = entries.get(oli.pricebookEntryId).product2.color__c; }

Note the following code in this trigger:

• trigger oppLineTrigger on OpportunityLineItem bulk (before insert) {

Similar to a Java method declaration, this trigger declaration states that the following trigger named oppLineTriggerexecutes before any OpportunityLineItem record is inserted into the database. The bulk keyword is required and denotesthat this trigger processes several records at a time in batches.

• Set<Id> pbeIds = new Set<Id>(); for (OpportunityLineItem oli : Trigger.new) pbeIds.add(oli.pricebookentryid);

In any insert or update trigger, Trigger.new is a list that provides access to the new version of eachOpportunityLineItem record that is being processed by the trigger. In any update or delete trigger, Trigger.oldprovides access to the old versions of the records.

In this instance, the code adds each PricebookEntry associated with the OpportunityLineItem records in Trigger.newto a set, ensuring that the set contains only distinct elements.

• Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>( [select product2.color__c from pricebookentry where id in :pbeIds]);

This statement queries the PricebookEntries for their associated product color by issuing a SOQL query (in square brackets[]) and then creates a map of the results. Note that :pbeIds is a local trigger variable used within the SOQL query itself.You can use any Apex Code variable in a SOQL query as long as it is preceded by a colon (:).

Note:

For a full description of SOQL query syntax, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#sforce_api_calls_soql.htm.

• for (OpportunityLineItem oli : Trigger.new) oli.color__c = entries.get(oli.pricebookEntryId).product2.color__c;

This final statement goes back to the Trigger.new list and iterates over each OpportunityLineItem record that it containsto assign it the appropriate product color, according to the map created in the previous step.

Lastly, this trigger also demonstrates the case insensitivity of Apex Code. SOQL field references, keywords and Apex Codeidentifiers can all use mixed case.

13

Walking Through a Sample Apex Code Application

Page 16: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Example 2: Copying Records

For the second business rule, when a user wants to generate a quote from an opportunity, the new quote's line items shouldbe automatically built from the opportunity's line items. To do this, the sample application uses an after insert triggeron the Quote object. An after trigger is used in this instance because the sample application does not need to modify anyfields on the quote record itself. Instead, the application just needs to create new quote line items for the parent quotes thatwere just generated:

trigger quoteTrigger on quote__c bulk (after insert) { for (Quote__c q : Trigger.new) { util.copyLineItemsFromOpp(q);}

Note: In the complete version of the sample application this trigger includes additional code. See Example 4: PreventingSaves on page 17 and Example 5: Implementing One-and-Only-One Logic on page 19.

The trigger consists of a for loop that iterates over each element in the Trigger.new context variable list, and makes a callto a stored package method, util.copyLineItemsFromOpp() for each record. In Apex Code, a package is equivalent to astandard library of stored methods and variables. The sample application abstracts the copyLineItemsFromOpp() methodinto the util package so that it can be reused by other scripts and triggers.

The code below shows the util package definition of copyLineItemsFromOpp():

package util { // Package variables can be used for communication between triggers public String quoteId;

// This method moves opportunity line items to the given quote q. public void copyLineItemsFromOpp(Quote__c q) {

// We will modify and update this quote at the end, so we clone it // first since Trigger.new records cannot be modified in after triggers q = q.clone();

try {

// By setting the quoteId package variable, this method tells // the quoteLine trigger that it should disable itself during this // operation (the quoteLine trigger is described in Example 3) quoteId = q.id;

// Now the method creates an empty array of quote line items quoteline__c[] quoteitems = new quoteline__c[0];

// Next, it manually calculates the overall total for the quote // by iterating over an array of OpportunityLineItem records that // are returned from a SOQL query. The query selects the data from // opportunity line items that match the opportunity associated // with the quote. Double tot = 0; // The running total Integer i = 0; // Number the line items

for (opportunitylineitem oppline : [select pricebookentry.product2id, color__c, unitprice, quantity, totalprice from opportunitylineitem where opportunityid = :q.opportunity__c order by createddate]) {

i++;

14

Walking Through a Sample Apex Code Application

Page 17: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// For each opportunity line item, the method // calculates the running total if (oppline.unitprice != null && oppline.quantity != null) tot += oppline.unitprice * oppline.quantity;

// And then it adds a new quote line item to the quoteitems, // array, initializing it with values. quoteitems.add( new quoteline__c( quote__c = q.id,

// The method uses the counter variable to number // the line items. Because the SOQL query ordered // them by the date they were created with an ORDER BY // clause, they will be numbered that way as well. name = String.valueOf(i),

// The method then uses the values for product, unit // price, quantity, total price, and color from the // opportunity line item. product__c = oppline.pricebookentry.product2id, unitprice__c = oppline.unitprice, quantity__c = oppline.quantity, totalprice__c = oppline.totalprice, color__c = oppline.color__c)); }

// The method adds the whole array of quote line items // to the database with a single insert statement. insert quoteitems;

// And then it updates the quote's overall total q.total__c = tot; update q;

} finally {

// To clean up the working variable, the method resets quoteId // to null. quoteId = null; } }}

Note the following about the code above:

• No data is returned by copyLineItemsFromOpp() because Apex Code uses pass-by-reference. That is, all changes tothe quote passed into the method are reflected afterwards in the code that called it.

• copyLineItemsFromOpp() uses a strongly typed method declaration and accepts only a single Quote__c variable. Unlikethe Apex API, Apex Code does not allow for abstract types like SObject. Instead, all methods and variables must bedeclared with a concrete type.

• Package variables such as quoteId allow triggers that are spawned by the same operation to communicate with one another.In this case, when copyLineItemsFromOpp() is creating several quote line items for a new quote, it sets quoteId to anon-null value. This signals another piece of the code (highlighted in Example 3: Performing Calculations), to refrainfrom executing.

• copyLineItemsFromOpp() takes a single Quote__c object as it’s argument. As an exercise for the reader, this methodshould be converted to operate on a list of quote records so that the Opportunity Line Item query in the sample is executedonly once no matter how many quotes are submitted.

15

Walking Through a Sample Apex Code Application

Page 18: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Example 3: Performing Calculations

For the third business rule, the sample application needs to update the total price of a quote when a related quote line itemchanges. To implement this, the sample application uses a single trigger on the QuoteLine object whenever a QuoteLinerecord is inserted, updated, or deleted, as shown below:

// A single trigger can handle multiple triggering conditions by adding each// condition to the trigger declaration. For example, this trigger is fired// when five of the six possible triggering conditions occur.trigger quoteLineTrigger on quoteLine__c bulk (before insert, before update, after insert, after update, after delete) {

// Trigger context variables like Trigger.isBefore and Trigger.isUpdate // allow a multi-condition trigger to execute Apex Code only when a // certain condition occurs. if (Trigger.isBefore) { for (quoteLine__c ql : Trigger.new) {

// If the trigger fires before quote line items are updated or // inserted, the TotalPrice__c field is updated on each item. // Note that this calculation could have also been implemented // with a formula field in the application. if (Trigger.isUpdate || Trigger.isInsert) { ql.totalprice__c = ql.unitprice__c * ql.quantity__c; } } } else {

// As we did in Example 1, use a set to make sure we have a list of all // the distinct quotes that we are modifying. This is the first step in a // common bulk processing idiom. Set<Id> quoteIds = new Set<Id>();

// Note the use of the ternary operator to get the correct size of the // lists and then the correct IDs for each quote--for the delete case, // the application uses the Trigger.old list variable, while for insert // and update, the application uses Trigger.new. for (Integer i = 0; i < (Trigger.isDelete ? Trigger.old.size() : Trigger.new.size()); i++) { quoteIds.add(Trigger.isDelete ? Trigger.old[i].quote__c : Trigger.new[i].quote__c); }

// Now as the second step in our bulk processing idiom, use the set to issue // a SOQL query and create a map of Ids to Quotes Map<Id, Quote__c> quotes = new Map<Id, Quote__c>( [select id, total__c from quote__c where id in :quoteIds]);

// For each quote line item in Trigger.old or Trigger.new, find the quoteId for (Integer i = 0; i < (Trigger.isDelete ? Trigger.old.size() : Trigger.new.size()); i++) { String quoteId = Trigger.isDelete ? Trigger.old[i].quote__c : Trigger.new[i].quote__c;

// If the trigger fires after a quote line item is updated or deleted // the total__c field on the parent quote needs to be updated. However, // if this trigger fires in the middle of inserting a quote (that is, if // we're working on the same quote that the util.copyLineItemsFromOpp // method is working on, we skip this logic here (see Example 2) if (quoteId == util.quoteId) continue;

// As the third step in our bulk processing idiom, get the parent quote // (which must be in the set we created above) quote__c q = quotes.get(quoteId);

16

Walking Through a Sample Apex Code Application

Page 19: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// If the quote total does not yet have a value, the trigger first sets // it to zero. if (q.total__c == null) q.total__c = 0;

// If the quote line item is being inserted, the trigger // increments the total value of the quote if (Trigger.isInsert && Trigger.new[i].totalprice__c != null) { q.total__c += Trigger.new[i].totalprice__c; }

// If the quote line item is being updated, the trigger adds the new // line item total to the quote, and subtracts the old line item // total from the quote if (Trigger.isUpdate) { if (Trigger.new[i].totalprice__c != null) q.total__c += Trigger.new[i].totalprice__c; if (Trigger.old[i].totalprice__c != null) q.total__c -= Trigger.old[i].totalprice__c; }

// If the quote line item is being deleted, the trigger // decrements the total value of the quote if (Trigger.isDelete && Trigger.old[i].totalprice__c != null) { q.total__c -= Trigger.old[i].totalprice__c; } }

// For the fourth and final step of the bulk processing idiom, // update all quotes in bulk update quotes.values(); }}

Note the following about the code above:

• The trigger uses a common bulk processing idiom:

1. Create a set that includes all the distinct record Ids that require an update (in this case, the distinct parent quote recordsfor every quote line item in Trigger.new or Trigger.old).

2. Use the set to issue a SOQL query that maps Ids to the actual records themselves (Map<Id, quote__c>)3. For every record in Trigger.new or Trigger.old, use the map to access the appropriate record and update it as

appropriate.4. Update the database in bulk.

• The quoteId package variable is checked midway through the code to determine whether this trigger is firing as the resultof a new quote line item on a new quote, or whether it is simply a new or updated line item on an existing quote. If it isan existing quote, the quote total needs to be updated appropriately.

Example 4: Preventing Saves

For the fourth business rule, a user should never be able to delete:

• An opportunity if it has a quote• A quote if it is the primary quote of an opportunity• The value of the primary field for an existing quote

Apex Code allows you to prevent an operation from occurring by using an addError() method. Consequently, to implementthis business rule, the application needs to use addError() in both an opportunity trigger, and in the quote trigger discussedpreviously in Example 2: Copying Records:

17

Walking Through a Sample Apex Code Application

Page 20: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Note: Some code that is not related to this example has been omitted from quoteTrigger for readability.

// This trigger prevents the deletion of any opportunity that// has an associated quotetrigger oppTrigger on Opportunity bulk (before delete) {

// Trigger.oldMap is a trigger context variable that maps Ids to every // opportunity that is about to be deleted. Use it in a SOQL query to // create a list of associated quotes. for (Quote__c q : [select opportunity__c from quote__c where opportunity__c in :Trigger.oldMap.keySet()]) {

// For every quote that is active, retrieve the related opportunity // from Trigger.oldMap and prevent it from being deleted by placing // an error message on the opportunity. Trigger.oldMap.get(q.opportunity__c).addError( 'Cannot delete opportunity with a quote'); }}

// This quote trigger has been augmented to prevent deletion of the // primary quote on an opportunity, as well as the value of the Primary // field for an existing quote. Note that the code that was included in // Example 2 is still included in this trigger. trigger quoteTrigger on quote__c bulk (before update, before delete, after insert) { if (Trigger.isBefore) { if (Trigger.isUpdate) {

// The trigger first verifies that a primary quote is not // setting its Primary value to false. For each quote that // is being updated, the trigger gets a copy of the old // version and the new version. (Note that this is a common // bulk trigger technique for working with parallel new and // old lists.) for (Integer i = 0; i < Trigger.old.size(); i++) { Quote__c old = Trigger.old[i]; Quote__c nw = Trigger.new[i];

if (old.primary__c && !nw.primary__c) {

// A primary quote should only be set to non-primary if // the application is in the middle of a transaction // that switches the primary flag to another quote. // The next if statement tests that this condition is // not true by comparing the old quote's opportunityId // with the util package opportunityId variable (see // Example 5). if (old.opportunity__c != util.opportunityId) { nw.Primary__c.addError('Primary quote cannot be marked non-primary'); } } } }

// Next the trigger verifies that a primary quote is not being deleted if (Trigger.isDelete) { for (Quote__c q : Trigger.old) {

// If a primary quote is being deleted, the trigger prevents // it with addError(). if (q.primary__c) { q.addError('Primary quote cannot be deleted');

18

Walking Through a Sample Apex Code Application

Page 21: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

} } } } else {

// The trigger still includes the code from Example 2. for (Quote__c q : Trigger.new) { util.copyLineItemsFromOpp(q); } }}

Example 5: Implementing One-and-Only-One Logic

For the final business rule, the Is Primary flag must be set to false on all associated quotes if a new quote is selected as theprimary.The sample application implements this rule by augmenting the Trigger.isAfter if statement in the quote triggeralready presented in Example 2: Copying Records and Example 4: Preventing Saves, and by defining an additional methodin the util package.

Note: Some code that is not related to this example has been omitted from this trigger for readability.

// The quoteTrigger now includes an additional after update conditiontrigger quoteTrigger on quote__c bulk (after insert, after update, before update, before delete) { if (Trigger.isBefore) {

// Code from Example 4 omitted for readability

} else {

// The trigger still includes the code from Example 2, but this // time it is wrapped in an if clause. if (Trigger.isInsert) { for (Quote__c q : Trigger.new) { util.copyLineItemsFromOpp(q); } }

// After inserts and updates, we must ensure that only one record is marked // as primary. To do so, we get all opportunities referenced by the quotes // in Trigger.new that attempt to be primary and set the other's primary flags // to false. Special care is taken for the case where two or more records // within this batch attempt to be primary for the same opportunity

//Used to hold quotes that are marked as primary List<Quote__c> primaries = new List<Quote__c>();

// Used to map the opportunity Id for which there is a quote attempting // to be primary to the corresponding Quote Map<Id, Id> opWithPrimary = new Map<Id, Id>();

// Used to hold the Ids of quotes that attempt to be primary // for the same opportunity Set<Id> badQuotes = new Set<Id>();

for (Integer i = 0; i < Trigger.new.size(); i++) { Quote__c nw = Trigger.new[i]; // If the new quote is marked as primary and was either just inserted // or was not the primary quote before this operation if (nw.primary__c && (Trigger.isInsert || !Trigger.old[i].primary__c)) { // If there already is a quote that attempts to be primary for // this quote's opportunity

19

Walking Through a Sample Apex Code Application

Page 22: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

if (opWithPrimary.containsKey(nw.opportunity__c)) { // Then both quotes are bad, and should be remembered badQuotes.add(opWithPrimary.get(nw.opportunity__c)); badQuotes.add(nw.Id); } else { // The quote is good so far, add it to our list primaries.add(nw);

// Remember this quote's opportunity in case another quote // also wants to be primary for it opWithPrimary.put(nw.opportunity__c, nw.Id); } } }

// Mark the bad quotes as such for (Id bad : badQuotes) { Quote__c q = Trigger.newMap.get(bad); q.primary__c.AddError('More than one quote is attempting to be primary for this opportunity: ' + q.opportunity__c); }

// Remove the bad quotes from our set of good ones // We'll do this by first ensuring there are no duplicates by copying Ids // into a set and then removing the bad quotes' Ids from that set Set<Id> primaryIds = new Set<Id>(); for (Quote__c q : primaries) primaryIds.add(q.Id);

primaryIds.removeAll(badQuotes);

// Now that we have a set of unique and good quote ids, we need to // get the corresponding Quote__c objects primaries.clear(); util.opportunityIds.clear(); for (Id primId : primaryIds) { Quote__c q = Trigger.newMap.get(primId); primaries.add(q); // You need to remember the opportunity ids we're setting a new // primary quote for across triggers, so the before update trigger // doesn't throw an error about no primary quote existing util.opportunityIds.add(q.opportunity__c); }

// The trigger makes a call to getOtherPrimaryQuotes() in the util package // and assigns the result to a list of quotes. Quote__c[] others = util.getOtherPrimaryQuotes(primaries);

// Then it sets the primary flag to false for all the returned quotes // and updates the list for (quote__c q : others) { q.primary__c = false; }

try { update others; } finally { util.opportunityIds.clear(); } }}package util {

// Package variables can be used for communication between triggers public String quoteId; public String opportunityId;

20

Walking Through a Sample Apex Code Application

Page 23: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// This package method returns the primary quotes for all opportunities // associated with the given quotes, other than the quote passed into the method. // If there is no other primary quote, the method returns null. public Quote__c[] getOtherPrimaryQuotes(List<Quote__c> qs) { // Retrieve the list of all opportunities referenced by the given quotes List<Id> ops = new List<Id>(); for(Quote__c q : qs) ops.add(q.opportunity__c);

// Now retrieve all quotes that reference the opportunities, // excluding the given quotes Quote__c[] others = [select id from quote__c where opportunity__c = :ops and id not in :qs and primary__c = true]; return others; }

// Code from other examples omitted for readability }

This example now allows a full explanation of the code in Example 4: Preventing Saves. In that example, no quotes wereallowed to set their Primary field to false before being updated. However, in Example 5: Implementing One-and-Only-OneLogic, all quotes have their primary field set to false in the Trigger.isAfter code after a new primary quote has alreadybeen inserted. Consequently, the logic can be understood as follows:

1. Turn on the Primary field for the new Quote and insert it.2. Disable the Primary field for the old quote.

This logic is possible because the before and after triggers execute in the same transaction, before any change is actuallycommitted.

Note: Apex Code recognizes in-process data changes that have not yet been committed. In this example, no partof the save is committed until the entire operation, including these triggers, has completed successfully.

Testing the Sample Application

A well-written, data-focused application should assert its functionality through the use of unit and functional testing. For anexample and discussion of the functional tests that were implemented for the sample application, see Testing and CodeCoverage on page 97.

21

Walking Through a Sample Apex Code Application

Page 24: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 3

Apex Code Data Types, Variables, and Expressions

This chapter provides an overview of the primitive and complex data types,variable and constant declaration syntax, and operators and expressions that areused in Apex Code.

In this chapter ...

• Data Types• Iterating Collections In most cases, the rules that are described here are modeled on their counterparts

in Java and the Apex Web services API and can be quickly understood by those• Variables• Expressions who are familiar with them. Sections that discuss notable differences from Java

and the API include:

• SObject Types on page 24. In Apex Code, the term SObject refers to anyobject that is stored in the Apex platform database. However, unlike the Webservices API, the SObject type cannot be used to declare variables or definemethods. Instead, all object record variables must be instantiated with astrongly-typed variable that uses the name of the object type being declared.For example:

Account a = new Account();MyCustomObject__c co;

• Lists of SObjects on page 27. When an array of SObject records is insertedor upserted into the database with Apex Code, all new records areautomatically assigned a unique Id value without any additional code.Consequently, every record in the array must reference a unique location inmemory. Duplicate references in an array are not allowed and generate anexception.

• Creating Maps From SObject Arrays on page 29. Apex Code supports thequick creation of Id-to-SObject maps from an array of SObject records.

• Case Sensitivity on page 30. Apex Code is a case-insensitive language.• SOQL Queries on page 38. Apex Code defines syntax that allows developers

to embed Sforce Object Query Language (SOQL) statements into ApexCode as a way of populating arrays of SObject records. Use these SOQLqueries to quickly access data from the database.

22

Page 25: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Data Types

In Apex Code, all variables and expressions have a data type that is one of the following:

• A primitive, such as an Integer, Double, Date, Datetime, String, Id, or Boolean (see Primitive Data Types on page 23)• An SObject, such as an Account, Contact, or MyCustomObject__c (see SObject Types on page 24)• A collection, including:

• A list (or array) of primitives, SObjects, or other collections (see Lists on page 26)• A set of primitives (see Sets on page 28)• A map from a primitive to a primitive, SObject, or other collection (see Maps on page 28)

• A class (for Exceptions only—see Exception Types on page 58)• Null (for the null constant, which can be assigned to any variable)

Methods can return values of any of the listed types, or return no value and be of type Void.

Type checking is strictly enforced at compile time. For example, the parser generates an error if an object field of type Integeris assigned a value of type String. However, all compile-time exceptions are returned as specfic fault codes, with the line numberand column of the error. For more information, see Debugging Apex Code on page 95.

Primitive Data Types

Apex uses the same primitive data types as the Web services API. These include:

DescriptionData Type

A value that can only be assigned true, false, or null. For example:

Boolean isWinner = true;

Boolean

A value that indicates a particular day. Unlike Datetime values, Date values contain noinformation about time. Date values must always be created with a system static method. SeeSystem Static Methods on page 62 and Date Methods on page 77 for information.

Date

A value that indicates a particular day and time, such as a timestamp. Datetime values mustalways be created with a system static method. See System Static Methods on page 62 andDatetime Methods on page 78 for information.

Datetime

A 64-bit number that includes a decimal point. For example:Double d=3.14159;

Double

Note that scientific notation (e) for Doubles is not supported.

Any valid 18-character Apex record identifier. For example:

Id id=00300000003T2PGAA0;

Id

Note that if you set Id to a 15-character value, Apex Code automatically converts the valueto its 18-character representation. All invalid Id values are rejected with a runtime exception.

A 32-bit number that does not include a decimal point. Integers have a minimum value of-2,147,483,648 and a maximum value of 2,147,483,647. For example:

Integer i = 1;

Integer

23

Data Types

Page 26: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionData Type

Any set of characters surrounded by single quotes. For example,String s = 'The quick brown fox jumped over the lazy dog.';

String

Empty Strings and Trailing Whitespace: SObject String field values follow the same rulesas in the Web services API: they can never be empty (only null), and they can never includeleading and trailing whitespace. These conventions are necessary for database storage.

Conversely, Strings in Apex Code can be null or empty, and can include leading and trailingwhitespace (such as might be used to construct a message).

Escape Sequences: All Strings in Apex Code use the same escape sequences as SOQL strings:\b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), \" (doublequote), \' (single quote), and \\ (backslash).

Comparison Operators: Unlike Java, Apex Code Strings support use of the comparisonoperators ==, !=, <, <=, >, and >=. Since Apex Code uses SOQL comparison semantics,results for Strings are collated according to the context user's locale, and are not case sensitive.For more information, see Expression Operators on page 32.

String Methods: As in Java, Strings can be manipulated with a number of standard methods.See String Methods on page 75 for information.

In addition, two non-standard primitive data types cannot be used as variable or method types, but do appear in system staticmethods:

• AnyType. The valueOf() static method converts an SObject field of type AnyType to a standard primitive. AnyTypeis used within the Apex platform database exclusively for SObject fields in field history tracking tables.

• Currency. The Currency.newInstance() static method creates a literal of type Currency. This method is for use solelywithin SOQL WHERE clauses to filter against SObject currency fields.

For more information on AnyType and Currency data types, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

For more information on the methods in which they appear, see System Static Methods on page 62.

SObject Types

In this language reference, the term SObject refers to any object that can be stored in the Apex platform database. An SObjectvariable represents a row of data and can only be declared in Apex Code using the Web services API name of the object. Forexample:

Account a = new Account();MyCustomObject__c co = new MyCustomObject__c();

Unlike the Web services API, which allows the use of the generic SObject abstract type to represent any object record, ApexCode requires a strongly typed object variable declaration. This allows the Apex Code engine to validate object and fieldreferences at compile time.

SObject variables are initialized to null, but can be assigned a valid object reference with the new operator. For example:

Account a = new Account();

24

Data Types

Page 27: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Developers can also specify initial field values with comma-separated <name>=<value> pairs when instantiating a new SObject.For example:

Account a = new Account(name = 'Acme', billingcity = 'San Francisco');

For information on accessing existing SObjects from the Apex platform database, see SOQL Queries on page 38.

Note: The Id of an SObject is a read-only value and can never be modified explicitly in Apex Code unless it is clearedduring a clone operation, or is assigned with constructor. The Apex platform assigns Id values automatically when anobject record is initially inserted to the database for the first time. For more information see Lists of SObjects on page27.

Accessing SObject Fields

As in Java, SObject fields can be accessed or changed with simple dot notation. For example:

Account a = new Account();a.name = 'Acme'; // Access the account name field and assign it 'Acme'

All active permissions for the context user are upheld when modifying SObject field values in Apex Code. As a result, if youattempt to change the value of a system generated field such as Created By or Last Modified Date, the Apex Coderuntime engine generates an error. Additionally, formula field values and values for other fields that are read-only for thecontext user cannot be changed.

Accessing SObject Fields Through Relationships

SObject records represent relationships to other records with two fields: an Id and an address that points to a representationof the associated SObject. For example, the Contact SObject type has both an AccountId field of type Id, and an Accountfield of type Reference that points to the associated SObject record itself.

The Id field can be used to change the account with which the contact is associated, while the SObject reference field isread-only, and can only be used to access data from the account. The reference field is only populated as the result of a SOQLquery (see note below).

For example, the following Apex Code shows how an account and a contact can be associated with one another, and thenhow the contact can be used to modify a field on the account:

Note: In order to provide the most complete example, this code uses some elements that are described later in thisguide:

• For information on insert and update, see Data Manipulation Language (DML) Statements on page 49.• For information on SOQL, see SOQL Queries on page 38.

Account a = new Account(name = 'Acme');insert a; // Inserting the record automatically assigns a // value to its Id fieldContact c = new Contact(lastName = 'Weissman');c.accountId = a.Id;// The new contact now points at the new accountinsert c;

// A SOQL query accesses data for the inserted contact, // including a populated c.account fieldc = [select account.name from contact where id = :c.id];

// Now fields in both records can be changed through the contactc.account.name = 'salesforce.com';c.lastName = 'Roth';

25

Data Types

Page 28: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// To update the database, the two types of records must be // updated separatelyupdate c; // This only changes the contact's last nameupdate c.account; // This updates the account name

Note: The expression c.account.name, as well as any other expression that traverses a relationship, displays slightlydifferent characteristics when it is read as a value than when it is modified:

• When being read as a value, if c.account is null, then c.account.name evaluates to null, but does not yield aNullPointerException. This design allows developers to navigate multiple relationships without the tediumof having to check for null values.

• When being modified, if c.account is null, then c.account.name does yield a NullPointerException.

SObject and Field Validation

When an Apex Code script is parsed and validated, all SObject and field references are validated against actual object andfield names, and a parse-time exception is thrown when an invalid name is used.

In addition, the Apex Code parser tracks the custom objects and fields that are used, both in the script's syntax as well as inembedded SOQL statements.The platform uses this information to determine whether saved Apex Code remains syntacticallyvalid after a change has been made to an organization's metadata. If an object or field name that is used in the script changes,the platform marks the Apex Code as invalid and it no longer can be executed.

Common SObject Methods

All SObject variables support built-in methods for clearing field values, duplicating objects, and displaying object error messages.

For more information, including a complete list of all supported SObject system methods, see SObject Methods on page 74.

Lists

A list is an ordered collection of identically typed primitives, SObjects, or collections that are distinguished by their indices.For example, the following table is a visual representation of a list of Strings:

Index 5Index 4Index 3Index 2Index 1Index 0

'Purple''Blue''Green''Yellow''Orange''Red'

The index position of the first element in a list is always 0.

Because lists can contain any collection, they can be nested within one another and become multidimensional. For example,you can have a list of lists of sets of Integers. A list can only contain up to five levels of nested collections inside it.

To declare a list, use the List keyword followed by the primitive data, SObject, nested list, map, or set type within <>characters. For example:

List<String> my_list = new List<String>();List<List<Set<Integer>>> my_list_2 = new List<List<Set<Integer>>>();

To access elements in a list, use the system methods provided by Apex Code. For example:

List<Integer> l = new List<Integer>(); // Define a new listl.set(0, 1); // Adds the integer 1 to the set at index 0l.get(0); // Retrieves the element at index 0myIntArray.add(47); // Adds a second element of value 47 to the end // of the listmyIntArray.clear(); // Removes all elements from the list

26

Data Types

Page 29: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

For more information, including a complete list of all supported methods, see List Methods on page 68.

Note: Lists can have no more than 1000 elements, and will generate a runtime exception if they surpass this limit.For more information on execution limits, see Execution Governors and Limits on page 100.

Using Array Notation for One-Dimensional Lists of Primitives or SObjects

When using one-dimensional lists of primitives or SObjects, you can also use more traditional array notation to declare andreference list elements. For example, you can declare a one-dimensional list of primitives or SObjects by following the dataor SObject type name with the [] characters:

String[] colors = new List<String>();

To reference an element of a one-dimensional list of primitives or SObjects, you can also follow the name of the list with theelement's index position in square brackets. For example:

colors[3] = 'Green';

All lists are initialized to null, but one-dimensional lists of primitives or SObjects can be assigned values and allocated memoryusing literal notation. For example:

DescriptionExample

Defines an Integer list with no elementsList<Integer> ints = new Integer[0];

Defines an Account list with no elementsList<Account> accts = new Account[]{};

Defines an Integer list with memory allocated for six IntegersList<Integer> ints = new Integer[6];

Defines an Account list with memory allocated for threeAccounts, including a new Account object in the first position,

List<Account> accts = new Account[]{new

Account(), null, new Account()};

null in the second position, and another new Account objectin the third position

Lists of SObjects

Apex automatically generates Ids for each object in a list of SObjects when the list is successfully inserted or upserted into thedatabase with a data manipulation language (DML) statement. Consequently, a list of SObjects cannot be inserted or upsertedif it contains the same SObject more than once, even if it has a null Id. This situation would imply that two Ids would needto be written to the same structure in memory, which is illegal.

For example, the insert statement in the following block of code generates an ArrayException because it tries to inserta list with two references to the same SObject (a):

try {

// Create a list with two references to the same SObject element Account a = new Account(); Account[] accs = new Account[]{a, a};

// Attempt to insert it... insert accs;

// Will not get here System.assert(false);} catch (System.ArrayException e) {

27

Data Types

Page 30: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// But will get here}

For more information on DML statements, see Data Manipulation Language (DML) Statements on page 49.

Sets

A set is an unordered collection of primitives that do not contain any duplicate elements. For example, the following tablerepresents a set of city names:

'Tokyo''Paris''New York''San Francisco'

To declare a set, use the Set keyword followed by the primitive data type name within <> characters. For example:

Set<String> cities = new Set<String>();

Note: Because sets can only include primitive data types, they do not allow nesting.

To access elements in a set, use the system methods provided by Apex Code. For example:

Set<Integer> s = new Set<Integer>(); // Define a new sets.add(1); // Add an element to the setSystem.assert(s.contains(1)); // Assert that the set contains an elements.remove(1); // Remove the element from the set

For more information, including a complete list of all supported set system methods, see Set Methods on page 70.

Note: Sets can have no more than 1000 elements, and will generate a runtime exception if they surpass this limit. Formore information on execution limits, see Execution Governors and Limits on page 100.

Note: Unlike Java, Apex Code developers do not need to reference the algorithm that is used to implement a set intheir declarations (for example, HashSet or TreeSet). Apex Code uses a hash structure for all sets.

Maps

A map is a collection of key-value pairs where each unique key maps to a single value. Keys can be any primitive data type,while values can be a primitive, SObject, or collection type. For example, the following table represents a map of countriesand currencies:

'India''England''France''Japan''United States'Country (Key)

'Rupee''Pound''Euro''Yen''Dollar'Currency (Value)

Similar to lists, map values can contain any collection, and can be nested within one another. For example, you can have amap of Integers to maps, which, in turn, map Strings to lists. A map can only contain up to five levels of nested collectionsinside it.

28

Data Types

Page 31: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

To declare a map, use the Map keyword followed by the data type of the key and the value within <> characters. For example:

Map<String, String> country_currencies = new Map<String, String>();Map<Id, Set<String>> m = new Map<Id, Set<String>>();Map<Id, Map<Id, Account[]>> m2 = new Map<Id, Map<Id, Account[]>>();

To access elements in a map, use the system methods provided by Apex Code. For example:

Account myAcct = new Account(); //Define a new accountMap<Integer, Account> m = new Map<Integer, Account>(); // Define a new mapm.put(1, myAcct); // Insert a new key-value pair in the mapSystem.assert(!m.containsKey(3)); // Assert that the map contains a keyAccount a = m.get(1) // Retrieve a value, given a particular keySet<Integer> s = m.keySet(); // Return a set that contains all of the keys in the map

For more information, including a complete list of all supported map system methods, see Map Methods on page 72.

Note: Maps can have no more than 1000 elements, and will generate a runtime exception if they surpass this limit.For more information on execution limits, see Execution Governors and Limits on page 100.

Note: Unlike Java, Apex Code developers do not need to reference the algorithm that is used to implement a map intheir declarations (for example, HashMap or TreeMap). Apex Code uses a hash structure for all maps.

Creating Maps From SObject Arrays

Maps from an Id or String data type to an SObject can be initialized from a list of SObjects. The Ids of the objects (whichmust be non-null and distinct) are used as the keys. One common usage of this map type is for in-memory "joins" betweentwo tables. For instance, this example loads a map of Ids and Contacts:

Map<Id, Contact> m = new Map<Id, Contact>([select id, lastname from contact])

In the example, the SOQL query returns a list of contacts with their id and lastname fields. The new() method uses thelist to create a map. For more information, see SOQL Queries on page 38.

Iterating Collections

Collections can consist of lists, sets, or maps. Modifying a collection's elements while iterating that collection is not supportedand causes an error. Do not directly add or remove elements while the collection that includes them is being iterated.

Adding Elements While Iterating

To add elements while iterating a list, set or map, keep the new elements in a temporary list, set, or map and add them to theoriginal after you finish iterating.

Removing Elements While Iterating

To remove elements while iterating a list, create a new list, then copy the elements you wish to keep. Alternatively, add theelements you wish to remove to a temporary list and remove them after you finish iterating.

Note:

List.remove() performs linearly. Using it to remove elements has time and resource implications.

29

Iterating Collections

Page 32: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

To remove elements while iterating a map or set, keep the keys you wish to remove in a temporary list, then remove themafter you finish iterating.

Variables

Declaring Local Variables

Local variables are declared with Java-style syntax. For example:

Integer i = 0;String str;Account a;Account[] accts;Set<String> s;Map<Id, Account> m;

As with Java, multiple variables can be declared and initialized in a single statement, using comma separation. For example:

Integer i, j, k;

All variables allow null as a value and are initialized to null if they are not assigned another value. For instance, in thefollowing example, i, and k are assigned values, while j is set to null because it is not assigned:

Integer i = 0, j, k = 1;

Variables can be defined at any point in a block, and take on scope from that point forward. Sub-blocks cannot redefine avariable name that has already been used in a parent block, but parallel blocks can reuse a variable name. For example:

Integer i;{ // Integer i; This declaration is not allowed}

for (Integer j = 0; j < 10; j++);for (Integer j = 0; j < 10; j++);

Case Sensitivity

To avoid confusion with case-insensitive SOQL queries, Apex Code is also case-insensitive. This means:

• Variable and method names are case insensitive. For example:

Integer I;//Integer i; This would be an error.

• References to object and field names are case insensitive. For example:

Account a1;ACCOUNT a2;

• SOQL statements are case insensitive. For example:

Account[] accts = [sELect ID From ACCouNT where nAme = 'fred'];

30

Variables

Page 33: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Also note that Apex Code uses the same filtering semantics as SOQL, which is the basis for comparisons in the Web servicesAPI and the Salesforce application user interface. The use of these semantics can lead to some interesting behavior. Forexample, if an end user generates a report based on a filter for values that come before 'm' in the alphabet (ie, values < 'm'),null fields are returned in the result. The rationale for this behavior is that users typically think of a field without a value asjust a "space" character, rather than its actual "null" value. Consequently, in Apex Code, the following expressions all evaluateto true:

String s;System.assert('a' == 'A');System.assert(s < 'b');System.assert(!(s > 'b'));

Note: Although s < 'b' evaluates to true in the example above, s.compareTo('b') generates an error becausethe compareTo() method is based on its Java equivalent, and does not allow comparisons with null.

Constants

Constants can be defined using the final keyword, which means that the variable can be assigned at most once, either in thedeclaration itself, or with a static initializer method if the constant is defined in a package. For example:

package myPkg { final Integer PRIVATE_INT_CONST; private final Integer PRIVATE_INT_CONST2 = 200;

Integer calculate() { return 2 + 7; }

static { PRIVATE_INT_CONST = calculate(); }}

For more information, see The Public, Private, and Final Keywords on page 84.

Expressions

An expression is a construct made up of variables, operators, and method invocations that evaluates to a single value. In ApexCode, an expression is always one of the following types:

• A literal expression. For example:

1 + 1

• A new SObject, list, set, or map. For example:

new Account(<field_initializers>)new Integer[<n>]new Account[]{<elements>}new List<Account>()new Set<String>{}new Map<String, Integer>()

31

Expressions

Page 34: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• Any value that can act as the left-hand of an assignment operator (L-values), including variables, one-dimensional listpositions, and most SObject field references. For example:

Integer imyList[3]myContact.name

• Any SObject field reference that is not an L-value, including:

• The Id of an SObject in a list (see Lists of SObjects on page 27)• A set of child records associated with an SObject (for example, the set of contacts associated with a particular account).

This type of expression yields a query result, much like an inline SOQL query on page 38.

• A SOQL query surrounded by square brackets, allowing for on-the-fly evaluation in Apex Code. For example:

Account[] aa = [select id, name from account where name ='Acme'];Integer i = [select count() from contact where lastname ='Weissman'];

For information, see SOQL Queries on page 38.

• A static method. For example:

System.now()System.assert(true)

Extending SObject and List Expressions

As in Java, SObject and list expressions can be extended with method references and list expressions, respectively, to form newexpressions. For example:

• new Account[]{new Account(name='Acme')}[0].name.length()

• [select id from account][0].name.toLowerCase()

Expression Operators

Expressions can also be joined to one another with operators to create compound expressions. Apex Code supports the followingoperators:

DescriptionSyntaxOperator

Assignment operator (Right associative). Assigns the value of y to the L-valuex. Note that the data type of x must match the data type of y, and cannot benull.

x = y=

Addition assignment operator (Right associative). Adds the value of y to theoriginal value of x and then reassigns the new value to x. See + for additionalinformation. x and y cannot be null.

x += y+=

Multiplication assignment operator (Right associative). Multiplies the valueof y with the original value of x and then reassigns the new value to x. Note

x *= y*=

that x and y must be Integers or Doubles, or a combination. x and y cannotbe null.

Subtraction assignment operator (Right associative). Subtracts the value ofy from the original value of x and then reassigns the new value to x. Note

x -= y-=

32

Expressions

Page 35: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionSyntaxOperator

that x and y must be Integers or Doubles, or a combination. x and y cannotbe null.

Division assignment operator (Right associative). Divides the original valueof x with the value of y and then reassigns the new value to x. Note that xand y must be Integers or Doubles, or a combination.x and y cannot be null.

x /= y/=

OR assignment operator (Right associative). If x, a Boolean, and y, a Boolean,are both false, then x remains false. Otherwise, x is assigned the value of true.

Note:

x |= y|=

• This operator exhibits "short-circuiting" behavior, which means y isevaluated only if x is false.

• x and y cannot be null.

AND assignment operator (Right associative). If x, a Boolean, and y, aBoolean, are both true, then x remains true. Otherwise,x is assigned the valueof false.

Note:

x &= y&=

• This operator exhibits "short-circuiting" behavior, which means y isevaluated only if x is true.

• x and y cannot be null.

Bitwise shift left assignment operator. Shifts each bit in x to the left by ybits so that the high order bits are lost, and the new right bits are set to 0.This value is then reassigned to x.

x <<= y<<=

Bitwise shift right signed assignment operator. Shifts each bit in x to theright by y bits so that the low order bits are lost, and the new left bits are set

x >>= y>>=

to 0 for positive values of y and 1 for negative values of y. This value is thenreassigned to x.

Bitwise shift right unsigned assignment operator. Shifts each bit in x to theright by y bits so that the low order bits are lost, and the new left bits are setto 0 for all values of y. This value is then reassigned to x.

x >>>= y>>>=

Ternary operator (Right associative). This operator acts as a short-hand forif-then-else statements. If x, a Boolean, is true, y is the result. Otherwise zis the result. Note that x cannot be null.

x ? y : z? :

AND logical operator (Left associative). If x, a Boolean, and y, a Boolean,are both true, then the expression evaluates to true. Otherwise the expressionevaluates to false.

Note:

x && y&&

• && has precedence over ||• This operator exhibits "short-circuiting" behavior, which means y is

evaluated only if x is true.• x and y cannot be null.

33

Expressions

Page 36: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionSyntaxOperator

OR logical operator (Left associative). If x, a Boolean, and y, a Boolean, areboth false, then the expression evaluates to false. Otherwise the expressionevaluates to true.

Note:

x || y||

• && has precedence over ||• This operator exhibits "short-circuiting" behavior, which means y is

evaluated only if x is false.• x and y cannot be null.

Equality operator. If the value of x equals the value of y, the expressionevaluates to true. Otherwise, the expression evaluates to false.

Note:

x == y==

• Unlike Java,== in Apex Code compares object value equality, not referenceequality. Consequently:

• String comparison using == is case insensitive• Id comparison using == is case sensitive, and does not distinguish

between 15-character and 18-character formats

• For SObjects and SObject arrays,== performs a deep check of all SObjectfield values before returning its result.

• x or y can be the literal null.• The comparison of any two values can never result in null.• SOQL uses = for its equality operator, and not ==. Although Apex Code

and SOQL are strongly linked, this unfortunate syntax discrepancy existsbecause most modern languages use = for assignment and == for equality.The designers of Apex Code deemed it more valuable to maintain thisparadigm than to force developers to learn a new assignment operator.The result is that Apex Code developers must use == for equality tests inthe main script body, and = for equality in SOQL queries.

Less than operator. If x is less than y, the expression evaluates to true.Otherwise, the expression evaluates to false.

Note:

x < y<

• Unlike other database stored procedures, Apex Code does not supporttri-state Boolean logic, and the comparison of any two values can neverresult in null.

• If x or y equal null and are Integers, Doubles, Dates, or Datetimes, theexpression is false.

• A non-null String or Id value is always greater than a null value.• If x and y are Ids, they must reference the same type of object. Otherwise,

a runtime error results.• If x or y is an Id and the other value is a String, the String value is validated

and treated as an Id.• x and y cannot be Booleans.• The comparison of two strings is performed according to the locale of the

context user.

34

Expressions

Page 37: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionSyntaxOperator

Greater than operator. If x is greater than y, the expression evaluates to true.Otherwise, the expression evaluates to false.

Note:

x > y>

• The comparison of any two values can never result in null.• If x or y equal null and are Integers, Doubles, Dates, or Datetimes, the

expression is false.• A non-null String or Id value is always greater than a null value.• If x and y are Ids, they must reference the same type of object. Otherwise,

a runtime error results.• If x or y is an Id and the other value is a String, the String value is validated

and treated as an Id.• x and y cannot be Booleans.• The comparison of two strings is performed according to the locale of the

context user.

Less than or equal to operator. If x is less than or equal to y, the expressionevaluates to true. Otherwise, the expression evaluates to false.

Note:

x <= y<=

• The comparison of any two values can never result in null.• If x or y equal null and are Integers, Doubles, Dates, or Datetimes, the

expression is false.• A non-null String or Id value is always greater than a null value.• If x and y are Ids, they must reference the same type of object. Otherwise,

a runtime error results.• If x or y is an Id and the other value is a String, the String value is validated

and treated as an Id.• x and y cannot be Booleans.• The comparison of two strings is performed according to the locale of the

context user.

Greater than or equal to operator. If x is greater than or equal to y, theexpression evaluates to true. Otherwise, the expression evaluates to false.

Note:

x >= y>=

• The comparison of any two values can never result in null.• If x or y equal null and are Integers, Doubles, Dates, or Datetimes, the

expression is false.• A non-null String or Id value is always greater than a null value.• If x and y are Ids, they must reference the same type of object. Otherwise,

a runtime error results.• If x or y is an Id and the other value is a String, the String value is validated

and treated as an Id.• x and y cannot be Booleans.• The comparison of two strings is performed according to the locale of the

context user.

35

Expressions

Page 38: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionSyntaxOperator

Inequality operator. If the value of x does not equal the value of y, theexpression evaluates to true. Otherwise, the expression evaluates to false.

Note:

x != y!=

• Unlike Java,!= in Apex Code compares object value equality, not referenceequality.

• For SObjects and SObject arrays,!= performs a deep check of all SObjectfield values before returning its result.

• x or y can be the literal null.• The comparison of any two values can never result in null.

Addition operator. Adds the value of x to the value of y according to thefollowing rules:

x + y+

• If x and y are Integers or Doubles, adds the value of x to the value of y.If a Double is used, the result is a Double.

• If x is a Date and y is an Integer, returns a new Date that is incrementedby the specified number of days.

• If x is a Datetime and y is an Integer or Double, returns a new Date thatis incremented by the specified number of days, with the fractional portioncorresponding to a portion of a day.

• If x is a String and y is a String or any other type of non-null argument,concatenates y to the end of x.

Subtraction operator. Subtracts the value of y from the value of x accordingto the following rules:

x - y-

• If x and y are Integers or Doubles, subtracts the value of x from the valueof y. If a Double is used, the result is a Double.

• If x is a Date and y is an Integer, returns a new Date that is decrementedby the specified number of days.

• If x is a Datetime and y is an Integer or Double, returns a new Date thatis decremented by the specified number of days, with the fractional portioncorresponding to a portion of a day.

Multiplication operator. Multiplies x, an Integer or Double, with y, anotherInteger or Double. Note that if a double is used, the result is a Double.

x * y*

Division operator. Divides x, an Integer or Double, by y, another Integer orDouble. Note that if a double is used, the result is a Double.

x / y/

Logical complement operator. Inverts the value of a Boolean, so that truebecomes false, and false becomes true.

!x!

Unary negation operator. Multiplies the value of x, an Integer or Double, by-1. Note that the positive equivalent + is also syntactically valid, but does nothave a mathematical effect.

-x-

Increment operator. Adds 1 to the value of x, an Integer or Double. If prefixed(++x), the increment occurs before the rest of the statement is executed. Ifpostfixed (x--), the increment occurs after the rest of the statement is executed.

x++

++x

++

36

Expressions

Page 39: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionSyntaxOperator

Decrement operator. Subtracts 1 from the value of x, an Integer or Double.If prefixed (--x), the decrement occurs before the rest of the statement is

x--

--x

--

executed. If postfixed (x--), the decrement occurs after the rest of thestatement is executed.

Bitwise AND operator. ANDs each bit in x with the corresponding bit in yso that the result bit is set to 1 if both of the bits are set to 1.

x & y&

Bitwise OR operator. ORs each bit in x with the corresponding bit in y sothat the result bit is set to 1 if at least one of the bits is set to 1.

x | y|

Bitwise exclusive OR operator. Exclusive ORs each bit in x with thecorresponding bit in y so that the result bit is set to 1 if exactly one of the bitsis set to 1 and the other bit is set to 0.

x ^ y^

Bitwise shift left operator. Shifts each bit in x to the left by y bits so that thehigh order bits are lost, and the new right bits are set to 0.

x << y<<

Bitwise shift right signed operator. Shifts each bit in x to the right by y bitsso that the low order bits are lost, and the new left bits are set to 0 for positivevalues of y and 1 for negative values of y.

x >> y>>

Bitwise shift right unsigned operator. Shifts each bit in x to the right by ybits so that the low order bits are lost, and the new left bits are set to 0 for allvalues of y.

x >>> y<<<

Parentheses. Elevates the precedence of an expression x so that it is evaluatedfirst in a compound expression.

(x)()

Operator Precedence

The Apex Code language uses the following operator precedence rules:

DescriptionOperatorsPrecedence

Grouping and prefix increments and decrements{} () ++ --1

Unary negation! -x +x2

Multiplication and division* /3

Addition and subtraction+ -4

Comparisons: greater-than and less-than< <= > >=5

Comparisons: equal and not-equal== !=6

Logical AND&&7

Logical OR||8

Assignment operators= += -= *= /= &=9

37

Expressions

Page 40: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

SOQL Queries

You can evaluate Sforce Object Query Language (SOQL) statements on-the-fly in Apex Code by surrounding the statementin square brackets. The statements evaluate to a list of SObjects, or to an Integer for count() queries. For example:

List<Account> aa = [select id, name from account where name = 'Acme'];Integer i = [select count() from contact where lastname = 'Weissman'];Integer j = 5 * [select count() from account];

For a full description of SOQL query syntax, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#sforce_api_calls_soql.htm.

SOQL Queries That Return One Record

SOQL queries can also be used to assign a single SObject value when the result list contains only one element. When theL-value of an expression is a singleton SObject type, Apex Code automatically assigns the single SObject record in the queryresult list to the L-value. A runtime exception results if zero SObjects or more than one SObject is found in the list. Forexample:

List<Account> accts = [select id from account];

// These lines of code are only valid if one row is returned from// the query. Notice that the second line dereferences the field from the// query without assigning it to an intermediary SObject variable.Account acct = [select id from account];String name = [select name from account].name;

Working with SOQL Query Results

It is important to note that SOQL queries only return data for SObject fields that are selected in the original query. Any fieldsthat are not selected in the SOQL query (other than Id) are null when dereferenced in Apex Code, even if they contain valuesin the database. For example:

Account a1 = [select id from accountwhere name = 'Acme'];Double amt1 = 2 * a1.annualRevenue;// The code above is incorrect: amt1 is now null, even if // the account contains a value for annualRevenue in the // database

Account a2 = [select id, annualRevenue from account where name = 'Acme'];Double amt2 = 2 * a2.annualRevenue;// The code above is correct: if the account contains a value// for annualRevenue in the database, amt2 will not be null

Even if only one SObject field is selected, a SOQL query always returns a complete record. Consequently, you must dereferencethe field in order to access it. For example, this code retrieves an SObject list from the database with a SOQL query, accessesthe first account record in the list, and then dereferences the record's annualRevenue field:

Double rev = [select annualRevenue from account where name = 'Acme'][0].annualRevenue;

// Note that when only one result is returned, it is not necessary// to include the list's index.Double rev = [select annualRevenue from account where name = 'Acme'].annualRevenue;

38

Expressions

Page 41: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

The only situation in which it is not necessary to dereference an SObject field in the result of an SOQL query, is when thequery returns an Integer as the result of a count() operation.

Integer i = [select count() from account];

Also note that SObject fields that contain formulas return the value of the field at the time the SOQL query was issued. Anychanges to other fields that are used within the formula are not reflected in the formula field value until the record has beensaved and re-queried in Apex Code. Like other read-only SObject fields, the values of the formula fields themselves cannotbe changed in Apex Code.

Very Large SOQL Queries

SOQL queries that return multiple SObjects can only be used if the query results do not exceed 1000 records, the maximumsize limit of a list. If the query results return more than 1000 records, then a SOQL query for loop must be used instead,since it can process multiple batches of records through the use of internal calls to query() and queryMore().

Note: Triggers have an absolute limit of 1000 records for SOQL queries, regardless of whether the query is used ina for loop.

For example, if the results are too large, the syntax below causes a runtime exception:

Account[] accts = [select id from account];

Instead, use a SOQL query for loop as in one of the following examples:

// Use this format if you are not executing DML statements // within the for loopfor (Account a : [select id, name from account where name like 'Acme']) { // Your code without DML statements here}

// Use this format for efficiency if you are executing DML statements // within the for loopfor (List<Account> accts : [select id, name from account where name like 'Acme']) { // Your code here update accts;}

For more information, see SOQL For Loops on page 47.

Foreign Key and Parent-Child Relationship SOQL Queries

The select statement of a SOQL query can be any valid SOQL statement, including foreign key and parent-child recordjoins. If foreign key joins are included, the resulting SObjects can be referenced using normal field notation. For example:

System.debug([select account.name from contact where firstname = 'Caroline'].account.name);

Additionally, parent-child relationships in SObjects act as SOQL queries as well. For example:

for (Account a : [select id, name, (select lastname from contacts) from account where name = 'Acme']) { Contact[] cons = a.contacts;}

39

Expressions

Page 42: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

//The following example also works because we limit to only 1 contactfor (Account a : [select id, name, (select lastname from contacts limit 1) from account where name = 'testAgg']) { Contact c = a.contacts;}

Apex Code Variables in SOQL Queries

SOQL statements in Apex Code can reference Apex Code script variables and expressions if they are preceded by a colon (:).This use of a local script variable within a SOQL statement is called a bind. The Apex Code parser first evaluates the localvariable in script context before executing the SOQL statement. Bind expressions can be used as:

• The filter literals in WHERE clauses• The numeric value in LIMIT clauses• The value of the IN or NOT IN operator in WHERE clauses, allowing filtering on a dynamic set of values. Note that this is

of particular use with a list of Ids or Strings, though it works with lists of any type.

For example:

Account A = new Account(name='xxx');insert A;Account B;

// A simple bindB = [select id from account where id = :A.id];

// A bind with arithmeticB = [select id from account where name = :('x' + 'xx')];

String s = 'XXX';

// A bind with expressionsB = [select id from account where name = :'XXXX'.substring(0,3)];

// A bind with an expression that is itself a query resultB = [select id from account where name = :[select name from account where id = :A.id].name];

Contact C = new Contact(lastName='xxx', accountid=A.id);insert new Contact[]{C, new Contact(lastName='yyy', accountId=A.id)};

// Binds in both the parent and aggregate queriesB = [select id, (select id from contacts where id = :C.id) from account where id = :A.id];

// One contact returnedContact D = B.contacts;

// A limit bindInteger i = 1;B = [select id from account limit :i];

// An IN-bind with an Id list. Note that a list of SObjects// can also be used--the Ids of the objects are used for // the bindContact[] cc = [select id from contact limit 2];Task[] tt = [select id from task where whoId in :cc];

40

Expressions

Page 43: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// An IN-bind with a String listString[] ss = new String[]{'a', 'b'};Account[] aa = [select id from account where accountnumber in :ss];

Comments

Both single-line and multi-line comments are supported in Apex Code scripts:

• To create a single-line comment, use //. All characters on the same line to the right of the // are ignored by the parser.For example:

Integer i = 1; // This comment is ignored by the parser

• To create a multi-line comment, use /* and */ to demarcate the beginning and end of the comment block. For example:

Integer i = 1; /* This comment can wrap over multiple lines without getting interpreted by the parser. */

41

Expressions

Page 44: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 4

Apex Code Flow Control

This chapter discusses the syntax and behavior of statements. A statement is anycoded instruction that performs an action. In Apex Code, statements must endwith a semicolon and can be one of the following types:

In this chapter ...

• Assignment Statements• Conditional (If-Else) Statements

• Assignment• Loops

• Conditional (if-else)• Locking Statements • Loops• Data Manipulation Language

(DML) Statements • Do-while• While• Transaction Control Statements

(Commit and Rollback) • For

• Method Invoking Statements • Locking• Exception Statements • Data Manipulation Language (DML)

• Transaction Control• Method Invoking• Exception Handling

A block is a series of statements that are grouped together with curly braces andcan be used in any place where a single statement would be allowed. For example:

if (true) { System.debug(1); System.debug(2);} else { System.debug(3); System.debug(4);}

In cases where a block consists of only one statement, the curly braces can be leftoff. For example:

if (true) System.debug(1);else System.debug(2);

The remainder of this chapter discusses each type of statement in detail.

42

Page 45: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Assignment Statements

An assignment statement is any statement that places a value into a variable, generally in one of the following two forms:

<LValue> = <new_value_expression>;<LValue> = [<inline_soql_query>];

In the forms above, <LValue> stands for any expression that can be placed on the left side of an assignment operator. Theseinclude:

• A simple variable. For example:

Integer i = 1;Account a = new Account();Account[] accts = [select id from account];

• A de-referenced list element. For example:

ints[0] = 1;accts[0].name = 'Acme';

• An SObject field reference that satisfies the following criteria:

• The context user must have permission to edit the field.• The field must be in the main object and cannot be the object id. For example:

Account a = new Account(name = 'Acme', billingcity = 'San Francisco');

// Ids cannot be set manually// a.id = "00300000003T2PGAA0"; This code is invalid!

// Instead, insert the record. The system automatically assigns it an Id.insert a;

// Fields also must be writeable for the context user// a.createdDate = System.today(); This code is invalid because// createdDate is read-only!

// Since the account a has been inserted, it is now possible to// create a new contact that's related to itContact c = new Contact(lastname = 'Roth', accountId = a.Id);

// Notice that you can write to the account name directly through the contact c.account.name = 'salesforce.com';

Assignment is always done by reference. For example:

Account a = new Account();Account b;Account[] c = new Account[]{};a.name = 'Acme';b = a; c.add(a);

// These asserts should now be true. You can reference the data// originally allocated to account a through account b and account list c.System.assertEquals(b.name, 'Acme'); System.assertEquals(c[0].name, 'Acme');

43

Assignment Statements

Page 46: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Similarly, two lists can point at the same value in memory. For example:

Account[] a = new Account[]{new Account()};Account[] b = a;a[0].name = 'Acme';System.assert(b[0].name = 'Acme');

In addition to =, other valid assignment operators include +=, *=, /=, |=, &=, ++, and --. See Expression Operators on page32 for more information.

Conditional (If-Else) Statements

The conditional statement in Apex Code works similarly to Java:

if (<Boolean_condition>) // Statement 1else // Statement 2

The else portion is always optional, and always groups with the closest if. For example:

Integer x, sign;// Your codeif (x <= 0) if (x == 0) sign = 0; else sign = -1;

is equivalent to:

Integer x, sign;// Your codeif (x <= 0) {

if (x == 0) { sign = 0; } else { sign = -1; }}

Repeated else if statements are also allowed. For example:

if (place = 1) { medal_color = 'gold';} else if (place = 2) { medal_color = 'silver';} else if (place = 3) { medal_color = 'bronze';} else { medal_color = null;}

Note: Apex Code does not support the keyword elsif.

Loops

Apex Code supports the following five types of procedural loops:

44

Conditional (If-Else) Statements

Page 47: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• do {<statement>} while (<Boolean_condition>);

• while (<Boolean_condition>) <statement>;

• for (<initialization>; <Boolean_exit_condition>; <increment>) <statement>;

• for (<variable> : <array_or_set>) <statement>;

• for (<variable> : [inline_soql_query]) <statement>;

All loops allow for loop control structures:

• break; exits the entire loop• continue; skips to the next iteration of the loop

Note: To prevent infinite loops or highly inefficient iterative database calls, the Apex Code script execution frameworkthrows a runtime exception if too many script statements are executed without any Data Management Language(DML) statements. See Execution Governors and Limits on page 100 for details.

Do-While Loops

The Apex Code do-while loop repeatedly executes a block of code as long as a particular Boolean condition remains true.Its syntax is:

do { <code_block>} while (condition);

Note: Curly braces ({}) are always required around a <code_block>.

As in Java, the Apex Code do-while loop does not check the Boolean condition statement until after the first loop is executed.Consequently, the code block always runs at least once.

As an example, the following code outputs the numbers 1 - 10 into the debug log:

Integer count = 1;

do { System.debug(count); count++;} while (count < 11);

While Loops

The Apex Code while loop repeatedly executes a block of code as long as a particular Boolean condition remains true. Itssyntax is:

while (condition) { <code_block>}

Note: Curly braces ({}) are required around a <code_block> only if the block contains more than one statement.

Unlike do-while, the while loop checks the Boolean condition statement before the first loop is executed. Consequently,it is possible for the code block to never execute.

45

Loops

Page 48: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

As an example, the following code outputs the numbers 1 - 10 into the debug log:

Integer count = 1;

while (count < 11) { System.debug(count); count++;}

For Loops

Apex Code supports three variations of the for loop:

• The traditional for loop:

for (init_stmt; exit_condition; increment_stmt) { <code_block>}

• The list or set iteration for loop:

for (<variable> : <list_or_set>) { <code_block>}

where <variable> must be of the same primitive or SObject type as <list_or_set>.

• The SOQL for loop:

for (<variable> : [soql_query]) { <code_block>}

or

for (<variable_list> : [soql_query]) { <code_block>}

Both <variable> and <variable_list> must be of the same SObject type as is returned by the <soql_query>.

Note: Curly braces ({}) are required around a <code_block> only if the block contains more than one statement.

Each is discussed further in the sections that follow.

Traditional For Loops

The traditional for loop corresponds to the traditional syntax used in Java and other languages. Its syntax is:

for (init_stmt; exit_condition; increment_stmt) { <code_block>}

When executing this type of for loop, the Apex Code runtime engine performs the following steps, in order:

46

Loops

Page 49: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

1. Execute the init_stmt component of the loop. Note that multiple variables can be declared and/or initialized in thisstatement.

2. Perform the exit_condition check. If true, the loop exits. If false, the loop continues.3. Execute the <code_block>.4. Execute the increment_stmt statement.5. Return to Step 2.

As an example, the following code outputs the numbers 1 - 10 into the debug log. Note that an additional initialization variable,j, is included to demonstrate the syntax:

for (Integer i = 0, j = 0; i < 10; i++) { System.debug(i+1);}

List or Set Iteration For Loops

The list or set iteration for loop iterates over all the elements in a list or set. Its syntax is:

for (<variable> : <list_or_set>) { <code_block>}

where <variable> must be of the same primitive or SObject type as <list_or_set>.

When executing this type of for loop, the Apex Code runtime engine assigns <variable> to each element in <list_or_set>,and runs the <code_block> for each value.

For example, the following code outputs the numbers 1 - 10 to the debug log:

Integer[] myInts = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

for (Integer i : myInts) { System.debug(i);}

SOQL For Loops

SOQL for loops iterate over all of the SObject records returned by a SOQL query. The syntax of a SOQL for loop is either:

for (<variable> : [soql_query]) { <code_block>}

or

for (<variable_list> : [soql_query]) { <code_block>}

Both <variable> and <variable_list> must be of the same type as the SObjects that are returned by the <soql_query>.As in standard SOQL queries, the [soql_query] statement can refer to script expressions in their WHERE clauses using the:<expression> syntax. For example:

String s = 'Acme';for (Account a : [select id, name from account where name like :(s+'%')]) {

47

Loops

Page 50: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// Your code}

SOQL For Loops Versus Standard SOQL Queries

SOQL for loops differ from a standard SOQL statements because of the method they use to retrieve SObjects. While thestandard queries discussed in SOQL Queries on page 38 can retrieve either the count() of a query or a number of objectrecords limited by the maximum size of a list (1000), SOQL for loops retrieve all SObjects, using efficient chunking withcalls to the query() and queryMore() methods of the Apex Web Services API. Consequently, developers must always usea SOQL for loop to process query results that return more than 1000 records.

SOQL For Loop Formats

SOQL for loops can process records one at a time using a single SObject variable, or in batches of 200 SObjects at a timeusing an SObject list:

• The single SObject format executes the for loop's <code_block> once per SObject record. Consequently, it is easy tounderstand and use, but is grossly inefficient if you want to use data manipulation language (DML) statements within thefor loop body. Each DML statement ends up processing only one SObject at a time.

• The SObject list format executes the for loop's <code_block> once per list of 200 SObjects. Consequently, it is a littlemore difficult to understand and use, but is the optimal choice if you need to use DML statements within the for loopbody. Each DML statement can bulk process a list of SObjects at a time.

For example, the following code illustrates the difference between the two types of SOQL query for loops:

insert new account[]{new account(name = 'yyy'), new account(name = 'yyy'), new account(name = 'yyy')};

// The single SObject format executes the for loop once per returned recordInteger I = 0;for (account tmp : [select id from account where name = 'yyy']) { i++;}System.assert(i == 3); // Since there were three accounts named 'yyy' in the // database, the loop executed three times

// The SObject list format executes the for loop once per returned batch// of recordsi = 0;Integer j;for (account[] tmp : [select id from account where name = 'yyy']) { j = tmp.size(); i++;}System.assert(j == 3); // The list should have contained the three accounts // named 'yyy'System.assert(i == 1); // Since a single batch can hold up to 100 records and, // only three records should have been returned, the // loop should have executed only oncerollback;

Note:

• The break and continue keywords can be used in both types of inline query for loop formats. When using theSObject list format, continue skips to the next list of SObjects.

• DML statements can only process up to 200 records at a time, and SObject list for loops process records in batchesof 200. Consequently, if you are inserting, updating, or deleting more than one record per returned record in anSObject list for loop, it is possible to encounter runtime limit errors. See Execution Governors and Limits onpage 100.

48

Loops

Page 51: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Locking Statements

Apex Code allows developers to lock SObject records while they are being updated in order to prevent race conditions andother thread safety problems. While an SObject record is locked, no other program or user is allowed to make updates.

To lock a set of SObject records in Apex Code, embed the keywords FOR UPDATE after any inline SOQL statement. Forexample, the following statement, in addition to querying for two accounts, also locks the accounts that are returned:

Account [] accts = [select id from Account limit 2 for update];

Note: You cannot use the ORDER BY keywords in any SOQL query that uses locking. However, query results areautomatically ordered by ID.

While the accounts are locked, data manipulation language (DML) statements can modify their field values in the database.The locks are released once a commit or rollback transaction control statement executes.

Caution: Use care when setting locks in your Apex Code. See Avoiding Deadlocks, below.

Locking in a SOQL For Loop

The FOR UPDATE keywords can also be used within SOQL for loops. For example:

for (Account[] accts : [select id from Account for update]) { // Your code commit;}

As discussed in SOQL For Loops on page 47, the example above corresponds internally to calls to the query() andqueryMore() methods in the Apex Web Services API. Note that the initial query that gathers all SObjects does not lockthe SObjects all at once. Instead, each list of SObjects is locked as it is sent for processing, before the body of the for loopexecutes for the list. This occurs with SOQL for loops that return single SObjects as well.

Avoiding Deadlocks

Note that Apex Code has the possibility of deadlocks, as does any other procedural logic language involving updates to multipledatabase tables or rows. To avoid such deadlocks, the Apex Code runtime engine:

1. First locks SObject parent records, then children2. Locks SObject records in order of Id when multiple records of the same type are being edited

As a developer, use care when locking rows to ensure that you are not introducing deadlocks. Verify that you are using standarddeadlock avoidance techniques by accessing tables and rows in the same order from all locations in an application.

Data Manipulation Language (DML) Statements

Data manipulation language (DML) statements allow users to retrieve, insert, delete, and update data in a database. ApexCode DML statements perform the same logic as the Apex Web Services API bulk DML calls. They include:

• insert <SObject>

insert <SObject[]>

49

Locking Statements

Page 52: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• update <SObject>

update <SObject[]>

• upsert <SObject> <opt_external_id>

upsert <SObject[]> <opt_external_id>

• delete <SObject>

delete <SObject[]>

• merge <SObject> <SObject>

merge <SObject> <SObject[]>

merge <SObject> <Id>

merge <SObject> <Id[]>

Because Apex Code DML statements perform the same logic as the Web Services API, API fault codes can be thrown forerrors such as missing required fields or field integrity exceptions. See Bulk DML Exception Handling on page 56 for additionalinformation.

Insert Statements

The insert statement adds one or more SObjects, such as individual accounts or contacts, to your organization’s data.insertis analogous to the INSERT statement in SQL.

Syntaxinsert <SObject>

insert <SObject[]>

Rules and Guidelines

When inserting SObject records, consider the following rules and guidelines:

• Certain SObjects cannot be created. To create an SObject record, the createable property of the SObject must be setto true.

• You must supply a non-null value for all required fields.• You can pass a maximum of 200 SObject records to a single insert method.• The insert statement automatically sets the Id value of all new SObject records. Inserting a record that already has an

Id—and therefore already exists in your organization's data—produces an error. See Lists of SObjects on page 27 forinformation.

• The insert statement can only set the foreign key Id of related SObject records. Fields on related records cannot beupdated with insert. For example, if inserting a new contact, you can specify the contact's related account record bysetting the value of the AccountId field. However, you cannot change the account's name without updating the accountitself with a separate DML call.

• Insert is not supported with some SObjects. See SObjects That Do Not Support DML Statements. on page 55

Example

The following example inserts an account named 'Acme':

Account[] newAcct = new Account(name = 'Acme');try { insert newAcct;} catch (System.DmlException e) { // Process exception here

50

Data Manipulation Language (DML) Statements

Page 53: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

}commit;

Note: For more information on processing DmlExceptions, see Bulk DML Exception Handling on page 56.

Update Statements

The update statement modifies one or more existing SObject records, such as individual accounts or contacts, in yourorganization’s data. update is analogous to the UPDATE statement in SQL.

Syntaxupdate <SObject>

update <SObject[]>

Rules and Guidelines

When updating SObject records, consider the following rules and guidelines:

• Certain SObjects cannot be updated. To update an SObject record, the updateable property of the SObject must be setto true.

• When updating required fields you must supply a non-null value.• Unlike the Apex Web Services API, Apex Code allows you to change field values to null without updating the

fieldsToNull array on the SObject record. The API requires an update to this array due to the inconsistent handlingof null values by many SOAP providers. Because Apex Code runs solely on the Apex platform, this workaround isunnecessary.

• The Id of an updated SObject record cannot be modified, but related record Ids can.• The update statement automatically modifies the values of certain fields such as LastModifiedDate,LastModifiedById,

and SystemModstamp. You cannot explicitly specify these values in your Apex Code.• You can pass a maximum of 200 SObject records to a single update method.• A single update statement can only modify one type of SObject at a time. For example, if updating an account field

through an existing contact that has also been modified, two update statements are required:

// Use a SOQL query to access data for a contactContact c = [select account.name from contact where lastName = 'Carter' limit 1];

// Now we can change fields for both the contact and its// associated accountc.account.name = 'salesforce.com';c.lastName = 'Roth';

// To update the database, the two types of records must be // updated separatelyupdate c; // This only changes the contact's last nameupdate c.account; // This updates the account name

• Update is not supported with some SObjects. See SObjects That Do Not Support DML Statements. on page 55

51

Data Manipulation Language (DML) Statements

Page 54: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Example

The following example updates the billingcity field on a single account named 'Acme':

Account myAcct = [select id, name, billingcity from account where name = 'Acme'];myAcct.billingcity = 'San Francisco'; try { update myAcct;} catch (System.DmlException e) { // Process exception here}commit;

Note: For more information on processing DmlExceptions, see Bulk DML Exception Handling on page 56.

Upsert Statements

The upsert statement creates new SObject records and updates existing SObject records within a single statement, using anoptional custom field to determine the presence of existing objects.

Syntaxupsert <SObject> <opt_external_id>

upsert <SObject[]> <opt_external_id>

<opt_external_id> is an optional variable that specifies the custom field that should be used to match records that alreadyexist in your organization's data. This custom field must be created with the External Id attribute selected. Additionally,if the field does not have the Unique attribute selected, the context user must have the "View All Data" permission so thatupsert does not accidentally insert a duplicate record.

If <opt_external_id> is not specified, the SObject record's Id field is used by default.

Note: Custom field matching is case-insensitive only if the custom field has the Unique and Treat "ABC" and "abc"as duplicate values (case insensitive) attributes selected. If this is the case, “ABC123” is matched with “abc123.”

How Upsert Chooses to Insert or Update

Upsert uses the SObject record's primary key (or the external ID, if specified) to determine whether it should create a newobject record or update an existing one:

• If the key is not matched, then a new object record is created.• If the key is matched once, then the existing object record is updated.• If the key is matched multiple times, then an error is generated and the object record is neither inserted or updated.

Rules and Guidelines

When upserting SObject records, consider the following rules and guidelines:

• Certain SObjects cannot be inserted or updated. To insert an SObject record, the createable property of the SObjectmust be set to true. To update an SObject record, the updateable property of the SObject must be set to true.

• You must supply a non-null value for all required fields on any record that will be inserted.• The Id of an SObject record cannot be modified, but related record Ids can. This action is interpreted as an update.• The upsert statement automatically modifies the values of certain fields such as LastModifiedDate,LastModifiedById,

and SystemModstamp. You cannot explicitly specify these values in your Apex Code.

52

Data Manipulation Language (DML) Statements

Page 55: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• You can pass a maximum of 200 SObject records to a single upsert method.• The upsert statement can only set the Id of related SObject records. Fields on related records cannot be modified with

upsert. For example, if updating an existing contact, you can specify the contact's related account record by setting thevalue of the AccountId field. However, you cannot change the account's name without updating the account itself witha separate DML statement.

• Upsert is not supported with some SObjects. See SObjects That Do Not Support DML Statements. on page 55• You can use foreign keys to upsert SObject records if they have been set as reference fields. For more information, see

http://www.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm

Examples

The following example updates the city name for all existing accounts located in the city formerly known as Bombay, and alsoinserts a new account located in San Francisco:

Account[] acctsList = [select id, name, billingcity from account where billingcity = 'Bombay'];for (Account a : acctsList) { a.billingcity = 'Mumbai';}Account newAcct = new Account(name = 'Acme' billingcity = 'San Francisco');acctsList.add(newAcct);try { upsert acctsList;} catch (System.DmlException e) { // Process exception here}commit;

Note: For more information on processing DmlExceptions, see Bulk DML Exception Handling on page 56.

This next example uses upsert and an external Id field Line_Item_Id__c on the Asset object to maintain a one-to-onerelationship between an asset and an opportunity line item. Use of upsert with an external ID can reduce the number ofDML statements in your code, and help you to avoid hitting governor limits (see Execution Governors and Limits on page100).

Note: This example requires the addition of a custom text field on the Asset object named Line_Item_Id__c. Thisfield must be flagged as an external Id. For information on custom fields, see the Apex platform online help.

public void upsertExample() { Opportunity opp = [Select Id, Name, AccountId, (Select Id, PricebookEntry.Product2Id, PricebookEntry.Name From OpportunityLineItems) From Opportunity Where HasOpportunityLineItem = true Limit 1];

Asset[] assets = new Asset[]{};

// Create an asset for each line item on the opportunity for (OpportunityLineItem lineItem:opp.OpportunityLineItems) {

//This code populates the line item Id, AccountId, and Product2Id for each asset Asset asset = new Asset(Name = lineItem.PricebookEntry.Name, Line_Item_ID__c = lineItem.Id, AccountId = opp.AccountId, Product2Id = lineItem.PricebookEntry.Product2Id);

53

Data Manipulation Language (DML) Statements

Page 56: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

assets.add(asset); }

try { upsert assets Line_Item_ID__c; // This line upserts the assets list with // the Line_Item_Id__c field specified as the // Asset field that should be used for matching // the record that should be upserted. commit; } catch (System.DmlException e) { System.debug(e.getMessage()); }}

Delete Statements

The delete statement deletes one or more existing SObject records, such as individual accounts or contacts, from yourorganization’s data. delete is analogous to the DELETE statement in SQL.

Syntaxdelete <SObject>

delete <SObject[]>

Rules and Guidelines

When deleting SObject records, consider the following rules and guidelines:

• To ensure referential integrity, delete supports cascading deletions. If you delete a parent object, you delete its childrenautomatically, as long as each child record can be deleted.

For example, if you delete a case record, Apex Code automatically deletes any CaseComment, CaseHistory, and CaseSolutionrecords associated with that case. However, if a particular child record is not deletable or is currently being used, then thedelete operation on the parent case record fails.

• Certain SObjects cannot be deleted. To delete an SObject record, the deletable property of the SObject must be set totrue.

• You can pass a maximum of 200 SObject records to a single delete method.• Delete is not supported with some SObjects. See SObjects That Do Not Support DML Statements. on page 55

Example

The following example deletes an account named 'Acme':

Account doomedAccts = [select id, name from account where name = 'Enron']; try { delete doomedAccts;} catch (System.DmlException e) { // Process exception here}commit;

Note: For more information on processing DmlExceptions, see Bulk DML Exception Handling on page 56.

54

Data Manipulation Language (DML) Statements

Page 57: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Merge Statements

The merge statement merges up to three records of the same SObject type into one of the records, deleting the others, andre-parenting any related records.

Syntaxmerge <SObject> <SObject>

merge <SObject> <SObject[]>

merge <SObject> <Id>

merge <SObject> <Id[]>

The first parameter represents the master record into which the other records are to be merged.The second parameter representsthe one or two other records that should be merged and then deleted. You can pass these other records into the merge statementas a single SObject record or Id, or as a list of two SObject records or Ids.

Rules and Guidelines

When merging SObject records, consider the following rules and guidelines:

• Only Leads, Contacts, and Accounts can be merged.• You can pass a master record and up to two additional SObject records to a single merge method.• Merge is not supported with some SObjects. See SObjects That Do Not Support DML Statements. on page 55

Example

The following example merges two accounts named 'Acme Inc.' and 'Acme' into a single record:

Account masterAcct = [select id, name from account where name = 'Acme Inc.'];Account mergeAcct = [select id, name from account where name = 'Acme'];try { merge masterAcct mergeAcct;} catch (System.DmlException e) { // Process exception here}commit;

Note: For more information on processing DmlExceptions, see Bulk DML Exception Handling on page 56.

SObjects That Do Not Support DML Statements

DML statements are not supported with the following SObjects in Apex Code:

• User• Profile• Territory• RecordType• Translation• WebLink• BusinessHours• BusinessProcess

55

Data Manipulation Language (DML) Statements

Page 58: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• CategoryNode• Process*

Note: You can manipulate these SObjects in the Apex Web Services API.

Bulk DML Exception Handling

Exceptions that arise from a bulk DML call (including any recursive DML operations in triggers that are fired as a directresult of the call) are handled differently depending on where the original call originated:

• When errors occur because of a bulk DML call that originates directly from Apex Code, the runtime engine follows the"all or nothing" rule: during a single operation, all records must be updated successfully or the entire operation rolls backto the point immediately preceding the DML statement.

• When errors occur because of a bulk DML call that originates from the Apex Web Services API, the runtime engineattempts at least a partial save:

1. During the first attempt, the runtime engine processes all records. Any record that generates an error due to issues suchas validation rules or unique index violations is set aside.

2. If there were errors during the first attempt, the runtime engine makes a second attempt which includes only thoserecords that did not generate errors. All records that didn't generate an error during the first attempt are processed,and if any record generates an error (perhaps because of race conditions) it is also set aside.

3. If there were additional errors during the second attempt, the runtime engine makes a third and final attempt whichincludes only those records that did not generate errors during the first and second attempts. If any record generatesan error, the entire operation fails with the error message, "Too many batch retries in the presence of Apex triggersand partial failures."

Note: During the second and third attempts, governor limits are reset to their original state before the first attempt.See Execution Governors and Limits on page 100.

Transaction Control Statements (Commit and Rollback)

The results of all DML statements remain pending until a transaction control statement is issued:

• commit; saves the changes that have been made and updates the database.• rollback; reverts all changes and makes no updates to the database.

If any DML statements remain pending when a top-level script, such as an anonymous block or a stored method invocation,completes, the Apex Code runtime engine generates an exception.

Triggers cannot execute transaction control statements.

Method Invoking Statements

Void methods that have side effects are typically executed as stand-alone procedure statements in Apex Code scripts. Forexample:

System.debug('Here's a note for the log.');

As in Java, methods that return values can also be run as a statement if their results are not assigned to another variable.

56

Transaction Control Statements (Commit and Rollback)

Page 59: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Exception Statements

Apex Code uses exceptions to note errors and other events that disrupt the normal flow of script execution. throw statementscan be used to generate exceptions, while try, catch, and finally can be used to gracefully recover from an exception.

Throw Statements

A throw statement allows you to signal that an error has occurred. To throw an exception, use the throw statement andprovide it with an exception object to provide information about the specific error. For example:

throw <exceptionObject>;

Try-Catch-Finally Statements

The try, catch, and finally statements can be used to gracefully recover from a thrown exception:

• The try statement identifies a block of code in which an exception can occur• The catch statement identifies a block of code that can handle a particular type of exception. A singletry statement can

have multiple associated catch statements.• The finally statement optionally identifies a block of code that is guaranteed to execute and allows you to clean up after

the code enclosed in the try block. A single try statement can have only one associated finally statement.

Syntax

The syntax of these statements is as follows:

try {

<code_block>

} catch (<exceptionType>) {

<code_block>

}

// Optional catch statements for other exception types.

// Note that the general exception type, 'Exception',

// must be the last catch block when it is used.

} catch (Exception e) {

<code_block>

}

// Optional finally statement

} finally {

<code_block>

}

57

Exception Statements

Page 60: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Example

For example:

try { // Your code here} catch (System.ArrayException e) { // ArrayException handling code here} catch (Exception e) { // Generic exception handling code here}

Note: Limit exceptions caused by an execution governor cannot be caught. See Execution Governors and Limits onpage 100 for information.

Exception Types

Exceptions can be of the standard Exception type, or they can be more specific system- or user-defined types.

System-Defined Exception Types

System-defined exception types cannot be explicitly thrown, and are outlined in the following table.

DescriptionException

Any issue with a list, such as attempting to access an index that is out of boundsArrayException

Any issue with a DML statement, such as an insert statement missing a required field ona record

DmlException

Any issue with a mathematical operation, such as dividing by zeroMathException

Any issue with dereferencing null, such as in the following code:String s;s.toLowerCase(); // Since s is null, this call causes // a NullPointerException

NullPointerException

Any issue with SOQL queries, such as assigning a query that returns no records or more thanone record to a singleton SObject variable

QueryException

Any issue with Strings, such as a String that is longer than 32,000 charactersStringException

Any issue with type conversions, such as attempting to convert the String 'a' to an Integerusing the valueOf() method

TypeException

Note: System-defined exception types must be qualified with the System prefix. For example,

try { // Your code here} catch (System.ArrayException e) { // Your code here}

58

Exception Statements

Page 61: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

User-Defined Exception Types

Script developers can also define their own custom exception types in Apex Code. These exceptions behave as any otherstandard exception type, and can be thrown and caught as expected. For example, the following code defines an exceptiontype within an anonymous block:

// Note that the exception definition syntax is modeled after // class definition in Javapublic class MyException extends Exception {}

try { Integer i; // Your code here if (i < 5) throw new MyException();} catch (MyException e) { // Your MyException handling code here}

Exception type names must end with the string Exception.

Note: You can also define exception types within packages. Such exceptions can be referenced outside the homepackage using dot notation.

Like Java classes, user-defined exception types can form an inheritance tree, and catch blocks can catch any portion. Forexample:

public class BaseException extends Exception {}public class OtherException extends BaseException {}

try { Integer i; // Your code here if (i < 5) throw new OtherException('This is bad');} catch (BaseException e) { // This catches the OtherException}

Constructing an Exception

You can construct exceptions:

• With no arguments:

new MyException();

• With a single String argument that specifies the error message:

new MyException('This is bad');

• With a single Exception argument that specifies the cause and that displays in any stack trace:

new MyException(e);

• With both a String error message and a chained exception cause that displays in any stack trace:

new MyException('This is bad', e);

59

Exception Statements

Page 62: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

For example the following code generates a stack trace with information about both My1Exception and My2Exception:

public class My1Exception extends Exception {} public class My2Exception extends Exception {} try { throw new My1Exception(); } catch (My1Exception e) { throw new My2Exception('This is bad', e);}

Exception Variables

As in Java, variables, arguments, and return types can be declared of type Exception. For example:

Exception e1;try { String s = null; s.tolowercase(); // This will generate a null pointer exception...} catch (System.NullPointerException e) { e1 = e; // ...which can be assigned to a variable, or passed // into or out of another method}

Note: Exception variables cannot be used in lists, sets, or maps.

Exception Methods

All exceptions support built-in methods for returning the error message and exception type. In addition, bulk DML exceptionssupport a set of built-in methods that return:

• The number of failed rows from the last DML operation (e.getNumDml())• The original row number of the ith DML exception (e.getDmlIndex(int))• The Apex API fault code of the ith DML exception (e.getDmlStatusCode(int))• The textual message of the ith DML exception (e.getDmlMessage(int))

For example:

Account[] accts = new Account[]{new Account(billingcity = 'San Jose’)};try { insert accts;} catch (System.DmlException e) { for (Integer i = 0; i < e.getNumDml(); i++) { // Process exception here System.debug(e.getDmlMessage(i)); }}

For more information, see Exception Methods on page 80.

60

Exception Statements

Page 63: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 5

Apex Code Methods

Apex Code includes both built-in system static methods, and built-in methodsfor expressions of particular data types.

In this chapter ...

• System Static MethodsSystem static methods are invoked with no object context and, like Java, arealways of the form:

Class.method(args)

• Limits Methods• List Methods• Set Methods• Map Methods

All other methods occur on expressions of a particular data type, such as a list,set, or string. For example:

String s = 'Hello, world';

Integer i = s.length();

• Double Methods• SObject Methods• String Methods• Date Methods• Datetime Methods• Exception Methods

Note: If a method is called with an object expression that evaluates tonull, the Apex Code runtime engine throws a null pointer exception.• User-Defined Methods

The following sections summarize available methods by object type. The finalsection of this chapter discusses user-defined methods.

61

Page 64: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

System Static Methods

System static methods are stand-alone methods that do not have an implicit parameter. For example, the expression:

Math.round(1.75);

rounds the value of 1.75 to the nearest Integer without using any other values.

The table below describes all system static methods that are defined in Apex Code.

Note: In the table below <AnyDataType> represents any primitive, object record, array, map, set, or the special valuenull.

Table 11: System Static Methods

DescriptionReturnType

ArgumentsNamePackage

Returns the current date and timeDatetimenowSystem

Returns the current dateDatetoday

Asserts that condition is true. If it is not, aruntime exception is thrown with the optionalsecond argument, opt_msg as part of its message.

VoidBoolean condition,

<AnyDataType>opt_msg

assert

Asserts that the first two arguments, x and y arethe same. If they are not, a runtime exception is

Void<AnyDataType> x,

<AnyDataType> y,

assertEquals

thrown with the optional third argument,opt_msg as part of its message.<AnyDataType>

opt_msg

Asserts that the first two arguments, x and y aredifferent. If they are the same, a runtime

Void<AnyDataType> x,

<AnyDataType> y,

assertNotEquals

exception is thrown with the optional thirdargument, opt_msg as part of its message.<AnyDataType>

opt_msg

Writes the argument msg, in string format, to theexecution debug log.

Note that when a map or set is printed, the outputis sorted in key order and is surrounded with

Void<AnyDataType> msgdebug

square brackets ([]). When an array or list isprinted, the output is enclosed in parentheses(()).

Returns the context user's IdStringgetUserIdUserInfo

Returns the context user's first nameStringgetFirstName

Returns the context user's last nameStringgetLastName

Returns the context user's role IdStringgetUserRoleId

Returns the context user's default currency codeif their organization uses multiple currencies

StringgetDefaultCurrency

62

System Static Methods

Page 65: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturnType

ArgumentsNamePackage

Returns the context user's localeStringgetLocale

Returns the context user's languageStringgetLanguage

Returns the context organization's IdStringgetOrganizationId

Returns the context organization's company nameStringgetOrganizationName

Specifies whether the organization uses multiplecurrencies

BooleanisMultiCurrency

Creates a Currency literal that can be used withina SOQL query's WHERE clause. Note that this is

CurrencyDouble value,

String currency_code

newInstanceCurrency

the only place that such a type is created or usedin Apex Code.

Casts x, a history tracking table field of typeanyType, to an Integer. For more information on

IntegeranyType x*valueOfInteger

the anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

Returns an Integer that contains the value of thespecified String. As in Java, the String is

IntegerString svalueOf

interpreted as representing a signed decimalinteger.

Casts x, a history tracking table field of typeanyType, to a Double. For more information on

DoubleanyType x*valueOfDouble

the anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

Returns a Double that contains the value of thespecified String. As in Java, the String isinterpreted as representing a signed decimal.

DoubleString svalueOf

Casts x, a history tracking table field of typeanyType, to a Boolean. For more information on

BooleananyTypex*valueOfBoolean

the anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

Returns a String that represents the specifiedInteger

StringInteger ivalueOfString

Returns a String that represents the specifiedDouble

StringDouble dvalueOf

Casts x, a history tracking table field of typeanyType, to a String. For more information on

StringanyType x*valueOf

the anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

63

System Static Methods

Page 66: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturnType

ArgumentsNamePackage

Returns a String that represents the specified Datein the standard "yyyy-MM-dd HH:mm:ss"format

StringDate dvalueOf

Returns a String that represents the specifiedDatetime in the standard "yyyy-MM-ddHH:mm:ss" format for the local time zone

StringDatetime dtvalueOf

Returns a String that represents the specifiedDatetime in the standard "yyyy-MM-ddHH:mm:ss" format for the GMT time zone

StringDatetime dtvalueOfGmt

Returns a Datetime that contains the value of thespecified String. The String should use the

DatetimeString svalueOfDatetime

standard date format "yyyy-MM-dd HH:mm:ss"in the local time zone

Returns a Datetime that contains the value of thespecified String. The String should use the

DatetimeString svalueOfGmt

standard date format "yyyy-MM-dd HH:mm:ss"in the GMT time zone

Casts x, a history tracking table field of typeanyType, to a Datetime. For more information

DatetimeanyType x*valueOf

on the anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

Constructs a Datetime from Integerrepresentations of the year, month (1=Jan), day,

DatetimeInteger year,

Integer month,

newInstance

hour, minute, and second in the local timezoneInteger date,

Integer hour,

Integer minute,

Integer second

Constructs a Datetime from Integerrepresentations of the year, month (1=Jan), day,

DatetimeInteger year,

Integer month,

newInstanceGmt

hour, minute, and second in the GMT timezoneInteger date,

Integer hour,

Integer minute,

Integer second

Constructs a Datetime from Integerrepresentations of the year, month (1=Jan), andday at midnight in the local time zone

DatetimeInteger year,

Integer month,

Integer date

newInstance

64

System Static Methods

Page 67: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturnType

ArgumentsNamePackage

Constructs a Datetime from Integerrepresentations of the year, month (1=Jan), andday at midnight in the GMT time zone

DatetimeInteger year,

Integer month,

Integer date

newInstanceGmt

Constructs a Datetime from a history trackingtable field x. For more information on the

DatetimeanyType x*newInstanceGmt

anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

Returns a Date that contains the value of thespecified String. The String should use the

DateString svalueOfDate

standard date format "yyyy-MM-dd HH:mm:ss"in the local time zone.

Casts x, a history tracking table field of typeanyType, to a Date. For more information on the

DateanyType x*valueOf

anyType data type, seewww.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm.

Constructs a Date from Integer representationsof the year, month (1=Jan), and day

DateInteger year,

Integer month,

newInstance

Integer date

Returns the number of days in the month for thespecified year and month (1=Jan)

IntegerInteger year,

Integer month

daysInMonth

Returns true if the specified year is a leap yearBooleanInteger yearisLeapYear

Returns the closest Integer to the specifiedDouble by adding 1/2, taking the floor of the

IntegerDouble droundMath

result, and casting the result to type Integer. Ifthe result is less than -2,147,483,648 or greaterthan 2,147,483,647, Apex Code generates anerror.

Returns the largest (closest to positive infinity)Double that is not greater than the argument andis equal to a mathematical integer

DoubleDouble dfloor

Returns the smallest (closest to negative infinity)Double that is not less than the argument and isequal to a mathematical integer

DoubleDouble dceil

Returns the absolute value of the specified IntegerIntegerInteger iabs

Returns the absolute value of the specified DoubleDoubleDouble dabs

Returns the value of the first Double raised to thepower of exp

DoubleDouble d,

Double exp

pow

65

System Static Methods

Page 68: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturnType

ArgumentsNamePackage

Returns the natural logarithm (base e) of thespecified Double

DoubleDouble dlog

Returns the logarithm (base 10) of the specifiedDouble

DoubleDouble dlog10

Returns Euler's number e raised to the power ofthe specified Double

DoubleDouble dexp

Returns the smaller of the two specified DoublesDoubleDouble d1,

Double d2

min

Returns the smaller of the two specified IntegersIntegerInteger i1,

Integer i2

min

Returns the larger of the two specified DoublesDoubleDouble d1,

Double d2

max

Returns the larger of the two specified IntegersIntegerInteger i1,

Integer i2

max

Returns a positive Double that is greater than orequal to 0.0 and less than 1.0

Doublerandom

Returns the remainder of i1 divided by i2IntegerInteger i1,

Integer i2

mod

* The anyType data type is a particular type used only in EntityHistory tables. See www.salesforce.com/us/developer/docs/api/index_CSH.htm#field_types.htm for information.

Limits Methods

Because Apex Code runs in a multi-tenant environment, the Apex Code runtime engine strictly enforces a number of limitsto ensure that runaway scripts do not monopolize shared resources.

The Limits methods return the specific limit for the context in which they are being executed, that is, from a trigger, a WSDLmethod, and so on.

None of the Limits methods require an argument. The format of the limits methods is as follows:

myDMLLimit = Limits.getDMLStatements();

There are two versions of every method: the first returns the amount of the resource that has been used in the current context,while the second version contains the word limit and returns the total amount of the resource that is available for that context.

See Execution Governors and Limits on page 100.

66

Limits Methods

Page 69: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Table 12: Limit Methods

DescriptionReturnsMethod

Returns the number of records that havebeen processed with any DML statement

IntegergetDMLRows()

(insertions, deletions, and so on) in thecurrent context.

Returns the total number of records thatcan be processed with any DML statementin the current context.

IntegergetLimitDMLRows()

Returns the number of DML statements(such as insert or update) that havebeen called in the current context.

IntegergetDMLStatements()

Returns the total number of DMLstatements that can be called in the currentcontext.

IntegergetLimitDMLStatements()

Returns the approximate amount ofmemory (in bytes) that has been used forthe heap in the current context.

IntegergetHeapSize()

Returns the total amount of memory (inbytes) that can be used for the heap in thecurrent context.

IntegergetLimitHeapSize()

Returns the number of DML statementsthat have been called since the last

IntegergetDMLStatementsSinceTransactionControl()

transaction control statement (such as acommit or rollback) in the currentcontext.

Returns the total number of DMLstatements that can be called between two

IntegergetLimitDMLStatementsSinceTransactionControl()

transaction control statements in thecurrent context.

Returns the number of SOQL queries thathave been issued in the current context.

IntegergetQueries()

Returns the total number of SOQL queriesthat can be issued in the current context.

IntegergetLimitQueries()

Returns the number of records that havebeen returned by issuing SOQL queries inthe current context.

IntegergetQueryRows()

Returns the total number of records thatcan be returned by issuing SOQL queriesin the current context.

IntegergetLimitQueryRows()

Returns the number of statements thathave executed in the current context since

IntegergetScriptStatementsSinceDbStatement()

the last database statement (such as aDML statement or a transaction controlstatement).

67

Limits Methods

Page 70: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturnsMethod

Returns the total number of statementsthat can execute between two databasestatements in the current context.

IntegergetLimitScriptStatementsSinceDbStatement()

Returns the number of transaction controlstatements (such as commit or rollback)

IntegergetTransactionControlsStatements()

that have been issued in the currentcontext.

Returns the total number of transactioncontrol statements that can be issued in thecurrent context.

IntegergetLimitTransactionControlsStatements()

List Methods

Unlike system static methods, which do not have an implicit parameter, list methods are all called by and operate on a particularinstance of a list. For example, the following removes all elements from myList:

myList.clear();

Even though the clear() method does not include any parameters, the list that calls it is its implicit parameter.

The table below describes all list methods that are defined in Apex Code.

Note: In the table below, <List_elem> represents a single element of the same type as the list.

Table 13: List Methods

DescriptionReturn TypeArgumentsName

Adds an element e to the end of the listVoid<List_elem> eadd

Inserts an element e into the list at indexposition i

VoidInteger i,

<List_elem> e

add

Adds all of the elements in list l to the listthat calls the method. Note that both listsmust be of the same type.

VoidList laddAll

Removes all elements from a list,consequently setting the list's length to zero

Voidclear

Makes a duplicate copy of a list.

Note that if this is a list of SObject records,the duplicate list will only be a shallow copy

List (of same type)clone

of the list. That is, the duplicate will havereferences to each object, but the SObjectrecords themselves will not be duplicated.For example:

Account a = new Account(name='Acme',

68

List Methods

Page 71: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

city='New York');Account b = new Account();Account[] l1 = new Account[]{a,b};Account[] l2 = l1.clone();l1[0].city = 'San Francisco';System.assertEquals( l1[0].city, 'San Francisco');System.assertEquals( l2[0].city, 'San Francisco');

To also copy the SObject records, you mustuse the deepClone() method.

Makes a duplicate copy of a list of SObjectrecords, including the SObject recordsthemselves. For example:Account a = new Account(name='Acme',

List (of same objecttype)

Boolean opt_preserve_iddeepClone

city='New York');Account b = new Account();Account[] l1 = new Account[]{a,b};Account[] l2 = l1.deepClone();l1[0].city = 'San Francisco';System.assertEquals( l1[0].city, 'San Francisco');System.assertEquals( l2[0].city, 'New York');

Note: deepClone only works withlists of sObjects, not with lists ofprimitives.

The optional opt_preserve_id argumentdetermines whether the Id of the originalobjects are preserved or cleared in theduplicates.

To make a shallow copy of a list withoutduplicating the SObject records it contains,use the clone() method.

Returns the list element stored at index i

To reference an element of aone-dimensional list of primitives or

<Array_elem>Integer iget

SObjects, you can also follow the name ofthe list with the element's index position insquare brackets. For example:

colors[3]

69

List Methods

Page 72: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

Returns true if the list has zero elementsBooleanisEmpty

Removes the element that was stored at theith index of a list, returning the element thatwas removed

<Array_elem>Integer iremove

Assigns e to the position at list index i

To set an element of a one-dimensional listof primitives or SObjects, you can also follow

Integer i, <List_elem> eset

the name of the list with the element's indexposition in square brackets. For example:

colors[3] = 'green';

Returns the number of elements in the listIntegersize

For more information on lists, see Lists on page 26.

Set Methods

Similar to list methods, set methods are all called by and operate on a particular instance of a set.

The table below describes all set methods that are defined in Apex Code.

Note: In the table below, <Set_elem> represents a single element in the set. Sets can only contain primitive data types.

Table 14: Set Methods

DescriptionReturn TypeArgumentsName

Adds an element to the set if it is not already present.

This method returns true if the original set changed asa result of the call.

Boolean<Set_elem> eadd

Adds all of the elements in the specified array to the setif they are not already present. This method results in

BooleanArray aaddAll

the union of the array and the set. The array must be ofthe same type as the set that calls the method.

This method returns true if the original set changed asa result of the call.

Adds all of the elements in the specified set to the setthat calls the method if they are not already present.This

BooleanSet saddAll

method results in the union of the two sets.The specifiedset must be of the same type as the original set that callsthe method.

This method returns true if the original set changed asa result of the call.

70

Set Methods

Page 73: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

Removes all of the elements from the setVoidclear

Makes a duplicate copy of the setSet (of same type)clone

Returns true if the set contains the specified elementBoolean<Set_elem> econtains

Returns true if the set contains all of the elements in thespecified array. The array must be of the same type asthe set that calls the method.

BooleanArray acontainsAll

Returns true if the set contains all of the elements in thespecified set. The specified set must be of the same typeas the original set that calls the method.

BooleanSet scontainsAll

Returns true if the set has zero elementsBooleanisEmpty

Removes the specified element from the set if it ispresent.

This method returns true if the original set changed asa result of the call.

Boolean<Set_elem> eremove

Removes the elements in the specified array from theset if they are present. The array must be of the sametype as the set that calls the method.

This method returns true if the original set changed asa result of the call.

BooleanArray aremoveAll

Removes the elements in the specified set from theoriginal set if they are present. The specified set must

BooleanSet sremoveAll

be of the same type as the original set that calls themethod.

This method returns true if the original set changed asa result of the call.

Retains only the elements in this set that are containedin the specified array. This method results in the

BooleanArray aretainAll

intersection of the array and the set. The array must beof the same type as the set that calls the method.

This method returns true if the original set changed asa result of the call.

Retains only the elements in the original set that arecontained in the specified set. This method results in

BooleanSet sretainAll

the intersection of the two sets. The specified set mustbe of the same type as the original set that calls themethod.

This method returns true if the original set changed asa result of the call.

Returns the number of elements in the set (itscardinality)

Integersize

71

Set Methods

Page 74: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

For more information on sets, see Sets on page 28.

Map Methods

Similar to list methods, map methods are all called by and operate on a particular instance of a map.

The table below describes all map methods that are defined in Apex Code.

Note: In the table below:

• <Key_type> represents the primitive type of a map key.• <Value_type> represents the primitive or SObject type of a map

value.

Table 15: Map Methods

DescriptionReturn TypeArgumentsName

Removes all of the key-value mappings from the mapVoidclear

Makes a duplicate copy of the map.

Note that if this is a map with SObject record values,the duplicate map will only be a shallow copy of the map.

Map (of same type)clone

That is, the duplicate will have references to eachSObject record, but the records themselves are notduplicated. For example:

Account a = new Account(name='Acme', city='New York');

Map<Integer, Account> map1 = new Map<Id, Account>;map1.put(1, a);Map<Integer, Account> map2 = map1.clone();map1.get(1).city = 'San Francisco';

System.assertEquals(map1.get(1).city, 'San Francisco');System.assertEquals(map2.get(1).city, 'San Francisco');"

To also copy the SObject records, you must use thedeepClone() method.

Returns true if the map contains a mapping for thespecified key

Boolean<Key_type> keycontainsKey

Makes a duplicate copy of a map, including SObjectrecords if this is a map with SObject record values. Forexample:Account a = new Account(name='Acme', city='New York');

Map (of the sametype)

deepClone

Map<Integer, Account> map1 = new Map<Id, Account>;map1.put(1, a);Map<Integer, Account> map2 = map1.deepClone();

72

Map Methods

Page 75: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

map1.get(1).city = 'San Francisco';

System.assertEquals(map1.get(1).city, 'San Francisco');System.assertEquals(map2.get(1).city, 'New York');"

To make a shallow copy of a map without duplicatingthe SObject records it contains, use the clone()method.

Returns the value to which the specified key is mapped,or null if the map contains no value for this key

<Value_type><Key_type> keyget

Returns true if the map has zero key-value pairsBooleanisEmpty

Returns a set that contains all of the keys in the mapSet of Key_typekeySet

Associates the specified value with the specified key

in the map. If the map previously contained a mapping<Value_type><Key_type> key,

<Value_type> value

put

for this key, the old value is returned by the method andthen replaced.

Copies all of the mappings from the specified map m tothe original map.The new mappings from m replace anymappings that the original map had.

Map mputAll

If the map is of Ids or Strings to SObjects, adds the listof SObject records l to the map in the same way as the

BooleanSObject[] lputAll

Map constructor with this input, returning true if anychanges were made to the original map.

Removes the mapping for this key from the map if it ispresent. The value is returned by the method and thenremoved.

<Value_type><Key_type> keyremove

Returns the number of key-value pairs in the mapIntegersize

Returns a list that contains all of the values in the mapin arbitrary order

Array of<Value_type>

values

For more information on maps, see Maps on page 28.

Double Methods

Similar to list methods, Double methods are all called by and operate on a particular instance of a Double.

The table below describes all Double methods that are defined in Apex Code.

Table 16: Double Methods

DescriptionReturn TypeArgumentsName

Returns the Integer value of this Double by casting it toan Integer

IntegerintValue

73

Double Methods

Page 76: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

For more information on Doubles, see Primitive Data Types on page 23.

SObject Methods

Similar to list methods, SObject methods are all called by and operate on a particular instance of an SObject, such as an accountor contact.

The table below describes all SObject methods that are defined in Apex Code.

Table 17: SObject Methods

DescriptionReturn TypeArgumentsName

Marks a record with a custom error message andprevents any DML operation from occurring.

When used on Trigger.new in beforeinsert and before update triggers, and on

VoidString errorMsgaddError

Trigger.old in before delete triggers, theerror message is displayed in the applicationinterface.

See Triggers on page 86 and Trigger Exceptionson page 92.

Places the specified error message on the fieldthat calls this method in the application interface

VoidString errorMsg<field>.addError

and prevents any DML operation from occurring.For example:Trigger.new.myField__C.addError('bad');

Note:

• When used on Trigger.new in beforeinsert and before update triggers, andon Trigger.old in before deletetriggers, the error appears in the applicationinterface.

• This method is highly specialized because thefield identifier is not actually the invokingobject—the SObject record is the invoker.The field is simply used to identify the fieldthat should be used to display the error.

• This method will likely change in futureversions of Apex Code.

See Triggers on page 86 and Trigger Exceptionson page 92.

Clears all field valuesVoidclear

Creates a copy of the SObject record.

The optional opt_preserve_id argumentdetermines whether the Id of the original objectis preserved or cleared in the duplicate.

<SObject> (of sametype)

Booleanopt_preserve_id

clone

74

SObject Methods

Page 77: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

For more information on SObjects, see SObject Types on page 24.

String Methods

Similar to list methods, String methods are all called by and operate on a particular instance of a String.

The table below describes all String methods that are defined in Apex Code.

Table 18: String Methods

DescriptionReturn TypeArgumentsName

Compares two strings lexicographically,based on the Unicode value of each characterin the Strings. The result is:

IntegerString compStringcompareTo

• A negative Integer if the String thatcalled the method lexicographicallyprecedes compString

• A positive Integer if the String that calledthe method lexicographically followscompString

• Zero if the Strings are equal

If there is no index position at which theStrings differ, then the shorter Stringlexicographically precedes the longer String.

Note that this method returns 0 wheneverthe equals() method returns true.

Returns true if and only if the String thatcalled the method contains the specifiedsequence of characters in the compString

BooleanString compStringcontains

Returns true if the String that called themethod ends with the specified suffix

BooleanString suffixendsWith

Returns true if the compString is not nulland represents the same binary sequence of

BooleanString compStringequals

characters as the String that called themethod. This method is true whenever thecompareTo() method returns 0.

Note that the == operator also performsString comparison, but is case-insensitive tomatch Apex Code semantics. (== iscase-sensitive for Id comparison for the samereason.)

Returns true if the compString is not nulland represents the same sequence of

BooleanString compStringequalsIgnoreCase

characters as the String that called themethod, ignoring case

Returns the index of the first occurrence ofthe specified substring from the point of

IntegerString substring,

Integer i

indexOf

75

String Methods

Page 78: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

index i. If the substring does not occur, thismethod returns -1.

Returns the number of 16-bit Unicodecharacters contained in the String

Integerlength

Returns a list that contains each substring ofthe String that is terminated by the regular

String[]String regExp,

Integer limit

split

expression regExp, or the end of the String.(See http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/Pattern.html forinformation on regular expressions.)

The substrings are placed in the list in theorder in which they occur in the String. IfregExp does not match any part of theString, the resulting list has just one elementcontaining the original String.

The optional limit parameter controls thenumber of times the pattern is applied andtherefore affects the length of the list:

• If limit is greater than zero, the patternis applied at most limit - 1 times, thelist's length is no greater than limit, andthe list's last entry contains all inputbeyond the last matched delimiter.

• If limit is non-positive then the patternis applied as many times as possible andthe list can have any length.

• If limit is zero then the pattern isapplied as many times as possible, the listcan have any length, and trailing emptystrings are discarded.

For example, for String s ='boo:and:foo':

• s.split(':', 2) results in {'boo','and:foo'}

• s.split(':', 5) results in {'boo','and', 'foo'}

• s.split(':', -2) results in {'boo','and', 'foo'}

• s.split('o', 5) results in {'b','', ':and:f', '', ''}

• s.split('o', -2) results in {'b','', ':and:f', '', ''}

• s.split('o', 0) results in {'b','', ':and:f'}

Returns true if the String that called themethod begins with the specified prefix

BooleanString prefixstartsWith

76

String Methods

Page 79: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

Returns a new String that begins with thecharacter at the specified startIndex andextends to the end of the String

StringInteger startIndexsubstring

Returns a new String that begins with thecharacter at the specified startIndex and

StringInteger startIndex,

Integer endIndex

substring

extends to the character at endIndex - 1.For example:

"hamburger".substring(4, 8) // Returns "urge"

"smiles".substring(1, 5) // Returns "mile"

Converts all of the characters in the Stringto lowercase using the rules of the defaultlocale

StringtoLowerCase

Converts all of the characters in the Stringto uppercase using the rules of the defaultlocale

StringtoUpperCase

For more information on Strings, see Primitive Data Types on page 23.

Date Methods

Similar to list methods, Date methods are all called by and operate on a particular instance of a Date.

The table below describes all Date methods that are defined in Apex Code.

Table 19: Date Methods

DescriptionReturn TypeArgumentsName

Adds the specified number of addlDays toa Date

DateInteger addlDaysaddDays

Adds the specified number of addlMonths

to a DateDateInteger addlMonthsaddMonths

Adds the specified number of addlYears

to a DateDateInteger addlYearsaddYears

Returns the day-of-month component of aDate. For example, February 5, 1999 wouldbe day 5.

Integerday

Returns the day-of-year component of aDate. For example, February 5, 1999 wouldbe day 36.

IntegerdayOfYear

Returns the number of days between theDate that called the method and the

IntegerDate compDatedaysBetween

compDate. If the Date that calls the method

77

Date Methods

Page 80: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

occurs before the compDate, the return valueis negative.

Returns true if the Date that called themethod is the same as the compDate

BooleanDate compDateisSameDay

Returns the month component of a Date(1=Jan)

Integermonth

Returns the number of months between theDate that called the method and the

IntegerDate compDatemonthsBetween

compDate, ignoring the difference in dates.For example, March 1 and March 30 of thesame year have 0 months between them.

Returns the start of the week for the Datethat called the method, depending on the

DatetoStartOfWeek

context user's locale. For example, the startof a week is Sunday in the United Stateslocale, and Monday in European locales.

Returns the first of the month for the Datethat called the method. For example, July 14,1999 returns July 1, 1999.

DatetoStartOfMonth

Returns the year component of a DateIntegeryear

For more information on Dates, see Primitive Data Types on page 23.

Datetime Methods

Similar to list methods, Datetime methods are all called by and operate on a particular instance of a Datetime.

The table below describes all Datetime methods that are defined in Apex Code.

Table 20: Datetime Methods

DescriptionReturn TypeArgumentsName

Adds the specified number of addlDays toa Datetime

DatetimeInteger addlDaysaddDays

Adds the specified number of addlHours

to a DatetimeDatetimeInteger addlHoursaddHours

Adds the specified number of addlMinutes

to a DatetimeDatetimeInteger addlMinutesaddMinutes

Adds the specified number of addlMonths

to a DatetimeDatetimeInteger addlMonthsaddMonths

Adds the specified number of addlSeconds

to a DatetimeDatetimeInteger addlSecondsaddSeconds

Adds the specified number of addlYears

to a DatetimeDatetimeInteger addlYearsaddYears

78

Datetime Methods

Page 81: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionReturn TypeArgumentsName

Returns the day-of-month component of aDatetime in the local time zone of the

Integerday

context user. For example, February 5, 199908:30:12 would be day 5.

Returns the day-of-month component of aDatetime in the GMT time zone. For

IntegerdayGmt

example, February 5, 1999 08:30:12 wouldbe day 5.

Returns the day-of-year component of aDatetime in the local time zone of the

IntegerdayOfYear

context user. For example, February 5, 199908:30:12 would be day 36.

Returns the day-of-year component of aDatetime in the GMT time zone. For

IntegerdayOfYearGmt

example, February 5, 1999 08:30:12 wouldbe day 36.

Returns the hour component of a Datetimein the local time zone of the context user

Integerhour

Returns the hour component of a Datetimein the GMT time zone

IntegerhourGmt

Returns true if the Datetime that called themethod is the same as the compDt in thelocal time zone of the context user

BooleanDatetime compDtisSameDay

Returns the minute component of aDatetime in the local time zone of thecontext user

Integerminute

Returns the minute component of aDatetime in the GMT time zone

IntegerminuteGmt

Returns the month component of a Datetimein the local time zone of the context user(1=Jan)

Integermonth

Returns the month component of a Datetimein the GMT time zone (1=Jan)

IntegermonthGmt

Returns the second component of a Datetimein the local time zone of the context user

Integersecond

Returns the second component of a Datetimein the GMT time zone

IntegersecondGmt

Returns the year component of a Datetimein the local time zone of the context user

Integeryear

Returns the year component of a Datetimein the GMT time zone

IntegeryearGmt

For more information on Datetimes, see Primitive Data Types on page 23.

79

Datetime Methods

Page 82: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Exception Methods

Similar to list methods, Exception methods are all called by and operate on a particular instance of an Exception.

The table below describes all Exception methods that are defined in Apex Code.

Table 21: Exception Type Methods

DescriptionReturn TypeArgumentsName

Returns the names of the field(s) that caused the errordescribed by the ith failed row. For DMLExceptions,only.

String[]Integer igetDmlFields

Returns the original row position of the ith failed row.For DMLExceptions, only.

IntegerInteger igetDmlIndex

Returns the user message for the ith failed row. ForDMLExceptions, only.

StringInteger igetDmlMessage

Returns the Apex Code failure code for the ith failedrow. For DMLExceptions, only.

StringInteger igetDmlStatusCode

Returns the error message that displays for the userStringgetMessage

Returns the number of failed rows for DML exceptionsIntegergetNumDml

Returns the type of exception, such as DMLStringgetTypeName

For more information on exceptions, see Exception Statements on page 57.

User-Defined Methods

Apex Code users can define custom methods in anonymous blocks, triggers, or in stored packages. For example, the followingcode from an anonymous block defines a new method called fact(), and then calls it within a System.assertEquals()statement:

Integer fact(Integer n) { System.assert(n > 0); if (n == 1) return 1; return n * fact(n - 1);}System.assertEquals(24, fact(4));

Note that user-defined methods:

• Can be used anywhere that system methods are used• Pass arguments by reference, so that a variable that is passed into a method and then modified will also be modified in the

original code that called the method• Can be recursive• Can have side effects, such as DML insert statements that initialize SObject record Ids. See Data Manipulation Language

(DML) Statements on page 49 for information.• Can refer to themselves or to methods defined later in the same package or anonymous block. Apex Code parses methods

in two phases, so forward declarations are not needed.• Can be polymorphic. For example, a method named foo can be implemented in two ways, one with a single Integer

parameter, and one with two Integer parameters. Depending on whether the method is called with one or two Integers,

80

Exception Methods

Page 83: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

the Apex Code parser selects the appropriate implementation to execute. If the parser cannot find an exact match, it thenseeks an approximate match using type coercion rules:

• A Double can be an Integer• An Id can be a String• A String can be an Id

Note: If the parser finds multiple approximate matches, a parse-time exception is generated.

81

User-Defined Methods

Page 84: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 6

Packaging and Invoking Apex Code

Apex Code allows you to manage and invoke scripts through three differentconstructs: packages, triggers, and anonymous blocks.

In this chapter ...

• Packages• A package is a standard library of methods that can be reused from script to

script. Packages consist of a set of user-defined methods, variables, exception• Triggers• Anonymous Blocks types, and optional static initialization code, and are stored as metadata within

the application under Setup ➤ Build ➤ Code.

Once compiled, packages can be invoked through package methods orvariables by any other Apex Code script, or through the Apex Web Services

• Invoking Apex Code in AJAX

API (or AJAX toolkit) for methods that have been designated with thewebService keyword.

• A trigger is an Apex Code script that executes before or after a specific datamanipulation language (DML) events occur, such as before object recordsare inserted into the database, or after records have been deleted.

Triggers are stored as metadata within the application under Setup ➤

Customize ➤ <Std_Object_Name> ➤ Buttons & Links for standardobjects, and in the object detail page for custom objects (Setup ➤ Build ➤Custom Objects).

• An anonymous block is an Apex Code script that does not get stored in themetadata, but that can be compiled and executed through the use of theExecuteAnonymousResult()Apex API call, or the equivalent in the AJAXtoolkit.

The remainder of this chapter details the syntax and use of these three constructs.

82

Page 85: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Packages

As mentioned above, a package is equivalent to a standard library of methods that can be reused from script to script. Packagesconsist of:

• A set of package-level variables• A set of package-level exception types• A set of user-defined methods• Optional static initialization code (a block of code demarcated with the static keyword that runs only once when a

package is initially loaded for execution in the current context of Apex Code)

Package Syntax

To define a package, use the following syntax:

package <packageName> {

<variable_and_exception_declarations>

<method_definitions>

<static_initialization_code>

}

Note that while methods and exception types can be defined at any point in the package, variable declarations must alwaysprecede their first use in the code. For example:

package myPkg { // pkgInteger = 999; This assignment is not allowed because pkgInteger // has not yet been declared

Integer pkgInteger; define PkgException;

void pkgMethod() { // Your code here }

static { pkgInteger = 1000; // Allowed }}

Defining a Package

Packages are stored as metadata in the application. To define a pacakge:

1. In the application, click Setup ➤ Build ➤ Code.2. Click New.3. In the Body text box, enter the Apex Code for the package.

Note: A single package can be up to 100,000 characters in length.

4. Click Save.

Once compiled, packages can be invoked through package methods or variables by any other Apex Code script.

83

Packages

Page 86: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Note: To aid backwards-compatibility, packages are stored with the version of the API that was used to compilethem. Additionally, packages are stored with an IsValid flag that is set to true as long as dependent metadata hasnot changed since the package was last compiled. If any changes are made to object names or fields that are used inthe package, including superficial changes such as edits to an object or field description, the isValid flag is set tofalse until the Apex Code compiler reprocesses the code.

The Public, Private, and Final Keywords

Apex Code allows you to use the public and private keywords when defining package variables, exception types, andmethods, and the final keyword when defining variables. Note that while triggers and anonymous blocks can also use thesekeywords, they are not as useful in smaller portions of Apex Code.

By default, all package identifiers are visible to Apex Code within the package and within other packages in the same applicationnamespace (see Namespace Prefixes on page 85). You can change the level of visibility for individual identifiers by using thepublic or private keywords in the identifier's declaration:

• public allows the identifier to be used by any Apex Code that has access to the package, not just code in the samenamespace

• private restricts the identifier from being used by any package other than the one in which it is declared

You can define constants by using the final keyword in front of any variable declaration. final restricts the variable frombeing assigned a value more than once, either in the declaration itself, or in a static initializer. Assigning a value to a finalvariable more than once results in a runtime exception.

To use the public, private, or final keywords, use the following syntax:

<public | private> <final> <declaration>

For example:

package myPkg { public class PkgException extends Exception{} public Integer pubInt; final Integer INT_CONSTANT; private final Integer PRIVATE_INT_CONSTANT = 2;

public void doIt() { // This method can be called externally using myPkg.doIt();}

Integer calculate() { return 2 + 7;}

// Static initializer code runs only once when// a package is initially loadedstatic { INT_CONSTANT = calculate();}

Package Variables and Static Initializers

Package variables are always static, and are scoped by the current context of Apex Code in which they exist. As a result, alltriggers that are spawned by the same request can communicate with each other by viewing and updating variables in a relatedpackage. For example, a recursive trigger might use the value of a package variable to determine when to exit the recursion.

Any code in a static initializer is executed when a package is first loaded for the particular context of Apex Code.

84

Packages

Page 87: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

WebService Methods

Apex Code package methods can also be exposed as custom Apex Web Services API calls. To do so, use the webServicekeyword. For example:

package myPackage { webService Id makeContact(String lastName, Account a) { Contact c = new Contact(lastName = 'Weissman', AccountId = a.Id); insert c; commit; return c.id; }}

You can then download the WSDL from the package's detail page:

1. In the application navigate to Setup ➤ Build ➤ Code.2. Click the name of a package that contains webService methods.3. Click Generate WSDL.

All methods that are defined with the webService keyword are inherently public and can be used by any Apex Code thathas access to the package.

Because there are no SOAP analogs for certain Apex Code elements, methods cannot be defined with the webServicekeyword if they include Exceptions, maps, or sets.

Exposing Data with WebService Methods

Invoking a custom WebService method always uses System context. Consequently, the current user's credentials are not used,and any user who has access to these methods can use their full power, regardless of permissions, field-level security, or sharingrules. Developers who expose methods with the webService keyword should therefore take care that they are not inadvertentlyexposing any sensitive data.

Caution: Apex Code package methods that are exposed through the API with the webService keyword do notobserve object permissions, field-level security, or sharing rules for any records.

Polymorphism and Web Service Methods

SOAP and WSDL do not provide good support for polymorphism. Consequently, Apex Code does not allow two methodsmarked with the webService keyword to have the same name. Web service methods that do have the same name in the samepackage will generate a compile-time error.

Namespace Prefixes

With the release of Winter '07, the application now supports the use of namespace prefixes. Namespace prefixes are used inmanaged AppExchange packages to differentiate custom object and field names from those in use by other organizations.After a developer registers a globally unique namespace prefix and registers it with the AppExchange registry, external referencesto custom object and field names in the developer's managed packages take on the following long format:

<namespace_prefix>__<obj_or_field_name>__c

Because these fully-qualified names can be onerous to update in working SOQL statements and Apex Code code once apackage is marked as "managed," Apex Code supports a default namespace for schema names. When looking at identifiers,the parser considers the namespace of the current object and then assumes that it is the namespace of all other objects and

85

Packages

Page 88: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

fields unless otherwise specified. Consequently, a stored package should refer to custom object and field names directly (using<obj_or_field_name>__c) for those objects that are defined within its same application namespace.

Tip: Only use namespace prefixes when referring to custom object and field names that exist outside of yourorganization.

Using Namespaces When Invoking Methods

To invoke a method that was defined in another managed package, Apex Code allows fully-qualified identifiers of the form:

<namespace_prefix>.<package>.<method>(<args>)

The special namespace System can be used to disambiguate the built-in static packages from any user-defined ones (forexample, System.System.debug()). Without the System namespace prefix, system static package names such as Mathand System can be overridden by user-defined packages with the same name, as outlined in Namespace, Package, and VariableName Precedence, below.

Tip: Only use namespace prefixes when invoking methods stored in packages outside of your organization.

Namespace, Package, and Variable Name Precedence

Because local variables, package names, and namespaces can all hypothetically use the same identifiers, the Apex Code parserevaluates expressions in the form of name1.name2.<...>.nameN as follows:

1. The parser first assumes that name1 is a local variable with name2 - nameN as field references.2. If the first assumption does not hold true, the parser then assumes that name1 is a package name and name2 is a static

variable name with name3 - nameN as field references.3. If the second assumption does not hold true, the parser then assumes that name1 is a namespace name, name2 is a package

name, name3 is a static variable name, and name4 - nameN are field references.4. If the third assumption does not hold true, the parser reports an error.

If the expression ends with a set of parentheses (for example,name1.name2.<...>.nameM.nameN()), the Apex Code parserevaluates the expression as follows:

1. The parser first assumes that name1 is a local variable with name2 - nameM as field references, and nameN as a methodinvocation.

2. If the first assumption does not hold true:

• If the expression contains only two identifiers (name1.name2()), the parser then assumes that name1 is a packagename and name2 is a method invocation.

• If the expression contains more than two identifiers, the parser then assumes that name1 is a package name, name2 isa static variable name with name3 - nameM as field references, and nameN is a method invocation.

3. If the second assumption does not hold true, the parser then assumes that name1 is a namespace name, name2 is a packagename, name3 is a static variable name, name4 - nameM are field references, and nameN is a method invocation.

4. If the third assumption does not hold true, the parser reports an error.

Triggers

In addition to packages, Apex Code script can also be invoked through the use of triggers. A trigger is an Apex Code scriptthat executes before or after INSERT, UPDATE, or DELETE events occur, such as before object records are inserted into the

86

Triggers

Page 89: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

database, or after records have been deleted. You can define triggers for any top-level standard object, such as a Contact or anAccount, but not for standard child objects, such as a ContactRole.

Note:

• upsert events fire insert or update triggers as appropriate.• merge events fire delete triggers for the losing records and update triggers for the winning record only. See

Triggers and Merge Statements on page 91.

Triggers can be divided into two types:

• Before triggers can be used to update or validate record values before they are saved to the database• After triggers can be used to access field values that are set by the database (such as a record's Id or lastUpdated field),

and to affect changes in other object records, such as logging into an audit table, or firing asynchronous events with a queue

Triggers are similar to workflow in that they are not subject to the permissions, field-level security, or sharing rules of thecurrent user. If a trigger is fired, it operates as if the current user is an administrator.

Additionally, triggers can modify other records of the same type as the records that initially set off the trigger. For example,if a trigger fires after an update of contact a, the trigger can also modify contacts b, c, and d. Since triggers can cause otherrecords to change, and since these changes can, in turn, fire more triggers, the Apex Code runtime engine considers all suchoperations a single unit of work and sets limits on the number of operations that can be performed to prevent infinite recursion.See Execution Governors and Limits on page 100.

Bulk Triggers

In earlier versions of Apex Code, triggers could process only one SObject record at a time and did not support bulk processing.Consequently, if you defined a trigger that included SOQL queries or DML statements, you could not use API bulk processingcalls on SObjects that fired that trigger without quickly surpassing database query limits.

In this version of Apex Code, the single record processing model is no longer available. All triggers are now bulk triggers thatcan process multiple records at a time. Bulk triggers can handle both single record updates and bulk operations like:

• Data import• Bulk Apex API calls• Mass actions, such as record owner changes and deletes• Recursive Apex Code methods and triggers that invoke bulk DML statements

Syntax

To define a trigger, use the following syntax:

trigger <triggerName> on <ObjectName> bulk (<trigger_events>) {

<code_block>

}

where <trigger_events> can be a comma-separated list of one or more of the following events:

• before insert

• before update

• before delete

• after insert

• after update

• after delete

87

Triggers

Page 90: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

For example, the following code defines a trigger for the before insert and before update events on an Account:

trigger myAccountTrigger on Account bulk (before insert, before update) { // Your code here}

The <code_block> of a trigger can contain any type of Apex Code except for transaction control statements such as commitand rollback. These statements produce errors because triggers are already fired within the main object record transaction.

Trigger Context Variables

All triggers define implicit variables that allow developers to access runtime context. These variables are contained in theSystem.Trigger package:

Table 22: Trigger Context Variables

UsageVariable

Returns true if this trigger was fired due to an INSERT operationisInsert

Returns true if this trigger was fired due to an UPDATE operationisUpdate

Returns true if this trigger was fired due to a DELETE operationisDelete

Returns true if this trigger was fired before any record was savedisBefore

Returns true if this trigger was fired after all records were savedisAfter

Returns a list of the new versions of the SObject records.

Note that this SObject list is only available in insert and update triggers, and the recordscan only be modified in before triggers.

new

A map of Ids to the new versions of the SObject records.

Note that this map is only available in before update,after insert, and after updatetriggers.

newMap

Returns a list of the old versions of the SObject records.

Note that this SObject list is only available in update and delete triggers.

old

A map of Ids to the old versions of the SObject records.

Note that this map is only available in update and delete triggers.

oldMap

The total number of records in a trigger invocation, both old and new.size

Note: If any record that fires a trigger includes an invalid field value (for example, a formula that divides by zero),that value is set to null in the new, newMap, old, and oldMap trigger context variables.

For example, in this simple trigger, Trigger.new is a list of SObjects and can be iterated over in a for loop, or used as abind variable in the IN clause of a SOQL query:

Trigger t on Account bulk (after insert) { for (Account a : Trigger.new) { // Iterate over each SObject }

88

Triggers

Page 91: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// This single query finds every contact that is associated with any of the // triggering accounts. Note that although Trigger.new is a collection of // records, when used as a bind variable in a SOQL query, Apex Code automatically // transforms the list of records into a list of corresponding Ids. Contact[] cons = [select lastname from contact where accountid in :Trigger.new];}

This trigger uses Boolean context variables like Trigger.isBefore and Trigger.isDelete to define code that onlyexecutes for specific trigger conditions:

trigger myAccountTrigger on Account(before delete, before insert, before update, after delete, after insert, after update) {if (Trigger.isBefore) { if (Trigger.isDelete) {

// In a before delete trigger, the trigger accesses the records that will be // deleted with the Trigger.old list. for (Account a : Trigger.old) { if (a.name != 'okToDelete') { a.addError('You can\'t delete this record!'); } } } else {

// In before insert or before update triggers, the trigger accesses the new records // with the Trigger.new list. for (Account a : Trigger.new) { if (a.name == 'bad') { a.name.addError('Bad name'); } } if (Trigger.isInsert) { for (Account a : Trigger.new) { System.assertEquals('xxx', a.accountNumber); System.assertEquals('industry', a.industry); System.assertEquals(100, a.numberofemployees); System.assertEquals(100.0, a.annualrevenue); a.accountNumber = 'yyy'; }

// If the trigger is not a before trigger, it must be an after trigger.} else { if (Trigger.isInsert) { List<Contact> contacts = new Contact[0]; for (Account a : Trigger.new) { if(a.name == 'makeContact') { contacts.add(new Contact (lastname = a.name, accountId = a.id)); } } insert contacts; } }}

Common Bulk Trigger Idioms

Although bulk triggers allow developers to process more records without exceeding execution governor limits, they can bemore difficult for developers to understand and code because they involve processing batches of several records at a time. Thefollowing sections provide examples of idioms that should be used frequently when writing in bulk.

89

Triggers

Page 92: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Using Maps and Sets in Bulk Triggers

Set and map data structures are critical for successful coding of bulk triggers. Sets can be used to isolate distinct records, whilemaps can be used to hold query results organized by record Id.

For example, this bulk trigger from the sample quoting application first adds each pricebook entry associated with theOpportunityLineItem records in Trigger.new to a set, ensuring that the set contains only distinct elements. It then queriesthe PricebookEntries for their associated product color, and places the results in a map. Once the map is created, the triggeriterates through the OpportunityLineItems in Trigger.new and uses the map to assign the appropriate color.

// When a new line item is added to an opportunity, this trigger copies the value of the// associated product's color to the new record.trigger oppLineTrigger on OpportunityLineItem bulk (before insert) {

// For every OpportunityLineItem record, add its associated pricebook entry // to a set so there are no duplicates. Set<Id> pbeIds = new Set<Id>(); for (OpportunityLineItem oli : Trigger.new) pbeIds.add(oli.pricebookentryid);

// Query the PricebookEntries for their associated product color and place the results // in a map. Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>( [select product2.color__c from pricebookentry where id in :pbeIds]);

// Now use the map to set the appropriate color on every OpportunityLineItem processed // by the trigger. for (OpportunityLineItem oli : Trigger.new) oli.color__c = entries.get(oli.pricebookEntryId).product2.color__c; }

Correlating Records with Query Results in Bulk Triggers

If you need to issue a SOQL query to get related data for records in the Trigger.new and Trigger.old lists, it is best notto assume that the new query will return the same number of records in the same order. Even though these lists are sorted byId, external operations might change the number of records that are returned and make parallel list processing dangerous.

Instead, use the Trigger.newMap and Trigger.oldMap Id-to-SObject maps to correlate records with query results. Forexample, this trigger from the sample quoting app uses Trigger.oldMap to create a set of unique Ids(Trigger.oldMap.keySet()).The set is then used as part of a query to create a list of quotes associated with the opportunitiesbeing processed by the trigger. For every quote returned by the query, the related opportunity is retrieved from Trigger.oldMapand prevented from being deleted:

trigger oppTrigger on Opportunity bulk (before delete) { for (Quote__c q : [select opportunity__c from quote__c where opportunity__c in :Trigger.oldMap.keySet()]) { Trigger.oldMap.get(q.opportunity__c).addError('Cannot delete opportunity with a quote'); }}

Defining a Trigger

Trigger scripts are stored as metadata under the object with which they are associated:

1. To define a trigger on a standard object, click Setup ➤ Customize ➤ <Std_Object_Name> ➤ Buttons & Links.

To define a trigger on a custom object, click Setup ➤ Build ➤ Custom Objects and click the name of the object.

90

Triggers

Page 93: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

2. In the Triggers related list, click New.3. In the Body text box, enter the Apex Code for the trigger.

Note: A single trigger can be up to 32,000 characters in length.

4. Select the Is Active checkbox if the trigger should be compiled and enabled. Leave this checkbox unselected if you onlywant to store the script in your organization's metadata.

5. Click Save.

Note: To aid backwards-compatibility, a trigger is stored with the version of the API that was used to compile it.Additionally, triggers are stored with an IsValid flag that is set to true as long as dependent metadata has not changedsince the trigger was last compiled. If any changes are made to object names or fields that are used in the trigger,including superficial changes such as edits to an object or field description, the isValid flag is set to false until theApex Code compiler reprocesses the code.

Triggers and Merge Statements

Merge events do not fire their own trigger events. Instead, they fire delete and update events as follows:

• Deletion of losing records. A single merge operation fires a single delete event for all records that are deleted in the merge.To determine which records were deleted as a result of a merge operation use the MasterRecordId field in Trigger.old.When a record is deleted after losing a merge operation, its MasterRecordId field is set to the Id of the winning record.

• Update of the winning record. A single merge operation fires a single update event for the winning record only. Any childrecords that are reparented as a result of the merge operation do not fire triggers.

Triggers and Order of Execution

When a record is saved with an insert, update, or upsert statement, the following events occur in order:

1. The original record is loaded from the database (or initialized for an insert statement)2. The new record field values are loaded from the request and overwrite the old values3. All before triggers execute4. System validation occurs, such as verifying that all required fields have a non-null value, and running any user-defined

validation rules5. The record is saved to the database, but not yet committed6. The record is reloaded as required for Apex Code and/or workflow rules7. All after triggers execute8. Workflow rules execute9. All DML operations are committed to the database10. Post-commit logic executes, such as sending email

Trigger-Ignoring Operations

Triggers are only invoked for data manipulation language (DML) operations that are initiated or processed by the Javaapplication server. Consequently, some system bulk operations do not currently invoke triggers. Some examples include:

• Cascading delete operations. Records that did not initiate a delete do not cause trigger evaluation.• Cascading updates of child records that are reparented as a result of a merge operation• Mass campaign status changes• Mass division transfers

91

Triggers

Page 94: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• Mass address updates• Mass approval request transfers• Modifying custom field data types• Renaming or replacing picklists• Managing price books• Mass case status updates (including closing a case)• Mass lead status updates• Mass delete of leads

Note: Inserts, updates, and deletes on Person Accounts fire Account triggers, not Contact triggers.

Fields that Cannot Be Updated by Triggers

Some field values are set during the system save operation which occurs after before triggers have fired. As a result, thesefields cannot be modified or accurately detected in before insert or before update triggers. Some examples include:

• Task.isClosed

• Opportunity.isWon

• Opportunity.isClosed

• Opportunity.forecastCategory

• Contract.activatedDate

• Contract.activatedById

• Case.isClosed

• Solution.isReviewed

• Id (for all records)*• createdDate (for all records)*• lastUpdated (for all records)

* Id and createdDate can be detected in before update triggers, but cannot be modified.

Trigger Exceptions

Triggers can be used to prevent DML operations from occurring by calling the addError() method on a record or field.When used on Trigger.new records in insert and update triggers, and on Trigger.old records in delete triggers,the custom error message is displayed in the application interface and logged.

Note: Users experience less of a delay in response time if errors are added to before triggers.

A subset of the records being processed can be marked with the addError() method:

• If the trigger was spawned by a DML statement in Apex Code, any one error results in the entire operation rolling back.However, the runtime engine still processes every record in the operation to compile a comprehensive list of errors.

• If the trigger was spawned by a bulk DML call in the Apex API, the runtime engine sets aside the bad records and attemptsto do a partial save of the records that did not generate errors. See Bulk DML Exception Handling on page 56.

If a trigger ever throws an unhandled exception, all records are marked with an error and no further processing takes place.

92

Triggers

Page 95: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Anonymous Blocks

An anonymous block is an Apex Code script that does not get stored in the metadata, but that can be compiled and executedthrough the use of the executeAnonymous() Apex Web Services API call:

ExecuteAnonymousResult executeAnonymous(String code)

You can use anonymous blocks to quickly evaluate Apex Code on the fly, such as in IDE immediate windows, or to writescripts that change dynamically at runtime. For example, you might write a client Web application that takes input from auser, such as a name and address, and then uses an anonymous block of Apex Code to insert a contact with that name andaddress into the database.

The content of an anonymous block (the code String that is passed into executeAnonymous()) can be any valid Apex Codescript, including any user-defined methods and exceptions. Note that while a user-defined method can refer to itself or latermethods without the need for forward declarations, variables cannot be referenced before their actual declaration. For example:

Integer i = 0;

void myProcedure1() { myProcedure2();}

void myProcedure2() { i++;}

myProcedure1();

The return result for executeAnonymous() includes:

• Status information for the compile and execute phases of the call, including any errors that occur• The debug log content, including the output of any calls to the System.debug() method (see The Debug Log on page

96)• The Apex Code stack trace of any uncaught script execution exceptions, including the package, method, and line number

for each call stack element

Note: Unlike packages and triggers, anonymous blocks are executed as the current user and can fail to compile if thescript violates the user's object- and field-level permissions.

For more information on executeAnonymous(), see "Web Services API Calls for Apex Code" in the Salesforce online help.

Invoking Apex Code in AJAX

The AJAX toolkit includes built-in support for invoking Apex Code through anonymous blocks or public WebServicemethods. To do so, include the following lines in your AJAX code:

<script src="/soap/ajax/8.0/connection.js" type="text/javascript"></script><script src="/soap/ajax/8.0/apex.js" type="text/javascript"></script>

Note: For AJAX buttons, use the alternate forms of these includes.

To invoke Apex Code, use one of the following two methods:

93

Anonymous Blocks

Page 96: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• Execute anonymously via sforce.apex.executeAnonymous (<script>).This method returns a result similar to theAPI's result type, but as a JavaScript structure.

• Use a package WSDL. For example, you can call the following Apex Code:

package myPackage { webService Id makeContact(String lastName, Account a) { Contact c = new Contact(LastName = lastName, AccountId = a.Id); insert c; commit; return c.id; }}

By using the following Javascript code:

var account = sforce.SObject("Account");var id = sforce.apex.execute("myPackage","makeContact", {a:"Smith", b:account});

To call a webService method with no parameters, use {} as the third parameter for sforce.apex.execute. For example,to call the following Apex Code:

package myPackage { webService String getContextUserName() { return UserInfo.getFirstName();}

Use the following JavaScript code:

var contextUser = sforce.apex.execute("myPackage", "getContextUserName", {});

Both examples result in native JavaScript values that represent the return type of the methods.

Use the following line to display a popup window with debugging information:

sforce.debug.trace=true;

94

Invoking Apex Code in AJAX

Page 97: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Chapter 7

Debugging Apex Code

Apex Code supports a number of facilities for debugging and testing code.Theseinclude:

In this chapter ...

• Debugging Apex Code API Calls• Detailed debug logs for all API calls that invoke Apex Code• The Debug Log• Support for the creation and execution of unit tests• Testing and Code Coverage• User-friendly error messages and stack traces for uncaught exceptions• Handling Uncaught Exceptions• Execution governors to prevent runaway scripts from monopolizing shared

resources• Execution Governors and Limits

• Profiles of performance information

95

Page 98: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Debugging Apex Code API Calls

All API calls that invoke Apex Code code support a debug facility that allows access to detailed information about the executionof the script, including any calls to System.debug(). A SOAP input header called DebuggingHeader allows you to set thelogging granularity according to the levels outlined in the table below.

DescriptionLog Level

Does not include any log messagesNONE

Includes only log messages generated by calls to System.debug()DEBUGONLY

Includes log messages generated by calls to System.debug() and every datamanipulation language (DML) statement or inline SOQL query

DB

Includes log messages generated by calls to System.debug(), every DML statementor inline SOQL query, and the entrance and exit of every user-defined method

PROFILE

The corresponding output header, DebuggingInfo, contains the resulting debug log. Alternatively, you can view the debuglog from the Apex Log console, available from within the application by clicking Apex Log in the navigation bar header.

Figure 4: The Apex Console

Note: It is currently not possible to access the debug log for triggers that are fired from:

• An import operation• An operation in Outlook Edition, Lotus Notes Edition, or Office Edition• An operation in Data Loader

To debug a trigger, execute it in your development environment.

The Debug Log

A debug log contains the following information from the Apex Code runtime engine:

• The stack trace of any uncaught Apex Code exception

96

Debugging Apex Code API Calls

Page 99: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• The statement log, containing the information specified by the Log Level parameter• The execution governor limits, including the amount of resources used and the total amount of resource allocation. Note

that if any resource uses more than half of the amount allocated, the log includes a warning and an email is sent to therelevant Apex Code developer saying that a limit is approaching.

• The variables that are in scope at the end of execution, including their sizes• Cumulative profiling information if the Profile log level was selected, including:

• Details about the slowest SOQL and DML statements• The number of Apex Code method calls• The total time that each method call needed for processing, in descending order

• The start and completion of any triggers, including their total resource usage• The start and completion of any test method

Testing and Code Coverage

To facilitate the development of robust, error-free code, Apex Code supports the creation and execution of unit tests. Unittests are package methods that verify whether a particular piece of code is working properly. Unit test methods take noarguments, commit no data to the database, and are flagged with the testMethod keyword in the method definition. Forexample:

package myPackage { private testMethod void myTest() { <code_block> }}

Good unit tests should do the following:

• Cover as many lines of code as possible, and, in the case of conditional logic (including ternary operators), execute eachbranch of code logic

• Complete successfully without throwing any exceptions, unless those errors are expected and caught in a try…catch block• Liberally make use of System.assert() methods to prove that code behaves properly• Exercise bulk trigger functionality

For example, the following test method was written for the sample quoting application discussed in Walking Through aSample Apex Code Application on page 10:

testMethod void testQuoteApp() { // To begin, the sample application first creates the necessary records // to test OpportunityLineItems: Pricebook2, Product2, and PricebookEntry // First it creates a product with a standard price Product2 p = new product2(name='x', color__c='c'); insert p; Pricebook2 stdPb = [select Id from Pricebook2 where isStandard=true limit 1]; insert new PricebookEntry(pricebook2id = stdPb.id, product2id = p.id, unitprice=1.0, isActive=true); // Next, it creates a new pricebook with an entry for this product Pricebook2 pb = new pricebook2(name='test'); insert pb; PricebookEntry pbe = new PricebookEntry(pricebook2id=pb.id, product2id=p.id, unitprice=1.0, isActive=true); insert pbe; // To test the first example from the sample application, the test // method creates an opportunity line item using the pricebook entry, // and then asserts that the Color field was correctly copied from the // product after record insertion. Opportunity o = new Opportunity(name='test', pricebook2id=pb.id,

97

Testing and Code Coverage

Page 100: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

stageName='Open', CloseDate=Date.newInstance(2006,10,10)); insert o; OpportunityLineItem oli = new OpportunityLineItem(opportunityid=o.id, pricebookentryid=pbe.id, unitprice=1.5, quantity=2); insert oli; System.assertEquals('c', [select color__c from opportunitylineitem where id = :oli.id].color__c); // To test the fifth example from the sample application, the test method // creates a primary quote and then asserts that its Primary field cannot // be deselected. The code uses the try...catch testing idiom to assert // that the error message is correct. Quote__c q = new Quote__c(opportunity__c = o.id, primary__c = true); insert q; // Can't mark it non-primary q.primary__c = false; try { update q; } catch (System.DmlException e) { System.assert(e.getMessage().contains('first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Primary quote cannot be marked non-primary: [Primary__c]'), e.getMessage()); System.assertEquals('Primary quote cannot be marked non-primary', e.getDmlMessage(0)); System.assertEquals('Primary__c', e.getDmlFields(0)[0]); } // To test the second and third examples from the sample application, the // test method asserts that the inserted quote has the proper quote line // data copied from the opportunity line item, and that the quote's total // value is properly calculated. System.assertEquals(1, [select count() from quoteline__c where quote__c = :q.id]); // Total on the quote should be correct System.assertEquals(3.0, [select total__c from quote__c where id = :q.id].total__c); // To test the fourth example from the sample application, the test // method asserts that the opportunity and quote cannot be deleted // since the quote is primary try { delete o; System.assert(false); } catch (System.DmlException e) { System.assert(e.getDmlMessage(0).indexOf('Cannot delete opportunity with a quote') > -1); } try { delete q; System.assert(false); } catch (System.DmlException e) { System.assert(e.getDmlMessage(0).indexOf('Primary quote cannot be deleted') > -1); } // The test method now creates a second quote, marks it primary, and // verifies that the first quote is no longer primary. Quote__c q2 = new Quote__c(opportunity__c = o.id, primary__c = true); insert q2; System.assert(![select primary__c from quote__c where id = :q.id].primary__c); // Finally, the test method performs DML operations on quote line // items to assert that the quote line item values are properly // recalculated when associated values change. QuoteLine__c qLine = new QuoteLine__c(quote__c = q.id, product__c = p.id, unitprice__c = 2.0, quantity__c = 2); insert qLine; System.assertEquals(7.0, [select total__c from quote__c

98

Testing and Code Coverage

Page 101: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

where id = :q.id].total__c); qLine.unitprice__c = 3.0; update qLine; System.assertEquals(9.0, [select total__c from quote__c where id = :q.id].total__c); delete qLine; System.assertEquals(3.0, [select total__c from quote__c where id = :q.id].total__c);

// Try a bulk line item operation insert new QuoteLine__C[]{qLine1, qLine1.clone()}; System.assertEquals(11.0, [select total__c from quote__c where id = :q.id].total__c);

// Test that updating the product master color and then updating the // quote colors works p.color__c = 'c2'; update p; updateColors(q.id); for (QuoteLine__c line : [select color__c from quoteLine__c where quote__c = :q.id]) { System.assertEquals('c2', line.color__c); }}

Running Unit Test Methods

To run sets of Apex Code unit tests, use an IDE, such as Eclipse with the Apex Code plug-in (seehttps://wiki.apexdevnet.com/index.php/Apex_Toolkit_for_Eclipse), or use the runTests() call from the Apex Web ServicesAPI:

RunTestsResult[] runTests(RunTestsRequest ri)

This call allows you to run all tests in all packages, all tests in a specific namespace, or all tests in a subset of packages in aspecific namespace, as specified in the RunTestsRequest object. It returns the total number of tests that ran, code coveragestatistics (described below), and error information for each failed test. For more information, see the WSDL located athttps://<your_salesforce_server>/services/wsdl/apex, where <your_salesforce_server> is equivalent tothe server on which your organization is located, such as na1.salesforce.com.

Code Coverage Statistics

When running unit tests, Apex Code automatically tracks the lines of code that are executed by unit tests (not including thetests themselves). When the runTests() API call returns, its results include both the total number of lines that could havebeen executed, as well as the number, line, and column positions of code that was not executed. In this way, a developer candetermine the test coverage percentage for a particular package or trigger.

Note: Conditional and ternary operators are not considered executed unless both the positive and negative branchesare executed.

Handling Uncaught Exceptions

If an Apex Code script has a bug or does not catch a script-level exception:

• The end user sees a simple explanation of the problem in the application interface. This error message includes the ApexCode stack trace.

99

Handling Uncaught Exceptions

Page 102: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

• The developer who wrote the code receives the error via email with the Apex Code stack trace and the customer's organizationand user id. No other customer data is returned with the report.

Execution Governors and Limits

Because Apex Code runs in a multi-tenant environment, the Apex Code runtime engine strictly enforces a number of limitsto ensure that runaway scripts do not monopolize shared resources. These limits, or governors, track and enforce the statisticsoutlined in the table below. If a script ever exceeds a limit, the associated governor issues a runtime exception that cannot behandled.

Table 24: Apex Code Script Execution Limits

RunTests†††Anonymous Blockor WSDL Method

TriggerLimit

100100020Total number of SOQL queries issued*

100100001000Total number of records retrieved through SOQL queries

2010020Total number of DML statements issued (insert, update,upsert, merge, or delete)

10010000100Total number of records processed as a result of DMLstatements

0200Total number of transaction control statements issued (commitor rollback)

n/a1000n/aTotal number of uncommitted records since the lasttransaction control statement

1000†1000†1000†Total number of executed script statements since the lastSOQL query or DML statement***

500000 bytes†1000000 bytes†100000 bytes†Total heap size

100100100Total stack depth for any Apex Code invocation that does notresult in additional triggers firing due to insert, update, ordelete statements††

161616Total stack depth for any Apex Code invocation thatrecursively fires triggers due to insert, update, or deletestatements††

320003200032000Total number of characters for a single String

n/a200n/aFor loop array batch size**

1000†1000†1000†Total number of elements in a single Array

1000†1000†1000†Total number of elements in a single Set

1000†1000†1000†Total number of elements in a single Map

* In a SOQL query with parent-child relationship sub-queries, each parent-child relationship counts as an additional query,and the row counts from those relationship queries contribute to the row counts of the overall script execution.

** For information on batching, see SOQL For Loops on page 47.

*** This statistic is tracked in order to prevent infinite script loops.

100

Execution Governors and Limits

Page 103: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

† These limits scale with trigger batch size as follows:

• For 1-40 records, the normal limits apply• For 41-80 records, two times the normal limits apply• For 81-120 records, three times the normal limits apply• For 121-160 records, four times the normal limits apply• For 161 or more records, five times the normal limits apply

†† Recursive Apex Code that does not fire any triggers with insert, update, or delete statements exists in a singleinvocation, with a single stack. Conversely, recursive Apex Code that fires a trigger spawns the trigger in a new Apex Codeinvocation, separate from the invocation of the code that caused it to fire. Because spawning a new invocation of Apex Codeis a more expensive operation than a recursive call in a single invocation, there are tighter restrictions on the stack depth ofthese types of recursive calls.

††† RunTests limits apply individually to each testMethod.

Use the Limits methods to determine the script execution limits for your code while it is running. For example, you can usethe getDMLStatements method to determine the number of DML statements that have already been called by your program,or the getLimitDMLStatements method to determine the total number of DML statements available to your code in thatcontext.

For more information, seeLimits Methods on page 61.

101

Execution Governors and Limits

Page 104: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Appendix

AWeb Services API Calls for Apex Code

This appendix details the Web services API executeanonymous call that is available by default for Apex Code.

For information on all other Web services API calls, including those that can be used to extend or implement any existing ApexCode IDEs, contact your salesforce.com representative.

executeanonymous

Executes a block of Apex Code.

Syntax

ExecuteAnonymousResult[] = sfdc.executeanonymous(string apexcode);

Usage

Use this call to execute an anonymous block of Apex Code. This call can be executed from AJAX.

This call supports the "DebuggingHeader" in the Salesforce online help and SessionHeader.

Arguments

DescriptionTypeName

A block of Apex Code.stringapexcode

Response

ExecuteAnonymousResult[]

ExecuteAnonymousResult

The executeanonymous call returns information about whether or not the compile and run of the code was successful.

An ExecuteAnonymousResult object has the following properties:

102

Page 105: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

DescriptionTypeName

If compiled is False, this field contains the column number of the point wherethe compile failed.

intcolumn

If compiled is False, this field contains a description of the problem thatcaused the compile to fail.

stringcompileProblem

If True, the code was successfully compiled. If False, the column, line, andcompileProblem fields are not null.

booleancompiled

If success is False, this field contains the exception message for the failure.stringexceptionMessage

If success is False, this field contains the stack trace for the failure.stringexceptionStackTrace

If compiled is False, this field contains the line number of the point wherethe compile failed.

intline

If True, the code was successfully executed. If False, the exceptionMessageand exceptionStackTrace values are not null.

booleansuccess

DebuggingHeader

Specifies that the response will contain the debug log in the return header, and specifies the level of detail in the debug header.

API Calls

executeanonymous

Fields

DescriptionTypeElement Name

Specifies the type of information returned in the debug log. Valid values include:None, DebugOnly, DB, and Profile. For more information about these levels,see Debugging Apex Code on page 95.

logtypedebugLevel

103

DebuggingHeader

Page 106: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Appendix

BReserved Keywords

The following table lists identifiers that are reserved for use as keywords and cannot be used otherwise:

Note: Keywords marked with an asterisk (*) are reserved for future use.

Table 28: Reserved Keywords

asany*andactivate*abstract*

breakbigdecimal*begin*autonomous*asc

cast*case*byte*bybulk

commitcollect*classchar*catch

deletedefault*convertcurrencycontinueconst*

enum*end*elsedodesc

finallyfalseextendsexport*exit*

group*goto*fromforfloat*

import*implements*ifhint*having*

into*interface*instanceof*insertinner*

last_weeklast_n_dayslast_monthlast_90_daysjoin*

loop*long*listlimitlike

next_monthnext_90_daysnewmergemap

nullsnullnotnext_weeknext_n_days

oronof*object*number*

privatepragma*parallel*packageouter*

returning*returnretrieve*publicprotected*

short*setselectsearch*rollback

synchronized*switch*super*staticsort*

this_month*this*then*testmethodsystem*

104

Page 107: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

tomorrowtolabeltodaythrowthis_week

type*trytruetriggertransaction*

webserviceusingupsertupdateundelete*

yesterdaywhilewherewhen*

Note that the following special keywords are allowed as identifiers:

• after• before• count• excludes• first• includes• last• order

105

Page 108: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Appendix

CQuoting App Sample Code

This appendix includes the complete sample code for the quoting application discussed in Apex Code Quick Start on page 9.

oppLineTrigger.apex

// This trigger assigns a value to the color__c custom field before opportunity // line items are saved to the database.trigger oppLineTrigger on OpportunityLineItem bulk (before insert) {

// Determine the distinct pricebook entries Set<Id> pbeIds = new Set<Id>(); for (OpportunityLineItem oli : Trigger.new) pbeIds.add(oli.pricebookentryid);

// Query the pricebook entries Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>( [select product2.color__c from pricebookentry where id in :pbeIds]);

// Now set the colors on the opportunity line items for (OpportunityLineItem oli : Trigger.new) oli.color__c = entries.get(oli.pricebookEntryId).product2.color__c; }

oppTrigger.apex

// This trigger prevents the deletion of any opportunity that has an // associated quote.trigger oppTrigger on Opportunity bulk (before delete) {

// Trigger.oldMap is a trigger context variable that maps Ids to every // opportunity that is about to be deleted. Use it in a SOQL query to // create a list of associated quotes. for (Quote__c q : [select opportunity__c from quote__c where opportunity__c in :Trigger.oldMap.keySet()]) {

// For every quote that is active, retrieve the related opportunity // from Trigger.oldMap and prevent it from being deleted by placing // an error message on the opportunity. Trigger.oldMap.get(q.opportunity__c).addError( 'Cannot delete opportunity with a quote'); }}

106

Page 109: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

quoteLineTrigger.apex

// This trigger updates the total price of a quote when a related quote line // item changes.trigger quoteLineTrigger on quoteLine__c bulk (before insert, before update, after insert, after update, after delete) {

// Trigger context variables like Trigger.isBefore and Trigger.isUpdate // allow a multi-condition trigger to execute Apex Code only when a // certain condition occurs. if (Trigger.isBefore) { for (quoteLine__c ql : Trigger.new) {

// If the trigger fires before quote line items are updated or // inserted, the TotalPrice__c field is updated on each item. // Note that this calculation could have also been implemented // with a formula field in the application. if (Trigger.isUpdate || Trigger.isInsert) { ql.totalprice__c = ql.unitprice__c * ql.quantity__c; } } } else {

// As we did in Example 1, use a set to make sure we have a list of all // the distinct quotes that we are modifying. This is the first step in a // common bulk processing idiom. Set<Id> quoteIds = new Set<Id>();

// Note the use of the ternary operator to get the correct size of the // lists and then the correct IDs for each quote--for the delete case, // the application uses the Trigger.old list variable, while for insert // and update, the application uses Trigger.new. for (Integer i = 0; i < (Trigger.isDelete ? Trigger.old.size() : Trigger.new.size()); i++) { quoteIds.add(Trigger.isDelete ? Trigger.old[i].quote__c : Trigger.new[i].quote__c); }

// Now as the second step in our bulk processing idiom, use the set to issue // a SOQL query and create a map of Ids to Quotes Map<Id, Quote__c> quotes = new Map<Id, Quote__c>( [select id, total__c from quote__c where id in :quoteIds]);

// For each quote line item in Trigger.old or Trigger.new, find the quoteId for (Integer i = 0; i < (Trigger.isDelete ? Trigger.old.size() : Trigger.new.size()); i++) { String quoteId = Trigger.isDelete ? Trigger.old[i].quote__c : Trigger.new[i].quote__c;

// If the trigger fires after a quote line item is updated or deleted // the total__c field on the parent quote needs to be updated. However, // if this trigger fires in the middle of inserting a quote (that is, if // we're working on the same quote that the util.copyLineItemsFromOpp // method is working on, we skip this logic here (see Example 2) if (quoteId == util.quoteId) continue;

// As the third step in our bulk processing idiom, get the parent quote // (which must be in the set we created above) quote__c q = quotes.get(quoteId);

// If the quote total does not yet have a value, the trigger first sets // it to zero. if (q.total__c == null) q.total__c = 0;

// If the quote line item is being inserted, the trigger

107

quoteLineTrigger.apex

Page 110: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// increments the total value of the quote if (Trigger.isInsert && Trigger.new[i].totalprice__c != null) { q.total__c += Trigger.new[i].totalprice__c; }

// If the quote line item is being updated, the trigger adds the new // line item total to the quote, and subtracts the old line item // total from the quote if (Trigger.isUpdate) { if (Trigger.new[i].totalprice__c != null) q.total__c += Trigger.new[i].totalprice__c; if (Trigger.old[i].totalprice__c != null) q.total__c -= Trigger.old[i].totalprice__c; }

// If the quote line item is being deleted, the trigger // decrements the total value of the quote if (Trigger.isDelete && Trigger.old[i].totalprice__c != null) { q.total__c -= Trigger.old[i].totalprice__c; } }

// For the fourth and final step of the bulk processing idiom, // update all quotes in bulk update quotes.values(); }}

quoteTrigger.apex

// This quote trigger has been augmented to prevent deletion of the // primary quote on an opportunity, as well as the value of the Primary // field for an existing quote. Note that the code that was included in // Example 2 is still included in this trigger. trigger quoteTrigger on quote__c bulk (after insert, after update, before update, before delete) { if (Trigger.isBefore) { if (Trigger.isUpdate) {

// The trigger first verifies that a primary quote is not // setting its Primary value to false. For each quote that // is being updated, the trigger gets a copy of the old // version and the new version. (Note that this is a common // bulk trigger technique for working with parallel new and // old lists.) for (Integer i = 0; i < Trigger.old.size(); i++) { Quote__c old = Trigger.old[i]; Quote__c nw = Trigger.new[i];

if (old.primary__c && !nw.primary__c) {

// A primary quote should only be set to non-primary if // the application is in the middle of a transaction // that switches the primary flag to another quote. // The next if statement tests that this condition is // not true by comparing the old quote's opportunityId // with the util package opportunityId variable (see // Example 5). if (old.opportunity__c != util.opportunityId) { nw.Primary__c.addError('Primary quote cannot be marked non-primary'); } } } }

108

quoteTrigger.apex

Page 111: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// Next the trigger verifies that a primary quote is not being deleted if (Trigger.isDelete) { for (Quote__c q : Trigger.old) {

// If a primary quote is being deleted, the trigger prevents // it with addError(). if (q.primary__c) { q.addError('Primary quote cannot be deleted'); } } } } else {

// When creating a new quote, copy the opp lineitems. Note this is an iterative // procedure at the moment, meaning that we will hit our governor limits if we // insert too many quotes at once. It is left as an exercise for the reader // to convert this to a truly bulk process if (Trigger.isInsert) { for (Quote__c q : Trigger.new) { util.copyLineItemsFromOpp(q); } }

// After inserts and updates, we must ensure that only one record is marked // as primary. To do so, we get all opportunities referenced by the quotes // in Trigger.new that attempt to be primary and set the other's primary flags // to false. Special care is taken for the case where two or more records // within this batch attempt to be primary for the same opportunity

//Used to hold quotes that are marked as primary List<Quote__c> primaries = new List<Quote__c>();

// Used to map the opportunity Id for which there is a quote attempting // to be primary to the corresponding Quote Map<Id, Id> opWithPrimary = new Map<Id, Id>();

// Used to hold the Ids of quotes that attempt to be primary // for the same opportunity Set<Id> badQuotes = new Set<Id>();

for (Integer i = 0; i < Trigger.new.size(); i++) { Quote__c nw = Trigger.new[i]; // If the new quote is marked as primary and was either just inserted // or was not the primary quote before this operation if (nw.primary__c && (Trigger.isInsert || !Trigger.old[i].primary__c)) { // If there already is a quote that attempts to be primary for // this quote's opportunity if (opWithPrimary.containsKey(nw.opportunity__c)) { // Then both quotes are bad, and should be remembered badQuotes.add(opWithPrimary.get(nw.opportunity__c)); badQuotes.add(nw.Id); } else { // The quote is good so far, add it to our list primaries.add(nw);

// Remember this quote's opportunity in case another quote // also wants to be primary for it opWithPrimary.put(nw.opportunity__c, nw.Id); } } }

// Mark the bad quotes as such for (Id bad : badQuotes) { Quote__c q = Trigger.newMap.get(bad); q.primary__c.AddError('More than one quote is attempting to be primary

109

quoteTrigger.apex

Page 112: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

for this opportunity: ' + q.opportunity__c); }

// Remove the bad quotes from our set of good ones // We'll do this by first ensuring there are no duplicates by copying Ids // into a set and then removing the bad quotes' Ids from that set Set<Id> primaryIds = new Set<Id>(); for (Quote__c q : primaries) primaryIds.add(q.Id);

primaryIds.removeAll(badQuotes);

// Now that we have a set of unique and good quote ids, we need to // get the corresponding Quote__c objects primaries.clear(); util.opportunityIds.clear(); for (Id primId : primaryIds) { Quote__c q = Trigger.newMap.get(primId); primaries.add(q); // You need to remember the opportunity ids we're setting a new // primary quote for across triggers, so the before update trigger // doesn't throw an error about no primary quote existing util.opportunityIds.add(q.opportunity__c); }

// The trigger makes a call to getOtherPrimaryQuotes() in the util package // and assigns the result to a list of quotes. Quote__c[] others = util.getOtherPrimaryQuotes(primaries);

// Then it sets the primary flag to false for all the returned quotes // and updates the list for (quote__c q : others) { q.primary__c = false; }

try { update others; } finally { util.opportunityIds.clear(); } }}

util.apex

package util { // Package variables can be used for communication between triggers public String quoteId; public String opportunityId;

// This package method returns the primary quotes for all opportunities // associated with the given quotes, other than the quote passed into the method. // If there is no other primary quote, the method returns null. public Quote__c[] getOtherPrimaryQuotes(List<Quote__c> qs) { // Retrieve the list of all opportunities referenced by the given quotes List<Id> ops = new List<Id>(); for(Quote__c q : qs) ops.add(q.opportunity__c);

// Now retrieve all quotes that reference the opportunities, // excluding the given quotes Quote__c[] others = [select id from quote__c where opportunity__c = :ops and id not in :qs and primary__c = true]; return others;

110

util.apex

Page 113: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

}

// This method moves opportunity line items to the given quote q. public void copyLineItemsFromOpp(Quote__c q) {

// We will modify and update this quote at the end, so we clone it // first since Trigger.new records cannot be modified in after triggers q = q.clone();

try {

// By setting the quoteId package variable, this method tells // the quoteLine trigger that it should disable itself during this // operation (the quoteLine trigger is described in Example 3) quoteId = q.id;

// Now the method creates an empty array of quote line items quoteline__c[] quoteitems = new quoteline__c[0];

// Next, it manually calculates the overall total for the quote // by iterating over an array of OpportunityLineItem records that // are returned from a SOQL query. The query selects the data from // opportunity line items that match the opportunity associated // with the quote. Double tot = 0; // The running total Integer i = 0; // Number the line items

for (opportunitylineitem oppline : [select pricebookentry.product2id, color__c, unitprice, quantity, totalprice from opportunitylineitem where opportunityid = :q.opportunity__c order by createddate]) {

i++;

// For each opportunity line item, the method // calculates the running total if (oppline.unitprice != null && oppline.quantity != null) tot += oppline.unitprice * oppline.quantity;

// And then it adds a new quote line item to the quoteitems, // array, initializing it with values. quoteitems.add( new quoteline__c( quote__c = q.id,

// The method uses the counter variable to number // the line items. Because the SOQL query ordered // them by the date they were created with an ORDER BY // clause, they will be numbered that way as well. name = String.valueOf(i),

// The method then uses the values for product, unit // price, quantity, total price, and color from the // opportunity line item. product__c = oppline.pricebookentry.product2id, unitprice__c = oppline.unitprice, quantity__c = oppline.quantity, totalprice__c = oppline.totalprice, color__c = oppline.color__c)); }

// The method adds the whole array of quote line items // to the database with a single insert statement. insert quoteitems;

111

util.apex

Page 114: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// And then it updates the quote's overall total q.total__c = tot; update q;

} finally {

// To clean up the working variable, the method resets quoteId // to null. quoteId = null; } }

// Set the colors on the line items equals to the master product catalog // colors, which may have changed void updateColors(Id qId) {

// First load the line items into memory QuoteLine__c[] lineItems = [select product__c from quoteLine__c where quote__c = :qId];

// Now find the distinct product2 Ids Set<Id> productIds = new Set<Id>(); for (QuoteLine__c line : lineItems) productIds.add(line.product__c);

// Now query all of those products at once. Id is always selected implicitly. // Note the use of IN Map<Id, Product2> products = new Map<Id, Product2>( [select color__c from product2 where id in :productIds]);

// Update the line items, using the Map we created above QuoteLine__c[] lineItemsToUpdate = new QuoteLine__c[0]; for (QuoteLine__c line : lineItems) { Product2 product = products.get(line.product__c); if (product != null && line.color__c != product.color__c) { line.color__c = product.color__c; lineItemsToUpdate.add(line); } } update lineItemsToUpdate; }

webService Proposal__c makeProposal(String id) { Proposal__c p = new Proposal__c(name = 'propose it', quote__c = id); insert p; commit; return p; }}

testMethod void testQuoteApp() {

// To begin, the sample application first creates the necessary records // to test OpportunityLineItems: Pricebook2, Product2, and PricebookEntry // First it creates a product with a standard price Product2 p = new product2(name='x', color__c='c'); insert p; Pricebook2 stdPb = [select Id from Pricebook2 where isStandard=true limit 1]; insert new PricebookEntry(pricebook2id = stdPb.id, product2id = p.id, unitprice=1.0, isActive=true);

// Next, it creates a new pricebook with an entry for this product Pricebook2 pb = new pricebook2(name='test'); insert pb; PricebookEntry pbe = new PricebookEntry(pricebook2id=pb.id, product2id=p.id, unitprice=1.0, isActive=true);

112

util.apex

Page 115: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

insert pbe;

// To test the first example from the sample application, the test // method creates an opportunity line item using the pricebook entry, // and then asserts that the Color field was correctly copied from the // product after record insertion. Opportunity o = new Opportunity(name='test', pricebook2id=pb.id, stageName='Open', CloseDate=Date.newInstance(2006,10,10)); insert o; OpportunityLineItem oli = new OpportunityLineItem(opportunityid=o.id, pricebookentryid=pbe.id, unitprice=1.5, quantity=2); insert oli; System.assertEquals('c', [select color__c from opportunitylineitem where id = :oli.id].color__c);

// To test the fifth example from the sample application, the test method // creates a primary quote and then asserts that its Primary field cannot // be deselected. The code uses the try...catch testing idiom to assert // that the error message is correct. Quote__c q = new Quote__c(opportunity__c = o.id, primary__c = true); insert q;

// Can't mark it non-primary q.primary__c = false; try { update q; } catch (System.DmlException e) { System.assert(e.getMessage().contains('first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Primary quote cannot be marked non-primary: [Primary__c]'), e.getMessage()); System.assertEquals('Primary quote cannot be marked non-primary', e.getDmlMessage(0)); System.assertEquals('Primary__c', e.getDmlFields(0)[0]); }

// To test the second and third examples from the sample application, the // test method asserts that the inserted quote has the proper quote line // data copied from the opportunity line item, and that the quote's total // value is properly calculated. System.assertEquals(1, [select count() from quoteline__c where quote__c = :q.id]);

// Total on the quote should be correct System.assertEquals(3.0, [select total__c from quote__c where id = :q.id].total__c);

// To test the fourth example from the sample application, the test // method asserts that the opportunity and quote cannot be deleted // since the quote is primary try { delete o; System.assert(false); } catch (System.DmlException e) { System.assert(e.getDmlMessage(0).indexOf('Cannot delete opportunity with a quote') > -1); } try { delete q; System.assert(false); } catch (System.DmlException e) { System.assert(e.getDmlMessage(0).indexOf('Primary quote cannot be deleted') > -1); }

113

util.apex

Page 116: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

// The test method now creates a second quote, marks it primary, and // verifies that the first quote is no longer primary. Quote__c q2 = new Quote__c(opportunity__c = o.id, primary__c = true); insert q2; System.assert(![select primary__c from quote__c where id = :q.id].primary__c);

// Finally, the test method performs DML operations on quote line // items to assert that the quote line item values are properly // recalculated when associated values change. QuoteLine__c qLine = new QuoteLine__c(quote__c = q.id, product__c = p.id, unitprice__c = 2.0, quantity__c = 2); insert qLine; System.assertEquals(7.0, [select total__c from quote__c where id = :q.id].total__c); qLine.unitprice__c = 3.0; update qLine; System.assertEquals(9.0, [select total__c from quote__c where id = :q.id].total__c); delete qLine; System.assertEquals(3.0, [select total__c from quote__c where id = :q.id].total__c);

// Try a bulk line item operation insert new QuoteLine__C[]{qLine1, qLine1.clone()}; System.assertEquals(11.0, [select total__c from quote__c where id = :q.id].total__c);

// Test that updating the product master color and then updating the // quote colors works p.color__c = 'c2'; update p; updateColors(q.id); for (QuoteLine__c line : [select color__c from quoteLine__c where quote__c = :q.id]) { System.assertEquals('c2', line.color__c); } }}

114

util.apex

Page 117: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

115

util.apex

Page 118: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Index

A

addError()triggers and 92

After triggers 86AJAX support 93Anonymous blocks 93AnyType data type 23Apex 106

AJAX support 93data types 23flow control 42methods 61reserved keywords 104Web services API calls

executeAnonymous() 93runTests() 99

Apex codedebugging 96

Apex CodeAPI calls 102how it works 7IDEs 10introduction 5limitations 8overview 6quick start 9sample application walk-through 10Web services API calls

custom 85when to use 8

Apex log console 96API calls, web services

custom 85executeAnonymous() 93runTests() 99

Arrays and lists 27Assignment statements 43

B

Batch size, SOQL query for loop 47Before triggers 86Binds 40Blocks 42Boolean data type 23Bulk copy

example 14Bulk processing and triggers 87, 89

C

Calculationexample 16

callsexecuteanonymous 102

Case sensitivity 30Character escape sequences 23Chunk size, SOQL query for loop 47Code coverage statistics 99Collection iteration for loops 47

Collectionsiterating 29

Comments 41commit statement 49Commit statements 56Compound expressions 32Constants 31Context variables, trigger 88Copy records code example 14Currency data type 23

D

Data Loaderdebugging triggers 96

Data modelsample application 10

Data types 23primitive 23SObject 24

Date data type 23Datetime data type 23Deadlocks, avoiding 49Debug log console 96Debugging 96

log 96Declaring variables 30Delete statements 54Developer Edition 10DML statements 49

exception handling 56Unsupported SObjects 55

Do-while loops 45Double data type 23

E

Escape sequences, character 23Exceptions 57

DML 56methods 60throw statements 57trigger 92types 57, 58uncaught 99user defined 59variables 58

executeanonymous call 102executeAnonymous() API call 93Execution governors 100Execution order, triggers and 91Expressions 31

extending SObject and list 32operators 32

F

Field valuescopying example 12

Field-level security and custom API calls 85 116

Index

Page 119: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Fieldsaccessing 25accessing through relationships 25that cannot be modified by triggers 92validating 26

Fields, SObjectdereferencing 38formula 38

Final keyword 31, 84For loops 46

list or set iteration 47SOQL query

locking 49traditional 46

FOR UPDATE keyword 49Foreign keys and SOQL queries 39Formula fields, dereferencing 38Functional tests 97

minimum coverage 99running 99

G

Governorslimit methods 66

Governors, execution 100

I

Id data type 23Identifiers, reserved 104IDEs 10If-else statements 44Import

debugging triggers 96In clause, SOQL query 40Inheritance of user-defined exceptions 59Initializers, static 84Inline SOQL queries

locking rows for 49returning a single record 38

Insert statements 50Integer data type 23isAfter trigger variable 88isBefore trigger variable 88isDelete trigger variable 88isInsert trigger variable 88isUpdate trigger variable 88IsValid field 83IsValid flag 90

K

Keywordsfinal 31, 84FOR UPDATE 49private 84public 84TestMethod 97WebService 85

Keywords, reserved 104

L

L-value expressions 31Limit clause, SOQL query 40Limitations, Apex Code 8

Limitsmethods 66

Limits, code execution 100List iteration for loops 47List size, SOQL query for loop 47Lists

about 26array notation 27defining 26expressions 32iterating 29SObject 27

Literal expressions 31Locking statements 49Log, debug 96Loops 44

do-while 45for

list or set iteration 47SOQL query

locking 49traditional 46

while 45Lotus Notes Edition

debugging triggers 96

M

Managed AppExchange packages 85Maps 28

creating from SObject arrays 29iterating 29

Merge statements 55triggers and 91

Method invoking statements 56Methods

exception 60limits 66map 28namespace prefixes and 86passing-by-reference 80recursive 80set 28SObject 26user-defined 80

N

Namespace prefixes 85precedence 86

Nested lists 26new trigger variable 88newMap trigger variable 88Not In clause, SOQL query 40

O

Object data types 24Objects

lists 27Office Edition

debugging triggers 96old trigger variable 88oldMap trigger variable 88Operators 32

precedence 37Order of trigger execution 91

117

Index

Page 120: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Outlook Editiondebugging triggers 96

P

Packages 83defining 83IsValid field 83keywords

final 84private 84public 84WebService 85

precedence 86static initializers 84syntax 83variables 84

Packages, managed AppExchange 85Parent-child relationships 31

SOQL queries and 39Passing-by-reference 80Permissions and custom API calls 85Person account triggers 91Polymorphic methods 80Polymorphism and custom API calls 85Precedence, operator 37Preventing saves

example 17Primitive data types 23Private keyword 84Processing, triggers and bulk 87Public keyword 84

Q

Queries, SOQL 31working with results 38

Quoting application code 106

R

Recursive methods 80Recursive triggers 86Relationships

accessing fields through 25rollback statement 49Rollback statements 56runTests() API call 99

S

S-Controls, when to use 8Sample application

business logic 12calculating fields 16copy 14copying field values 12data model 10one-and-only-one logic 19overview 10preventing saves 17testing 21tutorial 10

Security and custom API calls 85Set iteration for loops 47Sets 28

iterating 29

Sharing and custom API calls 85size trigger variable 88SOAP and polymorphism 85SObject data types 24SObjects

accessing fields through relationships 25dereferencing fields 38expressions 32fields 25formula fields 38lists 27that do not support DML statements 55validating 26

SOQL queries 31, 38Apex variables in 40for loops

locking 49foreign key 39large result lists 39parent-child relationship 39working with results 38

SOQL queries, inlinelocking rows for 49

Special characters 23Statements 42

assignment 43commit 56DML 49exception

DML 56methods 60try-catch-finally 57user-defined 59

execution limits 100if-else 44locking 49method invoking 56rollback 56transaction control 56

Static initialization code 83Static initializers 84Static package variables 84Statistics, code coverage 99String data type 23Syntax 30

case sensitivity 30comments 41

System architecture, Apex Code 7System namespace prefix 86System static methods

namespace prefixes and 86System validation 91

T

Testingexample 21

TestMethod keyword 97Tests 97

minimum coverage 99running 99

Throw statements 57Tokens, reserved 104Traditional for loops 46Transaction control statements 56

triggers and 87Trigger-ignoring operations 91 118

Index

Page 121: Apex Code Language Reference - s3. · PDF fileWhat is Apex Code? Apex Code is a procedur al scripting language that al lows developers to ex ecute flo w and tr ansactio n control statements

Triggers 86bulk exception handling 56bulk processing 87bulk queries 90common idioms 89context variables 88debugging 96defining

isValid flag 90exceptions 92execution order 91fields that cannot be modified 92maps and sets, using 90merge events and 91package variables and 84syntax 87transaction control 87transaction control statements 56

Try-catch-finally statements 57Tutorial

sample application 10Types 23

Primitive 23SObject 24

U

Uncaught exception handling 99Unit tests 97

minimum coverage 99running 99

Update statements 51

Upsert statements 52User-defined methods, Apex 80

V

Validating SObject and field names 26Validation, system 91Variables

declaring 30exception 58in SOQL queries 40precedence 86trigger context 88

W

Web services APIwhen to use 8

Web services API callscustom 85executeAnonymous() 93runTests() 99

WebService methods 85exposing data 85polymorphism 85

Where clause, SOQL query 40While loops 45Workflow 91WSDLs

polymorphism 85WSDLs, generating 85

119

Index