package com.buschmais.xo.impl.cache; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import com.buschmais.xo.api.ValidationMode; import com.buschmais.xo.api.bootstrap.XOUnit; import com.buschmais.xo.impl.AbstractInstanceManager; import com.buschmais.xo.impl.SessionContext; import com.buschmais.xo.impl.instancelistener.InstanceListenerService; import com.buschmais.xo.spi.datastore.DatastorePropertyManager; import com.buschmais.xo.spi.datastore.DatastoreSession; public class CacheSynchronizationService<Entity, Relation> { private final SessionContext<?, Entity, ?, ?, ?, Relation, ?, ?, ?> sessionContext; private final XOUnit xoUnit; public CacheSynchronizationService(SessionContext<?, Entity, ?, ?, ?, Relation, ?, ?, ?> sessionContext, XOUnit xoUnit) { this.sessionContext = sessionContext; this.xoUnit = xoUnit; } public void flush() { DatastoreSession<?, Entity, ?, ?, ?, Relation, ?, ?, ?> datastoreSession = sessionContext.getDatastoreSession(); InstanceListenerService instanceListenerService = sessionContext.getInstanceListenerService(); flush(sessionContext.getRelationCache(), sessionContext.getRelationInstanceManager(), datastoreSession.getDatastoreRelationManager(), instanceListenerService); flush(sessionContext.getEntityCache(), sessionContext.getEntityInstanceManager(), datastoreSession.getDatastoreEntityManager(), instanceListenerService); } private <T> void flush(TransactionalCache<?> cache, AbstractInstanceManager<?, T> instanceManager, DatastorePropertyManager<T, ?> datastoreManager, InstanceListenerService instanceListenerService) { Collection<?> writtenInstances = cache.writtenInstances(); if (!writtenInstances.isEmpty()) { List<T> entities = new ArrayList<>(writtenInstances.size()); for (Object instance : writtenInstances) { T entity = instanceManager.getDatastoreType(instance); entities.add(entity); instanceListenerService.preUpdate(instance); validateInstance(instance); instanceListenerService.postUpdate(instance); } datastoreManager.flush(entities); cache.flush(); } } public void clear() { DatastoreSession<?, Entity, ?, ?, ?, Relation, ?, ?, ?> datastoreSession = sessionContext.getDatastoreSession(); clear(sessionContext.getRelationCache(), sessionContext.getRelationInstanceManager(), datastoreSession.getDatastoreRelationManager()); clear(sessionContext.getEntityCache(), sessionContext.getEntityInstanceManager(), datastoreSession.getDatastoreEntityManager()); } private <T> void clear(TransactionalCache<?> cache, AbstractInstanceManager<?, T> instanceManager, DatastorePropertyManager<T, ?> datastoreManager) { Collection<?> instances = cache.readInstances(); for (Object instance : instances) { T datastoreType = instanceManager.getDatastoreType(instance); if (datastoreType != null) { datastoreManager.afterCompletion(datastoreType, xoUnit.isClearAfterCompletion()); } } cache.clear(); } private void validateInstance(Object instance) { if (!ValidationMode.NONE.equals(xoUnit.getValidationMode())) { Set<ConstraintViolation<Object>> constraintViolations = sessionContext.getInstanceValidationService().validate(instance); if (!constraintViolations.isEmpty()) { throw new ConstraintViolationException(constraintViolations); } } } }