[SalesForce] Optional parameter in apex (sending email with PDF)

I have Messaging.SingleEmailMessage method return type that requires several parameters when its called, the code is below;

public Messaging.SingleEmailMessage createEmailMessage(Id templateName, Id emailAddressId, Id targetObjectId, Id whatId, String accountManagerEmail, boolean accountManagerStatus, String accountOwnerEmail, boolean accountOwnerStatus, String country ){

        String ReplyToEmail;

        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

        mail.setTemplateId(templateName);  
        mail.setOrgWideEmailAddressId(emailAddressId);
        mail.setTargetObjectId(targetObjectId); 
        mail.setWhatId(whatId);
        mail.setFileAttachments(new Messaging.EmailFileAttachment[] {efa});

        IF(accountManagerEmail <> null && accountManagerStatus == TRUE)
            ReplyToEmail = accountManagerEmail;
        ELSE IF(accountOwnerEmail <> null && accountOwnerStatus == TRUE)
            ReplyToEmail = accountOwnerEmail;
        ELSE IF(country == 'ID')
            ReplyToEmail = defaultReplyEmailID; 
        ELSE IF(country == 'PH')
            ReplyToEmail = defaultReplyEmailPH; 
        ELSE
            ReplyToEmail = defaultReplyEmailMX;      
        mail.setReplyTo(ReplyToEmail); 

        return mail;      
    }

The only problem I have here is this method handles only SingleEmailMessage without PDF attached while I have 2 different methods that will call this function with 1 only sends out an regular email and the other method needs to set PDF as the attachment, what should I do to make my code more efficient here? do I need to write optional parameter which I'm not sure whether its possible or not?

This is a snippet of my method that requires PDF

 public void sendInvoiceReminderLimit(String selectCountry){
        String ReplyToEmail;

        country = selectCountry;
        this.setEmailTemplate(country);

/**** Set Template ****/

        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
        Set<Id> ids = new Set<Id>();

//some code here

                FOR(Invoice__c inv : linv){

                    /// Create the pdf for attachment ///

                    if(inv.Account__c == cont.AccountId && inv.ServicePeriodStartDate__c == inv.Account__r.Due_date_of_last_open_invoice__c){

                        PageReference BillPDF = new PageReference('/apex/InvoicePDF' + inv.Account__r.AccountCountry__c);
                        String pdfname = 'temp';

                        BillPDF.getParameters().put('id', inv.Id);
                        attach = new Attachment();
                        Blob attachbody;
                        try{
                            attachbody = BillPDF.getContentAsPDF();
                        } catch (VisualForceException e) {
                            attachbody = Blob.valueof(pdfname);
                            }

                        attach.Body = attachbody;
                        attach.Name = 'Invoice' + inv.InvoiceAutoNumber__c + '.pdf';
                        attach.IsPrivate = true;
                        attach.ParentId = parent.Id;
                        insert attach;

                        invPDFattachmemt = attach.Id;

                    /// Attach pdf to mail ///

                        Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment();
                        efa.setFileName(attach.Name);
                        efa.setBody(attach.Body);

                        mail = createEmailMessage(emailtemplate, orgWideMail.Id, cont.Id, cont.AccountId, cont.Account.AccountManager__r.Email, cont.Account.AccountManager__r.isActive, cont.Account.Owner.Email, cont.Account.Owner.isActive, cont.Account.AccountCountry__c); 

                        mails.add(mail);             

    }

I need to pass Messaging.Emailfileattachment efa = new Messaging.Emailfileattachment(); to my return type method when its called in the above method

Best Answer

Apex supports method overloading. You can define two versions of this method, which accept a different set of parameters. It's common for one of these versions to call through to the other, which contains the main body of the logic, while supplying default values for omitted parameters.

For example, you might define these two methods:

public Messaging.SingleEmailMessage createEmailMessage(Id templateName, Id emailAddressId, Id targetObjectId, Id whatId, String accountManagerEmail, boolean accountManagerStatus, String accountOwnerEmail, boolean accountOwnerStatus, String country ){

and

public Messaging.SingleEmailMessage createEmailMessage(Id templateName, Id emailAddressId, Id targetObjectId, Id whatId, String accountManagerEmail, boolean accountManagerStatus, String accountOwnerEmail, boolean accountOwnerStatus, String country, Messaging.Emailfileattachment attachment){

The former calls through to the latter, supplying all of its own parameters plus a null for the final parameter attachment. It's the responsibility of the latter method to handle any null values or placeholder values in its parameters as is appropriate for your business logic.

Your current implementation can be adapted by simply taking efa, which it refers to, as a parameter and appropriately handling the situation where efa is null to not add attachments. You can then choose to, if you wish, write another method that doesn't take an attachment parameter but which calls through to this one and supplies null.

As a note on style, one typically does not capitalize Apex keywords, such as if. You don't need to explicitly compare a Boolean to true; just evaluate it in a Boolean context (unless it might be null!)

It's also best practice to always use braces around if and else blocks.

    IF(accountManagerEmail <> null && accountManagerStatus == TRUE)
        ReplyToEmail = accountManagerEmail;
    ELSE IF(accountOwnerEmail <> null && accountOwnerStatus == TRUE)
        ReplyToEmail = accountOwnerEmail;

becomes

    if (accountManagerEmail <> null && accountManagerStatus) {
        ReplyToEmail = accountManagerEmail;
    } else if (accountOwnerEmail <> null && accountOwnerStatus) {
        ReplyToEmail = accountOwnerEmail;
    } // etc.