Dart DocumentationdormEntityAssembler

EntityAssembler class

class EntityAssembler {
 
 //---------------------------------
 //
 // Private properties
 //
 //---------------------------------
 
 final List<EntityScan> _entityScans = <EntityScan>[];
 final List<DormProxy> _proxyRegistry = <DormProxy>[];
 final EntityKey _keyChain = new EntityKey();
 
 int _proxyCount = 0;
 
 //---------------------------------
 //
 // Singleton Constructor
 //
 //---------------------------------
 
 EntityAssembler._construct();
 
 //---------------------------------
 //
 // Factories
 //
 //---------------------------------
 
 static EntityAssembler _instance;

 factory EntityAssembler() {
   if (_instance == null) {
     _instance = new EntityAssembler._construct();
   }

   return _instance;
 }
 
 //---------------------------------
 //
 // Public methods
 //
 //---------------------------------
 
 EntityScan scan(Type forType, String refClassName, Function constructorMethod) {
   const Symbol entitySymbol = const Symbol('dorm.Entity');
   EntityScan scan = _getExistingScan(refClassName);
   
   if(scan != null) {
     return scan;
   }
   
   scan = new EntityScan()
   ..refClassName = refClassName
   ..contructorMethod = constructorMethod;
   
   ClassMirror classMirror = reflectClass(forType);
   
   Map<Symbol, Mirror> members = new Map<Symbol, Mirror>.from(classMirror.members);
   
   classMirror = classMirror.superclass;
   
   while (classMirror.qualifiedName != entitySymbol) {
     members.addAll(classMirror.members);
     
     classMirror = classMirror.superclass;
   }
   
   members.forEach(
     (Symbol symbol, Mirror mirror) {
       if (mirror is VariableMirror) {
         InstanceMirror instanceMirror;
         Property property;
         int i = mirror.metadata.length;
         int j;
         bool isIdentity;
         dynamic metatag;
         
         while (i > 0) {
           instanceMirror = mirror.metadata[--i];
           
           if (instanceMirror.reflectee is Property) {
             property = instanceMirror.reflectee as Property;
             
             isIdentity = false;
             
             j = mirror.metadata.length;
             
             while (j > 0) {
               metatag = mirror.metadata[--j].reflectee;
               
               scan.metadataCache.registerTagForProperty(property.property, metatag);
               
               if (metatag is Id) {
                 isIdentity = true;
               }
             }
             
             scan.addProxy(property, isIdentity);
           }
         }
       }
     }
   );
   
   _entityScans.add(scan);
   
   return scan;
 }
 
 void registerProxies(Entity entity, List<DormProxy> proxies) {
   _ProxyEntry entry;
   DormProxy proxy;
   
   if (entity._uid == null) {
     entity._uid = entity.hashCode;
     entity._scan = _getScanForInstance(entity);
   }
   
   EntityScan scan = entity._scan;
   List<_ProxyEntry> proxyEntryList = scan._proxies;
   int i = proxyEntryList.length;
   int j;
   
   while (i > 0) {
     entry = proxyEntryList[--i];
     
     j = proxies.length;
     
     while (j > 0) {
       proxy = proxies[--j];
       
       if (entry.property == proxy.property) {
         _PropertyMetadataCache propertyMetadataCache = scan.metadataCache.obtainTagForProperty(proxy.property);
         
         proxy.isId = propertyMetadataCache.isId;
         proxy.isTransient = propertyMetadataCache.isTransient;
         proxy.isNullable = propertyMetadataCache.isNullable;
         proxy.isLabelField = propertyMetadataCache.isLabelField;
         proxy.isMutable = (scan.isMutableEntity && propertyMetadataCache.isMutable);
         
         proxy._initialValue = propertyMetadataCache.initialValue;
         
         entry.proxy = proxy;
         
         entity._proxies.add(proxy);
         
         _proxyRegistry.add(proxy);
         
         proxies.remove(proxy);
         
         break;
       }
     }
   }
 }
 
 //---------------------------------
 //
 // Library protected methods
 //
 //---------------------------------
 
 EntityScan _getScanForInstance(Entity entity) {
   EntityScan scan = _getExistingScan(entity.refClassName);
   
   if(scan != null) {
     return new EntityScan.fromScan(scan, entity);
   }
   
   throw new DormError('Scan for entity not found');
 }
 
