Created
October 31, 2019 22:06
-
-
Save bsutton/ba892873a94d9f6f3924436e9fcd1b42 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class IdRef<E extends Entity> { | |
GUID guid; | |
// Once the entity has been resolved we cache it here. | |
E resolvedEntity; | |
/// Creates an IdRef from a guid. | |
/// | |
/// Calling [future] will trigger the process | |
/// to resolve the entity (i.e. do the network call) | |
IdRef.fromGUID(this.guid); | |
/// Creates an IdRef from an already resolved entity. | |
/// This is used when construction entities on the | |
/// client which are going to be sent to the server | |
/// or even just temporary entities. | |
IdRef(E entity) | |
: resolvedEntity = entity, | |
guid = entity.guid; | |
/// Returns a future to the entity | |
/// and starts the process of 'completing' | |
/// the future. | |
/// Essentially if required this will trigger | |
/// a network call to return the entity. | |
/// If the entity has already been [completed] | |
/// then the future will be complted immediately. | |
Future<E> get future { | |
Repository<E> repo = Repositories.of<E>(); | |
Future<E> future; | |
if (resolvedEntity == null) { | |
future = repo.getByGUID(guid); | |
future.then((resolved) => resolvedEntity = resolved); | |
} else { | |
future = Future.value(resolvedEntity); | |
} | |
return future; | |
} | |
/// | |
/// Returns the completed entity. | |
/// Note: it is illegal to call this method | |
/// if the entity is not already resolved [completed]. | |
/// An entity can be resolved in one of two ways: | |
/// 1) | |
/// The IdRef was created with a resolved entity by calling [IdRef(entity)]. | |
/// 2) | |
/// The IdRef was resolved by a call to [IdRef.future] and that future | |
/// has completed. | |
/// | |
/// You can call 'isResolved' to determine if the entity has been resolved. | |
E get entity { | |
if (resolvedEntity == null) { | |
throw UnresolvedEntityException(); | |
} | |
} | |
bool get isResolved => resolvedEntity != null; | |
/// completes the future on the IdRef's entity and | |
/// then executes the provided function against | |
/// the resolved entity. | |
/// This method is designed as a short cut | |
/// method of access fields of an entity wrapped | |
/// via an IdRef. | |
/// example: | |
/// ```dart | |
/// class Customer { | |
/// String name; | |
/// } | |
/// | |
/// IdRef<Customer> rCustomer; | |
/// | |
/// rCustomer.resolve((customer) => customer.name); | |
/// | |
/// ``` | |
/// | |
Future<R> resolve<R>(R Function(E entity) fn) { | |
Completer<R> completer = Completer(); | |
future.then((E entity) { | |
completer.complete(fn(entity)); | |
}); | |
return completer.future; | |
} | |
/// | |
/// This method is a short cut to getting | |
/// the [IdRef]'s future and then calling | |
/// [then()]. | |
/// example: | |
/// The long way | |
/// ```dart | |
/// ref.future.then((e) => fn()); | |
/// ``` | |
/// The short way | |
/// ```dart | |
/// ref.then((e) => fn()) | |
/// ``` | |
void then(void Function(E) fn) { | |
this.future.then((entity) => fn(entity)); | |
} | |
/// | |
/// This is a helper function which will resolve | |
/// every IdRef in the passed list. | |
/// Once this method returns you can access the entity | |
/// via [IdRef.entity] of each item in the list. | |
/// | |
static void resolveList<T extends Entity>(List<IdRef<T>> entities) async { | |
for (IdRef<T> entity in entities) { | |
await entity.future; | |
} | |
} | |
// IdRef<C> chain<C extends Entity>(IdRef<C> Function(E entity) fn) { | |
// return entity.then(()) | |
// // entity.then(()).resolve<IdRef<DIDPool>>((entity) => entity.pool); | |
// // return refPool.then((pool) => pool.resolve<Region>((pool) => pool.region)); | |
// } | |
} | |
class IdRefConverterCustomer extends IdRefConverter<Customer> { | |
const IdRefConverterCustomer(); | |
} | |
class IdRefConverter<T extends Entity> | |
implements JsonConverter<IdRef<T>, String> { | |
const IdRefConverter(); | |
@override | |
IdRef<T> fromJson(String json) { | |
return IdRef<T>.fromGUID(GUID(json)); | |
} | |
@override | |
String toJson(IdRef<T> idRef) { | |
return idRef == null ? null : idRef.guid.toString(); | |
} | |
} | |
class UnresolvedEntityException implements Exception { | |
UnresolvedEntityException(); | |
String toString() => | |
"You must resolve the entity before calling IdRef.entity"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment