Requirements of SObject wrappers

All SObjects must be wrapped so that interactions with SObjects are not directly exposed to external packages. This requires the creation of wrapper classes for every SObject that we need to access. There is a base wrapper class named WrapperBase, which contains the getInstance method and other helper methods. The getInstance method will auto check the CMT (Custom Metadata Type)  to see if there is an override, and it will instantiate based on that. When the getInstance method is called, the SObject provided is auto-mapped to the wrapper class via the Reflection class. The auto-mapping will take the API name of the SObject, convert it camel case, and assign that to the value in the wrapper class. For example:

EventApi__Thumbnail_Image_Url__c -> thumbnailImageUrl

Here is a how wrapper class should be written:

/*
 * -----------------------------------------------------------------------------
 * COPYRIGHT (C) 2018, FONTEVA, INC.
 * ALL RIGHTS RESERVED.
 *
 * ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS THE PROPERTY OF FONTEVA
 * INCORPORATED AND ITS SUPPLIERS, IF ANY. THE INTELLECTUAL AND TECHNICAL
 * CONCEPTS CONTAINED HEREIN ARE PROPRIETARY TO FONTEVA INCORPORATED AND
 * ITS SUPPLIERS AND MAY BE COVERED BY U.S. AND FOREIGN PATENTS, PATENTS IN
 * PROCESS, AND ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW. DISSEMINATION
 * OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL IS STRICTLY FORBIDDEN
 * UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED FROM FONTEVA, INC.
 * -----------------------------------------------------------------------------
 */
/**
 * Term wrapped object with camel case properties. Each properties maps to a field on the SObject that has _ for each
 * capital letter. Ex. (isActive -> Is_Active__c)
 */
global virtual inherited sharing class Term extends WrapperBase {

    @AuraEnabled
    global Id id;
    @AuraEnabled
    global String name;
    @AuraEnabled
    global Boolean isActive;
    @AuraEnabled
    global Date termStartDate;
    @AuraEnabled
    global Date termEndDate;
    @AuraEnabled
    global Id subscription;
    @AuraEnabled
    global Id subscriptionPlan;
    @AuraEnabled
    global Id contact;
    @AuraEnabled
    global Id account;
    @AuraEnabled
    global Id item;
    @AuraEnabled
    global Decimal assignmentsAllowed;
    @AuraEnabled
    global Decimal activeAssignments;
    @AuraEnabled
    global Date nextScheduledPaymentDate;
    @AuraEnabled
    global Boolean cancellationRequested;
    @AuraEnabled
    global List<SubscriptionLine> subscriptionLines = new List<SubscriptionLine>();
    @AuraEnabled
    global List<Assignment> assignments = new List<Assignment>();

    public static final String feature = 'Term';

    /**
     * Get base instance with no initial S0bject.
     *
     * @return Term
     */
    global static Term getInstance() {
        return (Term)getInstance(new OrderApi__Renewal__c());
    }

    /**
     * Get base instance with list of initial SObjects.
     *
     * @param terms List<OrderApi__Renewal__c>
     *
     * @return List<Term>
     */
    global static List<Term> getInstance(List<OrderApi__Renewal__c> terms) {
        return (List<Term>)WrapperBase.getInstanceHelper(MembershipConfiguration.MODULE_NAME, feature,Term.class.getName(),terms);
    }

    /**
     * Get base instance with an initial SObject.
     *
     * @param term OrderApi__Renewal__c
     *
     * @return Term
     */
    global static Term getInstance(OrderApi__Renewal__c term) {
        return (Term)WrapperBase.getInstanceHelper(MembershipConfiguration.MODULE_NAME, feature, Term.class.getName(), term);
    }

    /**
    * Term Constructor that should not be called directly.
    */
    global Term() {
    }

    public override void fromSObject(SObject termObj) {
    }

    public override SObject toSObject() {
        super.toSObject();
        this.subscriptionLines = new List<SubscriptionLine>();
        this.assignments = new List<Assignment>();
        return Reflect.mapTo(this,OrderApi__Renewal__c.class);
    }
}
JAVA

In the above code, the fromSObject will be auto-called during instantiation. This method will be used to map anything that the auto-mapping cannot do.

Each wrapper class should have a private final variable-named feature. This string variable is used to power the dependency injection overrides via CMTs.