9

Document and Attachment share a lot of fields, so that they might be just views to the same "table". I'd like to use just those fields that both object types share in Apex code. Is there a superclass which can be used in code for Document and Attachment?

  • I wish! The other non existent superclass I lament is Custom_Object__Feed – Daniel Blackhall May 20 '13 at 0:06
12

Good observation and desire to encapsulate here. There is no common super class or interface to these objects already supplied in Apex. However this does not prevent you from creating one, there is two options I can imagine for this.

Dynamic Apex Method. You can access the fields indirectly via a feature known as Dynamic Apex, its simalar to reflection in other languages. Its not type safe, so depending on how complex the logic in your wrapper class is going to get you may want to consider the more OO way of doing below.

public class File
{
    public SObject Record { get; private set; }

    public Blob Body { 
        get { return (Blob) record.get('Body'); } 
        set { record.put('Body', value); } }

    public String ContentType { 
        get { return (String) record.get('ContentType'); } 
        set { record.put('ContentType', value); } }

    public File(SObject record)
    {
        if(record instanceof Document || record instanceof Attachment)
            this.Record = record;
        else
            throw new FileException('Unexpected SObject type, only Attachment and Document supported.');
    }

    public class FileException extends Exception { } 
}

Usage:

File file = new File(document);
file.Body = myBody;
File file = new File(attachment);
file.Body = myBody;

OO Method. Another approach is to create an abstract base class e.g. File and implement two subclasses for it Document and Attachment, providing a factory method on File. This depends on if you plan to put differing behaviour in the classes. Its more lines of code, but is more OO (get;set accessors as used in the above example cannot be abstract or virtual sadly).

public abstract class File
{
    public abstract SObject getRecord();
    public abstract Blob getBody();
    public abstract String getContentType();

    public static File make(SObject record)
    {
        if(record instanceof Document)
            return new File.DocumentImpl( (Document) record );
        else if(record instanceof Attachment)
            return new File.AttachmentImpl( (Attachment) record );
        throw new FileException('Unexpected SObject type, only Attachment and Document supported.');
    }

    private class DocumentImpl extends File
    {
         private Document document;
         public DocumentImpl(Document document) { this.document = document; }
         public override SObject getRecord() { return document; }
         public override Blob getBody() { return document.body; }
         public override String getContentType() { return document.contentType; }
    }

    private class AttachmentImpl extends File
    {
         private Attachment attachment;
         public AttachmentImpl(Attachment document) { this.attachment = attachment; }
         public override SObject getRecord() { return attachment; }
         public override Blob getBody() { return attachment.body; }
         public override String getContentType() { return attachment.contentType; }
    }

    public class FileException extends Exception { }
}

Usage

File myFile = File.make(myDocument);
Body body = myFile.getBody();

File myFile = File.make(myAttachment);
Body body = myFile.getBody();
  • All-encompassing and very thorough, great share Andy – bigassforce May 17 '13 at 12:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.