Objectory class
class Objectory{
String uri;
Function registerClassesCallback;
bool dropCollectionsOnStartup;
DataMapDecorator dataMapDecorator = (Map map) => map;
DataListDecorator dataListDecorator = (List list) => list;
final Map<String,BasePersistentObject> cache = new Map<String,BasePersistentObject>();
final Map<Type,FactoryMethod> _factories = new Map<Type,FactoryMethod>();
final Map<Type,FactoryMethod> _listFactories = new Map<Type,FactoryMethod>();
final Map<Type,ObjectoryCollection> _collections = new Map<Type,ObjectoryCollection>();
final Map<String,Type> _collectionNameToTypeMap = new Map<String,Type>();
bool useFieldLevelUpdate = true;
Objectory(this.uri,this.registerClassesCallback,this.dropCollectionsOnStartup);
void _addToCache(PersistentObject obj) {
cache[obj.id.toString()] = obj;
obj.markAsFetched();
}
Type getClassTypeByCollection(String collectionName) => _collectionNameToTypeMap[collectionName];
PersistentObject _findInCache(var id) {
if (id == null) {
return null;
}
return cache[id.toString()];
}
PersistentObject findInCacheOrGetProxy(var id, Type classType) {
if (id == null) {
return null;
}
PersistentObject result = _findInCache(id);
if (result == null) {
result = objectory.newInstance(classType);
result.id = id;
}
return result;
}
BasePersistentObject newInstance(Type classType){
if (_factories.containsKey(classType)){
return _factories[classType]();
}
throw new Exception('Class $classType have not been registered in Objectory');
}
PersistentObject dbRef2Object(DbRef dbRef) {
return findInCacheOrGetProxy(dbRef.id, objectory.getClassTypeByCollection(dbRef.collection));
}
BasePersistentObject map2Object(Type classType, Map map){
if (map == null) {
map = new LinkedHashMap();
}
var result = newInstance(classType);
result.map = map;
if (result is PersistentObject){
result.id = map["_id"];
}
if (result is PersistentObject) {
if (result.id != null) {
objectory._addToCache(result);
}
}
return result;
}
List createTypedList(Type classType) {
return _listFactories[classType]();
}
List<String> getCollections() => _collections.values.map((ObjectoryCollection oc) => oc.collectionName).toList();
Future save(PersistentObject persistentObject){
Future res;
if (persistentObject.id != null){
res = update(persistentObject);
}
else{
persistentObject.id = generateId();
persistentObject.map["_id"] = persistentObject.id;
objectory._addToCache(persistentObject);
res = insert(persistentObject);
}
persistentObject.dirtyFields.clear();
return res;
}
ObjectId generateId() => new ObjectId();
void registerClass(Type classType,FactoryMethod factory,[FactoryMethod listFactory]){
_factories[classType] = factory;
_listFactories[classType] = (listFactory==null ? ()=>new List<PersistentObject>() : listFactory);
BasePersistentObject obj = factory();
if (obj is PersistentObject) {
var collectionName = obj.collectionName;
_collectionNameToTypeMap[collectionName] = classType;
_collections[classType] = _createObjectoryCollection(classType,collectionName);
}
}
Future dropCollections() { throw new Exception('Must be implemented'); }
Future open() { throw new Exception('Must be implemented'); }
ObjectoryCollection constructCollection() => new ObjectoryCollection();
ObjectoryCollection _createObjectoryCollection(Type classType, String collectionName){
return constructCollection()
..classType = classType
..collectionName = collectionName;
}
Future insert(PersistentObject persistentObject) { throw new Exception('Must be implemented'); }
Future doUpdate(String collection, ObjectId id, Map toUpdate) { throw new Exception('Must be implemented'); }
Future remove(BasePersistentObject persistentObject) { throw new Exception('Must be implemented'); }
Future<Map> dropDb() { throw new Exception('Must be implemented'); }
Future<Map> wait() { throw new Exception('Must be implemented'); }
void close() { throw new Exception('Must be implemented'); }
Future<bool> initDomainModel() {
registerClassesCallback();
return open().then((_){
if (dropCollectionsOnStartup) {
return objectory.dropCollections();
}
});
}
Future update(PersistentObject persistentObject) {
var id = persistentObject.id;
if (id == null) {
return new Future.error(new Exception('Update operation on object with null id'));
}
Map toUpdate = _getMapForUpdateCommand(persistentObject);
if (toUpdate.isEmpty) {
return new Future.value({'ok': 1.0, 'warn': 'Update operation called without actual changes'});
}
return doUpdate(persistentObject.collectionName,id,toUpdate);
}
completeFindOne(Map map,Completer completer,ObjectoryQueryBuilder selector,Type classType) {
var obj;
if (map == null) {
completer.complete(null);
}
else {
obj = objectory.map2Object(classType,map);
if ((selector == null) || !selector.paramFetchLinks) {
completer.complete(obj);
} else {
obj.fetchLinks().then((_) {
completer.complete(obj);
});
}
}
}
Map _getMapForUpdateCommand(PersistentObject object) {
if (!useFieldLevelUpdate) {
return object.map;
}
var builder = modify;
for (var attr in object.dirtyFields) {
var root = object.map;
for (var field in attr.split('.')) {
root = root[field];
}
builder.set(attr, root);
}
return builder.map;
}
ObjectoryCollection operator[](Type classType) => _collections[classType];
}
Subclasses
ObjectoryDirectConnectionImpl, ObjectoryWebsocketBrowserImpl
Constructors
Properties
final Map<String, BasePersistentObject> cache #
final Map<String,BasePersistentObject> cache = new Map<String,BasePersistentObject>()
DataListDecorator dataListDecorator #
DataListDecorator dataListDecorator = (List list) => list
DataMapDecorator dataMapDecorator #
DataMapDecorator dataMapDecorator = (Map map) => map
Operators
ObjectoryCollection operator [](Type classType) #
ObjectoryCollection operator[](Type classType) => _collections[classType];
Methods
void close() #
void close() { throw new Exception('Must be implemented'); }
dynamic completeFindOne(Map map, Completer completer, ObjectoryQueryBuilder selector, Type classType) #
completeFindOne(Map map,Completer completer,ObjectoryQueryBuilder selector,Type classType) {
var obj;
if (map == null) {
completer.complete(null);
}
else {
obj = objectory.map2Object(classType,map);
if ((selector == null) || !selector.paramFetchLinks) {
completer.complete(obj);
} else {
obj.fetchLinks().then((_) {
completer.complete(obj);
});
}
}
}
ObjectoryCollection constructCollection() #
ObjectoryCollection constructCollection() => new ObjectoryCollection();
List createTypedList(Type classType) #
List createTypedList(Type classType) {
return _listFactories[classType]();
}
PersistentObject dbRef2Object(DbRef dbRef) #
PersistentObject dbRef2Object(DbRef dbRef) {
return findInCacheOrGetProxy(dbRef.id, objectory.getClassTypeByCollection(dbRef.collection));
}
Future doUpdate(String collection, ObjectId id, Map toUpdate) #
Future doUpdate(String collection, ObjectId id, Map toUpdate) { throw new Exception('Must be implemented'); }
PersistentObject findInCacheOrGetProxy(id, Type classType) #
PersistentObject findInCacheOrGetProxy(var id, Type classType) {
if (id == null) {
return null;
}
PersistentObject result = _findInCache(id);
if (result == null) {
result = objectory.newInstance(classType);
result.id = id;
}
return result;
}
Type getClassTypeByCollection(String collectionName) #
Type getClassTypeByCollection(String collectionName) => _collectionNameToTypeMap[collectionName];
List<String> getCollections() #
List<String> getCollections() => _collections.values.map((ObjectoryCollection oc) => oc.collectionName).toList();
Future<bool> initDomainModel() #
Future<bool> initDomainModel() {
registerClassesCallback();
return open().then((_){
if (dropCollectionsOnStartup) {
return objectory.dropCollections();
}
});
}
Future insert(PersistentObject persistentObject) #
Future insert(PersistentObject persistentObject) { throw new Exception('Must be implemented'); }
BasePersistentObject map2Object(Type classType, Map map) #
BasePersistentObject map2Object(Type classType, Map map){
if (map == null) {
map = new LinkedHashMap();
}
var result = newInstance(classType);
result.map = map;
if (result is PersistentObject){
result.id = map["_id"];
}
if (result is PersistentObject) {
if (result.id != null) {
objectory._addToCache(result);
}
}
return result;
}
BasePersistentObject newInstance(Type classType) #
BasePersistentObject newInstance(Type classType){
if (_factories.containsKey(classType)){
return _factories[classType]();
}
throw new Exception('Class $classType have not been registered in Objectory');
}
void registerClass(Type classType, FactoryMethod factory, [FactoryMethod listFactory]) #
void registerClass(Type classType,FactoryMethod factory,[FactoryMethod listFactory]){
_factories[classType] = factory;
_listFactories[classType] = (listFactory==null ? ()=>new List<PersistentObject>() : listFactory);
BasePersistentObject obj = factory();
if (obj is PersistentObject) {
var collectionName = obj.collectionName;
_collectionNameToTypeMap[collectionName] = classType;
_collections[classType] = _createObjectoryCollection(classType,collectionName);
}
}
Future remove(BasePersistentObject persistentObject) #
Future remove(BasePersistentObject persistentObject) { throw new Exception('Must be implemented'); }
Future save(PersistentObject persistentObject) #
Future save(PersistentObject persistentObject){
Future res;
if (persistentObject.id != null){
res = update(persistentObject);
}
else{
persistentObject.id = generateId();
persistentObject.map["_id"] = persistentObject.id;
objectory._addToCache(persistentObject);
res = insert(persistentObject);
}
persistentObject.dirtyFields.clear();
return res;
}
Future update(PersistentObject persistentObject) #
Future update(PersistentObject persistentObject) {
var id = persistentObject.id;
if (id == null) {
return new Future.error(new Exception('Update operation on object with null id'));
}
Map toUpdate = _getMapForUpdateCommand(persistentObject);
if (toUpdate.isEmpty) {
return new Future.value({'ok': 1.0, 'warn': 'Update operation called without actual changes'});
}
return doUpdate(persistentObject.collectionName,id,toUpdate);
}