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

Commit

Permalink
Release 1.0
Browse files Browse the repository at this point in the history
* 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'
* 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)
* Updated README.md
* Setup Code Climate
* QueryBuilder.cls now has the ability to return all fields for the specified SObject type
  • Loading branch information
jongpie authored Jul 24, 2017
1 parent 9c0b0cb commit 44814ec
Show file tree
Hide file tree
Showing 44 changed files with 1,458 additions and 389 deletions.
9 changes: 6 additions & 3 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
engines:
apexmetrics:
enabled: true
enabled: true
config:
rulesets: "./tools/codeclimate/apex/apexunit.xml,./tools/codeclimate/apex/complexity.xml,./tools/codeclimate/apex/performance.xml,./tools/codeclimate/apex/security.xml,./tools/codeclimate/apex/style.xml"
enabled: true
ratings:
paths:
- "src/**.cls"
- "src/**.trigger"
- "**.cls"
- "**.trigger"
19 changes: 19 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Set the default line return behavior, in case people don't have core.autocrlf set.
* text=auto eol=lf

# Common git file types
.gitattributes text eol=lf
.gitignore text eol=lf
*.md text eol=lf

# Salesforce-specfic file types
*.app text eol=lf
*.cls text eol=lf
*.cmp text eol=lf
*.component text eol=lf
*.css text eol=lf
*.html text eol=lf
*.js text eol=lf
*.page text eol=lf
*.trigger text eol=lf
*.xml text eol=lf
7 changes: 3 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
language: node_js

node_js:
- "7"

script:
install:
- npm install -g jsforce-metadata-tools
- jsforce-deploy --dry-run -u $DEPLOYMENT_USERNAME -p $DEPLOYMENT_PASSWORD$DEPLOYMENT_TOKEN -D $TRAVIS_BUILD_DIR/src -l $DEPLOYMENT_LOGIN_URL --rollbackOnError true --testLevel $DEPLOYMENT_TEST_LEVEL --pollTimeout $POLL_TIMEOUT
script:
- jsforce-deploy --checkOnly -u $DEPLOYMENT_USERNAME -p $DEPLOYMENT_PASSWORD$DEPLOYMENT_TOKEN -D $TRAVIS_BUILD_DIR/src -l $DEPLOYMENT_LOGIN_URL --rollbackOnError true --testLevel $DEPLOYMENT_TEST_LEVEL --pollTimeout $POLL_TIMEOUT --pollInterval $POLL_INTERVAL--verbose
1 change: 0 additions & 1 deletion CNAME

This file was deleted.

54 changes: 45 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,46 @@
# Nebula Framework for Salesforce Apex
<a href="https://githubsfdeploy.herokuapp.com?owner=jongpie&repo=NebulaFramework">
<img alt="Deploy to Salesforce"src="https://raw.githubusercontent.com/afawcett/githubsfdeploy/master/src/main/webapp/resources/img/deploy.png">
</a>

