Skip to content

Instantly share code, notes, and snippets.

@bsutton
Created October 31, 2019 22:06
Show Gist options
  • Save bsutton/ba892873a94d9f6f3924436e9fcd1b42 to your computer and use it in GitHub Desktop.
Save bsutton/ba892873a94d9f6f3924436e9fcd1b42 to your computer and use it in GitHub Desktop.
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