Skip to content

Commit

Permalink
Reworked the singleton nature of SobjectRegister
Browse files Browse the repository at this point in the history
Added test for it
  • Loading branch information
rob-baillie-ortoo committed Dec 3, 2021
1 parent 533b206 commit b9e86a5
Show file tree
Hide file tree
Showing 4 changed files with 409 additions and 103 deletions.
6 changes: 5 additions & 1 deletion TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ SObject Fabricator:
* Unit Test
* ortoo_FabricatedSObjectRegister
* sfab_FabricatedSObject
* Do an end to end test for the fabricator committing stuff
* Set unsettable fields, and a parent and child
* Make ortoo_FabricatedSObjectRegister a hidden singleton and remove the static nature from most of the methods
* Add defaulting mechanism

* Standards:
* Always use when creating objects for storing in the database
Expand All @@ -25,7 +29,7 @@ SObject Fabricator:
* Implement a 'defaultXxxx' for every mandatory lookup / master detail relationship
* Use the ObjectRegister to get one
* Every one constructed in this way should also have a parent class defined.
*

* Look at subclasses for specific objects
* Setting default values

Expand Down
Original file line number Diff line number Diff line change
@@ -1,105 +1,152 @@
public class ortoo_FabricatedSObjectRegister {

private static List<sfab_FabricatedSObject> objectRegister = new List<sfab_FabricatedSObject>();
private static List<Relationship> relationships = new List<Relationship>();
private static Map<sfab_FabricatedSObject,Sobject> sobjectsByFabricated;

private static DirectedGraph graph = new DirectedGraph();

public static void registerObject( sfab_FabricatedSObject objectToRegister )
{
objectRegister.add( objectToRegister );
graph.addNode( objectToRegister.getSobjectType() );
}

public static void registerChildOfRelationship( sfab_FabricatedSObject child, String relationship, sfab_FabricatedSObject parent )
{
relationships.add(
buildChildOfRelationship( child, relationship, parent )
);
}

public static void registerParentOfRelationship( sfab_FabricatedSObject parent, String relationship, sfab_FabricatedSObject child )
{
relationships.add(
buildParentOfRelationship( parent, relationship, child )
);
}

public static void persist()
{
// build all the sobjects, and key them on the fabricated version
sobjectsByFabricated = new Map<sfab_FabricatedSObject,Sobject>();
for ( sfab_FabricatedSObject thisFabricatedObject : objectRegister )
{
Sobject objectToStore = thisFabricatedObject.toPersistableSobject();
sobjectsByFabricated.put( thisFabricatedObject, objectToStore );
}

// work out the order to do things in, using the directed graph
List<Object> childToParentTypes = graph.generateSorted();

List<SobjectType> parentToChildTypes = new List<SobjectType>();
for( Integer i = childToParentTypes.size() - 1; i >= 0; i-- )
{
parentToChildTypes.add( (SobjectType)childToParentTypes[i] );
}

// register all the inserts
ortoo_SobjectUnitOfWork uow = new ortoo_SobjectUnitOfWork( parentToChildTypes );
for ( sfab_FabricatedSObject thisFabricatedObject : objectRegister )
{
uow.registerNew( sobjectsByFabricated.get( thisFabricatedObject ) );
}

// register all the relationships
for ( Relationship thisRelationship : relationships )
{
thisRelationship.register( uow );
}

uow.commitWork();
}

private void clearRegister()
{
objectRegister = new List<sfab_FabricatedSObject>();
relationships = new List<Relationship>();
sobjectsByFabricated = null;
}

private inherited sharing class Relationship
{
sfab_FabricatedSObject child;
sfab_FabricatedSObject parent;
SobjectField relationship;

public Relationship( sfab_FabricatedSObject child, SobjectField relationship, sfab_FabricatedSObject parent )
{
this.parent = parent;
this.relationship = relationship;
this.child = child;
graph.addRelationship( child.getSobjectType(), parent.getSobjectType() );
}

public void register( ortoo_SobjectUnitOfWork uow )
{
Sobject parentSobject = sobjectsByFabricated.get( parent );
Sobject childSobject = sobjectsByFabricated.get( child );

uow.registerRelationship( childSobject, relationship, parentSobject );
}
}

public static Relationship buildChildOfRelationship( sfab_FabricatedSObject child, String relationship, sfab_FabricatedSObject parent )
{
SobjectField relationshipField = new sfab_ObjectDescriber().getFieldForParentRelationship( child.getSobjectName(), relationship );
return new Relationship( child, relationshipField, parent );
}

public static Relationship buildParentOfRelationship( sfab_FabricatedSObject parent, String relationship, sfab_FabricatedSObject child )
{
SobjectField relationshipField = new sfab_ObjectDescriber().getFieldForChildRelationship( parent.getSobjectName(), relationship );
return new Relationship( child, relationshipField, parent );
}
public static void registerObject( sfab_FabricatedSObject objectToRegister )
{
instance.registerObject( objectToRegister );
}

public static void registerChildOfRelationship( sfab_FabricatedSObject child, String relationship, sfab_FabricatedSObject parent )
{
instance.registerChildOfRelationship( child, relationship, parent );
}

public static void registerParentOfRelationship( sfab_FabricatedSObject parent, String relationship, sfab_FabricatedSObject child )
{
instance.registerParentOfRelationship( parent, relationship, child );
}

public static void persist()
{
instance.persist();
}

@testVisible
private static RegisterInstance instance
{
get
{
if ( instance == null )
{
instance = new RegisterInstance();
}
return instance;
}
set;
}

@testVisible
private inherited sharing class RegisterInstance
{
private List<sfab_FabricatedSObject> objectRegister = new List<sfab_FabricatedSObject>();
private List<Relationship> relationships = new List<Relationship>();
private Map<sfab_FabricatedSObject,Sobject> sobjectsByFabricated;
private DirectedGraph graph = new DirectedGraph();

public void registerObject( sfab_FabricatedSObject objectToRegister )
{
objectRegister.add( objectToRegister );
graph.addNode( objectToRegister.getSobjectType() );
}

public void registerChildOfRelationship( sfab_FabricatedSObject child, String relationship, sfab_FabricatedSObject parent )
{
relationships.add(
buildChildOfRelationship( child, relationship, parent )
);
graph.addRelationship( child.getSobjectType(), parent.getSobjectType() );
}

public void registerParentOfRelationship( sfab_FabricatedSObject parent, String relationship, sfab_FabricatedSObject child )
{
relationships.add(
buildParentOfRelationship( parent, relationship, child )
);
graph.addRelationship( child.getSobjectType(), parent.getSobjectType() );
}

public void persist()
{
ortoo_SObjectUnitOfWork uow = (ortoo_SObjectUnitOfWork)Application.UNIT_OF_WORK.newInstance( getOrderOfInserts() );

buildObjectsByFabricated();
registerInserts( uow );
registerRelationships( uow );
uow.commitWork();
}

@testVisible
private List<SobjectType> getOrderOfInserts()
{
List<Object> childToParentTypes = graph.generateSorted();

List<SobjectType> parentToChildTypes = new List<SobjectType>();
for( Integer i = childToParentTypes.size() - 1; i >= 0; i-- )
{
parentToChildTypes.add( (SobjectType)childToParentTypes[i] );
}
return parentToChildTypes;
}

private void buildObjectsByFabricated()
{
sobjectsByFabricated = new Map<sfab_FabricatedSObject,Sobject>();
for ( sfab_FabricatedSObject thisFabricatedObject : objectRegister )
{
Sobject objectToStore = thisFabricatedObject.toPersistableSobject();
sobjectsByFabricated.put( thisFabricatedObject, objectToStore );
}
}

private void registerInserts( ortoo_SobjectUnitOfWork uow )
{
for ( sfab_FabricatedSObject thisFabricatedObject : objectRegister )
{
uow.registerNew( sobjectsByFabricated.get( thisFabricatedObject ) );
}
}

private void registerRelationships( ortoo_SobjectUnitOfWork uow )
{
for ( Relationship thisRelationship : relationships )
{
thisRelationship.register( uow, sobjectsByFabricated );
}
}
}

private inherited sharing class Relationship
{
sfab_FabricatedSObject child;
sfab_FabricatedSObject parent;
SobjectField relationship;

public Relationship( sfab_FabricatedSObject child, SobjectField relationship, sfab_FabricatedSObject parent )
{
this.parent = parent;
this.relationship = relationship;
this.child = child;
}

public void register( ortoo_SobjectUnitOfWork uow, Map<sfab_FabricatedSObject,Sobject> sobjectsByFabricated )
{
Sobject parentSobject = sobjectsByFabricated.get( parent );
Sobject childSobject = sobjectsByFabricated.get( child );

uow.registerRelationship( childSobject, relationship, parentSobject );
}
}

// Would be on Relationship if inner classes were allowed to have static methods
private static Relationship buildChildOfRelationship( sfab_FabricatedSObject child, String relationship, sfab_FabricatedSObject parent )
{
SobjectField relationshipField = new sfab_ObjectDescriber().getFieldForParentRelationship( child.getSobjectName(), relationship );
return new Relationship( child, relationshipField, parent );
}

// Would be on Relationship if inner classes were allowed to have static methods
private static Relationship buildParentOfRelationship( sfab_FabricatedSObject parent, String relationship, sfab_FabricatedSObject child )
{
SobjectField relationshipField = new sfab_ObjectDescriber().getFieldForChildRelationship( parent.getSobjectName(), relationship );
return new Relationship( child, relationshipField, parent );
}
}
Loading

0 comments on commit b9e86a5

Please sign in to comment.