## Branches
| Name | Build Status |
| -------- | -------- |
| master | <img src="https://travis-ci.org/jongpie/NebulaFramework.svg?branch=master"> |
| dev | <img src="https://travis-ci.org/jongpie/NebulaFramework.svg?branch=dev"> |
[![Deploy to Salesforce](https://img.shields.io/badge/salesforce-deploy-blue.svg)](https://githubsfdeploy.herokuapp.com)
[![License: MIT](https://img.shields.io/badge/license-MIT-d742f4.svg)](https://opensource.org/licenses/MIT)
[![Travis CI](https://img.shields.io/travis/jongpie/NebulaFramework/master.svg)](https://travis-ci.org/jongpie/NebulaFramework)
[![Code Climate](https://img.shields.io/codeclimate/github/jongpie/NebulaFramework.svg)](https://codeclimate.com/github/jongpie/NebulaFramework)

Nebula is a development framework for Salesforce's Apex language on the Force.com platform. It aims to...
1. Provide a foundation for Apex development, with the flexibility to be easily adapted to meet your implementation needs
2. Promote the design of scalable, bulkified code
3. Standardise how your code is written & organised
4. Overcome some gaps in Apex and the Force.com platform

## Features
Nebula focusses on streamlining how you work with SObjects
1. **SObjectRepository.cls** - this module handles all DML actions & querying needs for an SObject, making the implementation of SObjects much easier & faster
* **QueryBuilder.cls** powers Nebula's querying, allowing you to dynamically build reusable SOQL & SOSL queries
* **SObjectRepositoryMock.cls** can be used in unit tests for test-driven development (TDD) & to drastically reduce the time of your unit tests.
2. **SObjectTriggerHandler.cls** - this module provides a trigger framework to handle all trigger contexts provided by Salesforce, along with additional features like recursion prevention

The framework also provides several additional classes to make development easier
1. **SObjectRecordTypes.cls** - record types are an important feature of the Force.com platform. Unfortunately, Apex has limitations with handling them - record types have a field called DeveloperName that (you guessed it!) should be used by developers... but native Apex describe methods cannot access this field. Nebula tries to overcome this by providing cacheable query results of record types so you can access the DeveloperName.
2. **Logger.cls** - a flexible logging solution for Apex, leveraged by the framework itself
3. **Environment.cls** - provides information about the current Salesforce environment
4. **UUID.cls** - used to reate a randomly-generated unique ID in your code, using the Universally Unique Identifier (UUID) standard

## Usage
Nebula uses interfaces, virtual & abstract classes and some Salesforce features (like custom settings) to provide a baseline for your own Apex development. You can deploy the latest version of Nebula to your org and build your implementation on top of it. If you want to customise how Nebula works, most classes & methods can be overridden with your own logic. Ideally, you should minimise any code changes to Nebula's classes so that you can easily upgrade in the future when new versions of Nebula are released.

Nebula also leverages custom settings to give you control over how the framework works within your Salesforce environment. There are 4 settings
1. **Logger Settings (API Name: NebulaLoggerSettings__c)**
* Enable or disable logging
2. **Record Type Settings (API Name: NebulaRecordTypesSettings__c)**
* Choose how record types are cached
* Select if you want to include managed record types
3. **Repository Settings (API Name: NebulaRepositorySettings__c)**
* Automatically include common fields in your queries, like record ID, audit fields (CreatedById, CreatedDate, etc), Name field (or Subject field, where applicable) and more
4. **Trigger Handler Settings (API Name: NebulaTriggerHandlerSettings__c)**
* Easily disable all triggers & handlers (great for data migration and other admin tasks),
* Enable or disable recursion prevention

## Versioning
Releases are versioned using [Semantic Versioning](http://semver.org/) in the format 'v1.0.2' (MAJOR.MINOR.PATCH):

- MAJOR version when incompatible API changes are made
- MINOR version new functionality is added in a backwards-compatible manner
- PATCH version when backwards-compatible bug fixes are made
1 change: 0 additions & 1 deletion _config.yml

This file was deleted.

45 changes: 45 additions & 0 deletions src/classes/CollectionUtils.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*************************************************************************************************
* This file is part of the Nebula Framework project, released under the MIT License. *
* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
*************************************************************************************************/
public without sharing class CollectionUtils {

public static Boolean isCollection(Object input) {
return isList(input) || isSet(input) || isMap(input);
}

public static Boolean isList(Object input) {
// If we can cast the object to a list of objects, then it's a list
try {
Object convertedInput = (List<Object>)input;
return true;
} catch(System.TypeException ex) {
return false;
}
}

public static Boolean isSet(Object input) {
// We can't cast the object to a set of objects
// But if we try to cast it to a list of objects & it's a set,
// then a TypeException is thrown so we know it's a set
try {
Object convertedInput = (List<Object>)input;
return false;
} catch(System.TypeException ex) {
return ex.getMessage().contains('Set<');
}
}

public static Boolean isMap(Object input) {
// We can't cast the object to a map of objects
// But if we try to cast it to a list of objects & it's a map,
// then a TypeException is thrown so we know it's a map
try {
Object convertedInput = (List<Object>)input;
return false;
} catch(System.TypeException ex) {
return ex.getMessage().contains('Map<');
}
}

}
140 changes: 140 additions & 0 deletions src/classes/CollectionUtils_Tests.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*************************************************************************************************
* This file is part of the Nebula Framework project, released under the MIT License. *
* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
*************************************************************************************************/
@isTest
private class CollectionUtils_Tests {

// Tests for lists
@isTest
static void it_should_say_that_a_list_of_strings_is_a_list_and_a_collection() {
List<String> collectionToCheck = new List<String>{'A', 'B', 'C'};

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isSet(collectionToCheck));
System.assertEquals(false, CollectionUtils.isMap(collectionToCheck));
}

@isTest
static void it_should_say_that_a_list_of_integers_is_a_list_and_a_collection() {
List<Integer> collectionToCheck = new List<Integer>{1, 2, 3};

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isSet(collectionToCheck));
System.assertEquals(false, CollectionUtils.isMap(collectionToCheck));
}

@isTest
static void it_should_say_that_a_list_of_users_is_a_list_and_a_collection() {
List<User> collectionToCheck = [SELECT Id FROM User LIMIT 10];

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isSet(collectionToCheck));
System.assertEquals(false, CollectionUtils.isMap(collectionToCheck));
}

// Tests for sets
@isTest
static void it_should_say_that_a_set_of_strings_is_a_set_and_a_collection() {
Set<String> collectionToCheck = new Set<String>{'A', 'B', 'C'};

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isSet(collectionToCheck));
System.assertEquals(false, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isMap(collectionToCheck));
}

@isTest
static void it_should_say_that_a_set_of_integers_is_a_set_and_a_collection() {
Set<Integer> collectionToCheck = new Set<Integer>{1, 2, 3};

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isSet(collectionToCheck));
System.assertEquals(false, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isMap(collectionToCheck));
}

@isTest
static void it_should_say_that_a_set_of_users_is_a_set_and_a_collection() {
Set<User> collectionToCheck = new Set<User>([SELECT Id FROM User LIMIT 10]);

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isSet(collectionToCheck));
System.assertEquals(false, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isMap(collectionToCheck));
}

// Tests for maps
@isTest
static void it_should_say_that_a_map_of_strings_is_a_map_and_a_collection() {
Map<String, Integer> collectionToCheck = new Map<String, Integer>{
'First' => 1,
'Second' => 2,
'Third' => 3
};

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isMap(collectionToCheck));
System.assertEquals(false, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isSet(collectionToCheck));
}

@isTest
static void it_should_say_that_a_map_of_integers_is_a_map_and_a_collection() {
Map<Integer, String> collectionToCheck = new Map<Integer, String>{
1 => 'First',
2 => 'Second',
3 => 'Third'
};

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isMap(collectionToCheck));
System.assertEquals(false, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isSet(collectionToCheck));
}

@isTest
static void it_should_say_that_a_map_of_users_is_a_map_and_a_collection() {
Map<Id, User> collectionToCheck = new Map<Id, User>([SELECT Id FROM User LIMIT 10]);

System.assertEquals(true, CollectionUtils.isCollection(collectionToCheck));
System.assertEquals(true, CollectionUtils.isMap(collectionToCheck));
System.assertEquals(false, CollectionUtils.isList(collectionToCheck));
System.assertEquals(false, CollectionUtils.isSet(collectionToCheck));
}

// Negative tests
@isTest
static void it_should_say_that_a_string_is_not_collection() {
String valueToCheck = 'test string';

System.assertEquals(false, CollectionUtils.isCollection(valueToCheck));
System.assertEquals(false, CollectionUtils.isList(valueToCheck));
System.assertEquals(false, CollectionUtils.isSet(valueToCheck));
System.assertEquals(false, CollectionUtils.isMap(valueToCheck));
}

@isTest
static void it_should_say_that_an_integer_is_not_collection() {
Integer valueToCheck = 1;

System.assertEquals(false, CollectionUtils.isCollection(valueToCheck));
System.assertEquals(false, CollectionUtils.isList(valueToCheck));
System.assertEquals(false, CollectionUtils.isSet(valueToCheck));
System.assertEquals(false, CollectionUtils.isMap(valueToCheck));
}

@isTest
static void it_should_say_that_a_user_is_not_collection() {
User valueToCheck = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];

System.assertEquals(false, CollectionUtils.isCollection(valueToCheck));
System.assertEquals(false, CollectionUtils.isList(valueToCheck));
System.assertEquals(false, CollectionUtils.isSet(valueToCheck));
System.assertEquals(false, CollectionUtils.isMap(valueToCheck));
}

}
5 changes: 5 additions & 0 deletions src/classes/CollectionUtils_Tests.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>39.0</apiVersion>
<status>Active</status>
</ApexClass>
80 changes: 41 additions & 39 deletions src/classes/Environment.cls
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
/*************************************************************************************************
* This file is part of the Nebula Framework project, released under the MIT License. *
* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
*************************************************************************************************/
public class Environment {

public static String BaseUrl {
get {return URL.getSalesforceBaseUrl().toExternalForm();}
private set;
}

public static String InstanceName {
get {return organization.InstanceName;}
private set;
}

public static Boolean IsSandbox {
get {return organization.IsSandbox;}
private set;
}

public static String Name {
get {return organization.Name;}
private set;
}

public static String Type {
get {return organization.OrganizationType;}
private set;
}

private static Organization organization {
get {
if(organization == null) organization = [SELECT Id, InstanceName, IsSandbox, Name, OrganizationType FROM Organization];
return organization;
}
private set;
}

/*************************************************************************************************
* This file is part of the Nebula Framework project, released under the MIT License. *
* See LICENSE file or go to https://github.com/jongpie/NebulaFramework for full license details. *
*************************************************************************************************/
public without sharing class Environment {

private Environment() {}

public static String BaseUrl {
get {return URL.getSalesforceBaseUrl().toExternalForm();}
private set;
}

public static String InstanceName {
get {return organization.InstanceName;}
private set;
}

public static Boolean IsSandbox {
get {return organization.IsSandbox;}
private set;
}

public static String Name {
get {return organization.Name;}
private set;
}

public static String Type {
get {return organization.OrganizationType;}
private set;
}

private static Organization organization {
get {
if(organization == null) organization = [SELECT Id, InstanceName, IsSandbox, Name, OrganizationType FROM Organization];
return organization;
}
private set;
}

}
Loading

0 comments on commit 44814ec

Please sign in to comment.