package er.memoryadaptor; import com.webobjects.eoaccess.EOAttribute; import com.webobjects.eoaccess.EOEntity; import com.webobjects.foundation.NSMutableDictionary; import com.webobjects.foundation.NSMutableSet; import com.webobjects.foundation.NSNotification; import com.webobjects.foundation.NSNotificationCenter; import com.webobjects.foundation.NSSelector; import com.webobjects.foundation.NSSet; import com.webobjects.foundation._NSUtilities; import er.memoryadaptor.EREntityStore.JoinEntityStore; /** * EREntityStoreFactory is an factory class used for creating and managing EREntityStore * instances. * * @author q */ public class EREntityStoreFactory { private boolean _hasTransaction = false; private NSMutableDictionary<String, EREntityStore> _entityStores; private NSMutableDictionary<String, EREntityStore> _transactionEntityStores; private final Class<? extends EREntityStore> _entityStoreClazz; public static final String RESET_ALL_ENTITIES = "EREntityStoreResetAllEntities"; public EREntityStoreFactory(Class<? extends EREntityStore> clazz) { _entityStores = new NSMutableDictionary<>(); _entityStoreClazz = clazz; NSNotificationCenter.defaultCenter().addObserver(this, new NSSelector("resetAllEntities", new Class[] { NSNotification.class }), RESET_ALL_ENTITIES, null); } /** * Resets all the entities in this context, removing any known rows and * clearing out any transactions. */ public void resetAllEntities() { _entityStores.removeAllObjects(); if (_transactionEntityStores != null) { _transactionEntityStores.removeAllObjects(); } } /* This is to satisfy NSNotificationCenter */ public void resetAllEntities(NSNotification object) { resetAllEntities(); } /** * Resets the given entity, removing any known rows and * clearing out any transactions. This is the equivalent * deleting all rows in a relational database table. Be * careful using this if you use single table inheritance. * * @param entity the entity to reset */ public void resetEntity(EOEntity entity) { _entityStores.removeObjectForKey(entity); if (_transactionEntityStores != null) { _transactionEntityStores.removeObjectForKey(entity); } } /** * Returns an EREntityStore for the given entity. * * @param entity the entity to lookup * @return the datastore for the entity */ public EREntityStore _entityStoreForEntity(EOEntity entity) { return _entityStoreForEntity(entity, _hasTransaction); } /** * Returns an EREntityStore for the given entity. * * @param entity the entity to lookup * @param transactional if true, this will return a transactional view of the store * @return the datastore for the entity */ public EREntityStore _entityStoreForEntity(EOEntity entity, boolean transactional) { NSSet<EOEntity> relatedEntities = _relatedEntities(entity); EREntityStore store = _entityStoreForExternalName(_entityExternalName(entity), transactional); if (relatedEntities.count() > 0 && !(store instanceof JoinEntityStore)) { NSMutableDictionary<EOEntity, EREntityStore> stores = new NSMutableDictionary<>(new EREntityStore[] { store }, new EOEntity[] { entity }); for (EOEntity related : relatedEntities) { store = _entityStoreForExternalName(_entityExternalName(related), transactional); stores.setObjectForKey(store, related); } store = new ERJoinEntityStore(stores, entity); } return store; } private String _entityExternalName(EOEntity entity) { String externalName = entity.externalName(); if (externalName == null || externalName.trim().length() == 0){ externalName = entity.name(); } return externalName; } private EREntityStore _entityStoreForExternalName(String name, boolean transactional) { EREntityStore store = _entityStores.objectForKey(name); if (store == null) { store = (EREntityStore) _NSUtilities.instantiateObject(_entityStoreClazz, null, null, false, false); _entityStores.setObjectForKey(store, name); } if (transactional) { EREntityStore transactionStore = _transactionEntityStores.objectForKey(name); if (transactionStore == null) { transactionStore = store.transactionStore(); _transactionEntityStores.setObjectForKey(transactionStore, name); } store = transactionStore; } return store; } public void beginTransaction() { if (!_hasTransaction) { _hasTransaction = true; _transactionEntityStores = new NSMutableDictionary<>(); } } public void commitTransaction() { if (_hasTransaction) { _hasTransaction = false; for (String entityName : _transactionEntityStores.allKeys()) { EREntityStore transactionStore = _transactionEntityStores.objectForKey(entityName); EREntityStore entityStore = _entityStores.objectForKey(entityName); entityStore.commitFromTransactionStore(transactionStore); } _transactionEntityStores = null; } } public void rollbackTransaction() { if (_hasTransaction) { _hasTransaction = false; _transactionEntityStores = null; } } private NSSet<EOEntity> _relatedEntities(EOEntity entity) { NSMutableSet<EOEntity> entities = new NSMutableSet<>(); for (EOAttribute attrib : entity.attributesToFetch()) { if (attrib.isDerived()) { attrib = entity._attributeForPath(attrib.definition()); if (attrib != null) entities.add(attrib.entity()); } } // for (EORelationship rel : (NSArray<EORelationship>) entity._hiddenRelationships()) { // entities.add(rel.destinationEntity()); // } return entities; } }