Skip to content
This repository has been archived by the owner on Jun 3, 2024. It is now read-only.

Releases: jongpie/NebulaFramework

SFDX Metadata Conversion

24 Aug 06:15
2463936
Compare
Choose a tag to compare
Pre-release
  • Converted metadata to SFDX format
  • Arranged metadata into subfolders

Query Builder Enhancements

19 Sep 12:43
Compare
Choose a tag to compare
Pre-release
  • Add query caching in all query builder classes (#41)
    • New: ISObjectQueryBuilder.cacheResults();
    • New: IAggregateResultQueryBuilder.cacheResults();
    • New: ISearchQueryBuilderQueryBuilder.cacheResults();
  • Add support for Summer 17's new SOSL 'WITH HIGHLIGHT' and 'WITH SPELL_CORRECTION' features (#55)
    • New: ISearchQueryBuilderQueryBuilder.withHighlight(Boolean);
    • New: ISearchQueryBuilderQueryBuilder.withSpellCorrection(Boolean);
  • Add support for SOQL 'OFFSET', 'FOR REFERENCE' & 'FOR VIEW' features (#8)
    • Renamed: ISObjectQueryBuilder forUpdate(); - formally called setAsUpdate();
    • New: ISObjectQueryBuilder.offset(numberOfRowsToSkip);
    • New: ISObjectQueryBuilder forReference();
    • New: ISObjectQueryBuilder forView();
  • Upgraded all classes to API v40.0 (Summer '17 release)

New Query Builders

29 Aug 13:26
Compare
Choose a tag to compare
New Query Builders Pre-release
Pre-release

Query Builders

QueryBuilder.cls has been split into SObjectQueryBuilder.cls, AggregateResultQueryBuilder.cls and SearchQueryBuilder.cls

QueryBuilder.cls

  • QueryBuilder.cls is now an abstract class. It only contains protected methods for shared logic that is used by SObjectQueryBuilder.cls, AggregateQueryBuilder.cls and SearchQueryBuilder.cls. QueryBuilder.cls should not be used directly anymore.

SObjectQueryBuilder.cls

A new builder class that generates dynamic SOQL queries & returns a list of SObject

  • Several ways to add fields to your query:
    1. addFields(Schema.FieldSet fieldSet)
    2. addFields(List fields)
    3. addAllFields()
    4. addAllStandardFields()
    5. addAllCustomFields()
    6. addAllReadableFields()
    7. addAllEditableFields()

  • Name fields for lookups are automatically added to your query. For example, adding the contact object's field AccountId (a lookup to account):
    sobjectQueryBuilder.addField(Schema.Contact.AccountId)

    will result in your query having 2 fields added
    SELECT AccountId, Account.Name FROM Contact

  • New method for including children records

  • New method, getQueryLocator()

AggregateResultQueryBuilder.cls

A new builder class that generates dynamic SOQL queries & returns a list of AggregateResult

  • Several methods to add fields to group by
    1. groupBy(QueryDate queryDate);
    2. groupBy(Schema.FieldSet fieldSet);
    3. groupBy(Schema.SObjectField groupByField);
    4. groupBy(List<Schema.SObjectField> groupByFields);

  • Several aggregate methods - each method is overloaded to allow you to provide the string to use for a field alias
    1. avg(Schema.SObjectField sbojectField)
    2. count(Schema.SObjectField sbojectField)
    3. countDistinct(Schema.SObjectField sbojectField)
    4. max(Schema.SObjectField sbojectField)
    5. min(Schema.SObjectField sbojectField)
    6. sum(Schema.SObjectField sbojectField)

Since this is the first round of implementing the class, not all aggregate result features (like 'GROUP BY ROLLUP') have been implemented, but more will be added in the future.

SearchQueryBuilder.cls - generates SOSL queries

A new builder class that generates dynamic SOSL search queries & returns a list of a list of SObjects (that's not a typo, it's a list of lists)

  • Instances of ISObjectQueryBuilder can be used to determine which SObjects are returned in the results
// Scenario: Search leads and accounts for a specified search term

// Step 1: define your search term
String searchTerm = 'Acme';

// Step 2: create 1 SObjectQueryBuilder per SObject Type that you want to search. In this case, there is 1 for account, and 1 for lead
ISObjectQueryBuilder accountQuery = SObjectQueryBuilder(Schema.Account.SObjectType).filterBy(queryFilters));
ISObjectQueryBuilder leadQuery = SObjectQueryBuilder(Schema.Lead.SObjectType).filterBy(queryFilters));
List<ISObjectQueryBuilder> queryBuilders = new List<ISObjectQueryBuilder>{accountQuery, leadQuery};

// Step 3: Pass search term & the query builders for account & lead to SearchQueryBuilder
List<List<SObject>> searchResults = new SearchQueryBuilder(searchTerm, queryBuilders).getSearchResults();

QueryField.cls

  • Used to dynamically generate field string for SObject fields, including parent fields.
// Convert an SObjectField to a QueryField
QueryField qf = new QueryField(Schema.Account.Id);

// Convert a parent object's SObjectField to a QueryField
// This is the equivalent of 'contact.Account.CreatedBy.User.Profile.Name'
List<Schema.SObjectField> fieldChain = new List<Schema.SObjectField>{
    Schema.Contact.AccountId, Schema.Account.CreatedById, Schema.User.ProfileId, Schema.Profile.Name
};
QueryField parentField= new QueryField(fieldChain);

QueryFilter.cls

  • Completely changed the methods available to handle 3 filtering scenarios
    1. filterByField(QueryField queryField, QueryOperator operator, Object providedValue)
    2. filterByQueryDate(QueryDate queryDateToFilter, QueryOperator operator, Integer providedValue)
    3. filterBySubquery(QueryOperator inOrNotIn, Schema.SObjectField lookupFieldOnRelatedSObject)
    4. filterBySubquery(Schema.SObjectField lookupField, QueryOperator inOrNotIn, Schema.SObjectField lookupFieldOnRelatedSObject)
  • Added support for specifying 'AND' and 'OR' statements in a query. To use, provide a list of query filters that you want to be wrapped as a set of 'AND' or 'OR' statements to the corresponding method
    1. andFilterBy(List queryFilters)
    2. orFilterBy(List queryFilters)

QueryDate.cls

  • A new class that can be used in two ways
    1. Filter on a date/datetime field, using date functions
QueryDate qd = QueryDate.CALENDAR_MONTH(Schema.Lead.CreatedDate);
QueryFilter filter = new QueryFilter().filterByQueryDate(qd, QueryOperator.EQUALS, 3);
sobjectQueryBuilder.filterBy(filter);
System.assertEquals(filter.getValue(), 'CALENDAR_MONTH(CreatedDate) = 3');

// In SOQL, it would be written as
List<Lead> leads = [SELECT Id
FROM Lead
WHERE CALENDAR_MONTH(CreatedDate) = 3')];
  1. Group by a date function in an aggregate result
QueryDate qd = QueryDate.CALENDAR_MONTH(Schema.Lead.CreatedDate);
aggregateResultQueryBuilder.groupBy(qd);

// In SOQL, it would be written as
List<AggregateResult> results = [SELECT CALENDAR_MONTH(CreatedDate)
FROM Lead
GROUP BY CALENDAR_MONTH(CreatedDate)];

QueryFilterScope.cls

  • Added 3 new filter scope enums
    1. DELEGATED
    2. MY_TERRITORY - only works in orgs with territory management enabled
    3. MY_TEAM_TERRITORY - only works in orgs with territory management enabled

SObject Repository

DML.cls

  • All DML methods now return the corresponding list of database results - see IDML.cls. Previously, these were void methods. This change is inherited by SObjectRepository.cls as well (it extends DML.cls)

SObjectRepository.cls

  • The member variable sobjectRepository.Query has been removed. Each method now instead initializes an instance of SObjectQueryBuilder.cls
  • New member variable sobjectRepository.AggregateQuery, an instance of the new class AggregateResultQueryBuilder.cls - see 'Query Builders' section for more info

Record Types

SObjectRecordTypes.cls

  • Now requires the abstract method Schema.SObjectType getSObjectType() to be implemented

Settings

  • The custom setting NebulaRepositorySettings__c.object has been renamed to NebulaSObjectQueryBuilderSettings__c.object

Utilities

CollectionUtils.cls

  • Added 3 new methods for working with collections
    1. getLastItem
    2. pop
    3. splice

Environment.cls

  • New property, NamespacePrefix

Documentation

  • Started commenting classes & methods with ApexDoc. This will be an ongoing improvement.

First major release

24 Jul 08:22
Compare
Choose a tag to compare

New Features & Enhancements

  • New Scheduler.cls class to help simplify scheduling jobs

  • Created the interface ISObjectRecordTypes.cls

  • SObjectRepository.cls has a new constructor that will automatically add all fields to the query for the specified SObject type - essentially, it's 'select * from sobject'

    Sample code for the simplest implementation of an account repository:

    public class AccountRepository extends SObjectRepository {
        public AccountRepository() {
            // When only an SObject type is provided, all fields for the SObject are included in your queries
            super(Schema.Account.SObjectType);
        }
    }
    

Bugfixes

  • Fixed a bug related to using maps & sets as query parameters
  • Refactored some code based on Code Climate's initial analysis (mostly in QueryDateLiteral.cls & QueryOperator.cls)

Other

  • Updated README.md
  • Setup Code Climate

Added support for parent field filtering and including children queries

09 Jun 19:45
Compare
Choose a tag to compare

New Features & Enhancements

  • SObjectRepository.cls now uses QueryFilter.cls to handle filtering on fields from the base object, parent object and grandparent objects - the constructor used for QueryFilter.cls determines the type of filter
    Sample code for a filter to get accounts created by active users

    public class AccountRepository extends SObjectRepository {
        public AccountRepository() {
            // When only an SObject type is provided, all fields for the SObject are included in your queries
            super(Schema.Account.SObjectType);
        }
    
        public List<Account> getAccountsCreatedToday() {
            return (List<Account>)this.Query
                // Create an instance of QueryFilter to apply any filters to the query
                .filterBy(new QueryFilter(Schema.Account.Status, QueryOperator.EQUALS, QueryDateLiteral.TODAY))
                .getQueryResults();
        }
    }
    
  • Children queries can now be included in your queries generated by SObjectRepository.cls.

    Sample code showing a method that could be added to AccountRepository (not included in the repository):

    public class AccountRepository extends SObjectRepository {
        public AccountRepository() {
            // When only an SObject type is provided, all fields for the SObject are included in your queries
            super(Schema.Account.SObjectType);
        }
    
        public List<Account> getAccountsCreatedToday() {
            return (List<Account>)this.Query
                // Create an instance of QueryFilter to apply any filters to the query
                .filterBy(new QueryFilter(Schema.Account.Status, QueryOperator.EQUALS, QueryDateLiteral.TODAY))
                .getQueryResults();
        }
    
        public Account getAccountAndContactsWithEmails(Id accountId) {
            return (Account)this.Query
                .filterBy(new QueryFilter(Schema.Account.Id, QueryOperator.EQUALS, accountId))
                .includeChildrenRecords(
                    // Provide the child object's field that relates it to the parent object
                    Schema.Contact.AccountId,
                    // Filters for the children records can also be included
                    new ContactRepository().filterBy(new QueryFilter(Schema.Contact.Email, QueryOperator.NOT_EQUAL_TO, null))
                )
                .getFirstQueryResult();
        }
    }
    

Declarative/Configuration Changes

  • Logging is now enabled by default (via the custom setting NebulaLoggerSettings__c)
  • A custom app (cleverly called 'Nebula') has been added - it includes 1 tab for the NebulaLog__c object
  • Updated some field descriptions & help text on the various custom settings

Refactoring (Could Impact Existing Code)

  • SObjectRecordTypes.cls now uses QueryBuilder.cls for its query generation
  • QueryBuilder.whereField() method has been replaced by QueryBuilder.filterBy() - it expects either a single instance or a list of QueryFilter.cls
  • SObjectRepository.queryFactory is now SObjectRepository.Query
  • Miscellaneous cleanup - variable name standardisation, whitespace, etc
  • Removed the method ISObjectRepository.getCreatedSinceTimeValue
  • Delete CollectionUtils.cls
  • TestingUtils.setReadOnlyField() has been refactored to allow any object type as a value & to prevent duplicating fields on the returned SObject

Continuous Integration Setup & Code Cleanup

10 May 00:07
Compare
Choose a tag to compare

Tech debt release to get CI working, catch up on some unit tests, documentation, etc.

Refactoring (Could Impact Existing Code)

  • Changed NebulaSettings.cls to use static variables and methods
  • Changed Logger.cls to use static methods - everything now calls Logger directly
  • Renamed QueryUtils.cls to QueryArgumentFormatter.cls (and refactored it)
  • QueryBuilder.cls now uses QueryArgumentFormatter.cls
  • Fixed the ordering of the filter scopes to be in descending order (for readability)

Bugfixes

  • Fixed a problem with SObjectRecordTypes.cls when the object has no record types
  • Logger now checks the custom setting to see if it is enabled

Continuous Integration

  • Added .travis.yml for continuous integration. Passing unit tests with 75% code coverage is now required to approve a PR
  • Added Travis CI build badges to README.md

Unit Tests

  • Standardised the naming convention on a few test methods
  • Added more unit tests & test classes

Added support for 'USING SCOPE' in SOQL

15 Mar 07:15
Compare
Choose a tag to compare
Pre-release
  • New enum, QueryFilterScope, with values EVERYTHING, MINE, TEAM
  • IQueryBuilder now has the method IQueryBuilder usingScope(QueryFilterScope filterScope);
  • Fixed all methods in QueryBuilder & IQueryBuilder to return IQueryBuilder instead of QueryBuilder
  • Fixed NebulaSettings so it actually loads the custom settings

Initial Alpha Release

13 Mar 19:33
Compare
Choose a tag to compare
Initial Alpha Release Pre-release
Pre-release

Initial alpha release of the Apex framework for Salesforce development.