 Entity _assemble(Map<String, dynamic> rawData, OnConflictFunction onConflict) {
   final String refClassName = rawData[SerializationType.ENTITY_TYPE];
   EntityScan scan;
   Entity entity, returningEntity;
   List<_ProxyEntry> entityProxies;
   int i, j;
   
   if (onConflict == null) {
     onConflict = _handleConflictAcceptClient;
   }
   
   i = _entityScans.length;
   
   while (i > 0) {
     scan = _entityScans[--i];
     
     if (scan.refClassName == refClassName) {
       entity = scan.contructorMethod();
       
       entity.readExternal(rawData, onConflict);
       
       entity._scan.buildKey();
       
       returningEntity = _existingFromSpawnRegistry(refClassName, entity);
       
       if (!entity._isPointer) {
         entity = _registerSpawnedEntity(
             entity,
             returningEntity, 
             refClassName, onConflict
         );
         
         returningEntity = entity;
       } else if (returningEntity._isPointer) {
         _removeEntityProxies(entity);
         
         _proxyCount++;
       }
       
       return returningEntity;
     }
   }
   
   throw new DormError('Scan for entity not found');
   
   return null;
 }
 
 Entity _registerSpawnedEntity(Entity spawnee, Entity existingEntity, String refClassName, OnConflictFunction onConflict) {
   ConflictManager conflictManager;
   List<_ProxyEntry> entryProxies;
   List<_ProxyEntry> spawneeProxies;
   _ProxyEntry entryA, entryB;
   int i, j;
   
   if (spawnee != existingEntity) {
     if (onConflict == null) {
       throw new DormError('Conflict was detected, but no onConflict method is available');
     }
     
     conflictManager = onConflict(
         spawnee, 
         existingEntity
     );
     
     if (conflictManager == ConflictManager.ACCEPT_SERVER) {
       entryProxies = existingEntity._scan._proxies;
       
       i = entryProxies.length;
       
       while (i > 0) {
         entryA = entryProxies[--i];
         
         spawneeProxies = spawnee._scan._proxies;
         
         j = spawneeProxies.length;
         
         while (j > 0) {
           entryB = spawneeProxies[--j];
           
           if (entryA.property == entryB.property) {
             entryA.proxy._initialValue = existingEntity.notifyPropertyChange(entryA.proxy.propertySymbol, entryA.proxy._value, entryB.proxy._value);
             
             _proxyRegistry.remove(entryB.proxy);
             
             break;
           }
         }
       }
       
       _keyChain.remove(spawnee);
     } else if (conflictManager == ConflictManager.ACCEPT_CLIENT) {
       _removeEntityProxies(spawnee);
     }
     
     _swap(existingEntity, false);
   }
   
   if (!existingEntity._isRegistered) {
     existingEntity._isRegistered = true;
     
     existingEntity.changes.listen(existingEntity._identityKeyListener);
   }
   
   _swap(existingEntity, true);
   
   return existingEntity;
 }
 
 void _removeEntityProxies(Entity entity) {
   List<_ProxyEntry> proxies = entity._scan._proxies;
   int i = proxies.length;
   
   while (i > 0) {
     _proxyRegistry.remove(proxies[--i].proxy);
   }
   
   _keyChain.remove(entity);
 }
 
 void _swap(Entity actualEntity, bool swapPointers) {
   if (
       swapPointers &&
       (_proxyCount == 0)
   ) {
     return;
   }
   
   DormProxy proxy;
   int i = _proxyRegistry.length;
   
   while (i > 0) {
     proxy = _proxyRegistry[--i];
     
     if (proxy.owner != null) {
       proxy.owner.forEach(
           (dynamic entry) {
             if (
                 (entry is Entity) &&
                 _keyChain.areSameKeySignature(entry, actualEntity)
             ) {
               if (swapPointers) _proxyCount--;
               
               //_removeEntityProxies(entry);
               
               proxy.owner[proxy.owner.indexOf(entry)] = actualEntity;
             }
           }
       );
     } else if (
         (proxy._value is Entity) &&
         _keyChain.areSameKeySignature(proxy._value, actualEntity)
     ) {
       if (swapPointers) _proxyCount--;
       
       //_removeEntityProxies(proxy._value);
       
       proxy._initialValue = actualEntity;
     }
   }
 }
 
 Entity _existingFromSpawnRegistry(String refClassName, Entity entity) {
   Entity registeredEntity = _keyChain.getExistingEntity(entity);
   
   if (
       (registeredEntity != null) &&
       !registeredEntity._isPointer
   ) {
     return registeredEntity;
   }
   
   return entity;
 }
 
 EntityScan _getExistingScan(String refClassName) {
   EntityScan scan;
   int i = _entityScans.length;
   
   while (i > 0) {
     scan = _entityScans[--i];
     
     if (scan.refClassName == refClassName) {
       return scan;
     }
   }
   
   return null;
 }
 
 ConflictManager _handleConflictAcceptClient(Entity serverEntity, Entity clientEntity) {
   return ConflictManager.ACCEPT_CLIENT;
 }
}

Constructors

factory EntityAssembler() #

factory EntityAssembler() {
 if (_instance == null) {
   _instance = new EntityAssembler._construct();
 }

 return _instance;
}

Methods

void registerProxies(Entity entity, List<DormProxy> proxies) #

void registerProxies(Entity entity, List<DormProxy> proxies) {
 _ProxyEntry entry;
 DormProxy proxy;
 
 if (entity._uid == null) {
   entity._uid = entity.hashCode;
   entity._scan = _getScanForInstance(entity);
 }
 
 EntityScan scan = entity._scan;
 List<_ProxyEntry> proxyEntryList = scan._proxies;
 int i = proxyEntryList.length;
 int j;
 
 while (i > 0) {
   entry = proxyEntryList[--i];
   
   j = proxies.length;
   
   while (j > 0) {
     proxy = proxies[--j];
     
     if (entry.property == proxy.property) {
       _PropertyMetadataCache propertyMetadataCache = scan.metadataCache.obtainTagForProperty(proxy.property);
       
       proxy.isId = propertyMetadataCache.isId;
       proxy.isTransient = propertyMetadataCache.isTransient;
       proxy.isNullable = propertyMetadataCache.isNullable;
       proxy.isLabelField = propertyMetadataCache.isLabelField;
       proxy.isMutable = (scan.isMutableEntity && propertyMetadataCache.isMutable);
       
       proxy._initialValue = propertyMetadataCache.initialValue;
       
       entry.proxy = proxy;
       
       entity._proxies.add(proxy);
       
       _proxyRegistry.add(proxy);
       
       proxies.remove(proxy);
       
       break;
     }
   }
 }
}

EntityScan scan(Type forType, String refClassName, Function constructorMethod) #

EntityScan scan(Type forType, String refClassName, Function constructorMethod) {
 const Symbol entitySymbol = const Symbol('dorm.Entity');
 EntityScan scan = _getExistingScan(refClassName);
 
 if(scan != null) {
   return scan;
 }
 
 scan = new EntityScan()
 ..refClassName = refClassName
 ..contructorMethod = constructorMethod;
 
 ClassMirror classMirror = reflectClass(forType);
 
 Map<Symbol, Mirror> members = new Map<Symbol, Mirror>.from(classMirror.members);
 
 classMirror = classMirror.superclass;
 
 while (classMirror.qualifiedName != entitySymbol) {
   members.addAll(classMirror.members);
   
   classMirror = classMirror.superclass;
 }
 
 members.forEach(
   (Symbol symbol, Mirror mirror) {
     if (mirror is VariableMirror) {
       InstanceMirror instanceMirror;
       Property property;
       int i = mirror.metadata.length;
       int j;
       bool isIdentity;
       dynamic metatag;
       
       while (i > 0) {
         instanceMirror = mirror.metadata[--i];
         
         if (instanceMirror.reflectee is Property) {
           property = instanceMirror.reflectee as Property;
           
           isIdentity = false;
           
           j = mirror.metadata.length;
           
           while (j > 0) {
             metatag = mirror.metadata[--j].reflectee;
             
             scan.metadataCache.registerTagForProperty(property.property, metatag);
             
             if (metatag is Id) {
               isIdentity = true;
             }
           }
           
           scan.addProxy(property, isIdentity);
         }
       }
     }
   }
 );
 
 _entityScans.add(scan);
 
 return scan;
}