package com.smartitengineering.cms.repo.dao.impl.tx; import com.google.inject.Inject; import com.google.inject.Singleton; import com.smartitengineering.cms.repo.dao.impl.AbstractRepositoryDomain; import com.smartitengineering.cms.repo.dao.tx.Transaction; import com.smartitengineering.cms.repo.dao.tx.TransactionManager; import com.smartitengineering.dao.common.CommonDao; import com.smartitengineering.dao.common.CommonReadDao; import com.smartitengineering.dao.common.CommonWriteDao; import com.smartitengineering.dao.common.queryparam.QueryParameter; import com.smartitengineering.domain.PersistentDTO; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; /** * Implements the Common CMS Content Repo Trasnactionable DAO. * @author imyousuf */ @Singleton public class CommonTxDao<T extends AbstractRepositoryDomain<? extends PersistentDTO>> implements CommonDao<T, String> { private final CommonReadDao<T, String> readDao; private final CommonWriteDao<T> writeDao; private final TransactionService txService; private final TransactionManager txManager; private final TransactionInMemoryCache memCache; private final Class<T> entityClass; @Inject public CommonTxDao(@Transactionable CommonReadDao<T, String> readDao, @Transactionable CommonWriteDao<T> writeDao, TransactionService txService, TransactionManager txManager, TransactionInMemoryCache memCache, Class<T> entityClass) { this.readDao = readDao; this.writeDao = writeDao; this.txService = txService; this.txManager = txManager; this.memCache = memCache; this.entityClass = entityClass; } public Set<T> getByIds(List<String> ids) { LinkedHashSet<T> set = new LinkedHashSet<T>(); if (ids != null) { for (String id : ids) { T dto = this.getById(id); set.add(dto); } } return set; } public T getById(String id) { if (isWithinTransaction()) { Transaction tx = txManager.getCurrentTransaction(); T txDto = null; Pair<TransactionStoreKey, TransactionStoreValue> pair; if (tx.isIsolatedTransaction()) { pair = memCache.getValueForIsolatedTransaction(tx.getId(), entityClass.getName(), id); } else { pair = memCache.getValueForNonIsolatedTransaction(entityClass.getName(), id); } // It means the value is either deleted earlier in the transaction or has to been saved. if (pair != null && (pair.getValue().getOpState() == null || OpState.DELETE.equals(pair.getValue().getOpState()))) { return null; } if (pair == null) { return this.readDao.getById(id); } else { txDto = pair.getValue().<T>getCurrentState(); return txDto; } } else { return this.readDao.getById(id); } } public T getSingle(QueryParameter... query) { return this.getSingle(Arrays.asList(query)); } public T getSingle(List<QueryParameter> query) { T dto = readDao.getSingle(query); if (isWithinTransaction()) { if (dto != null) { return this.getById(dto.getId()); } else { return null; } } else { return dto; } } public Set<T> getAll() { return this.readDao.getAll(); } public List<T> getList(List<QueryParameter> query) { return this.readDao.getList(query); } public <OtherTemplate> OtherTemplate getOther(List<QueryParameter> query) { return this.readDao.<OtherTemplate>getOther(query); } public <OtherTemplate> List<OtherTemplate> getOtherList(List<QueryParameter> query) { return this.readDao.<OtherTemplate>getOtherList(query); } public List<T> getList(QueryParameter... query) { return this.readDao.getList(query); } public <OtherTemplate> OtherTemplate getOther(QueryParameter... query) { return this.readDao.<OtherTemplate>getOther(query); } public <OtherTemplate> List<OtherTemplate> getOtherList(QueryParameter... query) { return this.readDao.<OtherTemplate>getOtherList(query); } public void save(T... states) { if (states == null) { return; } if (isWithinTransaction()) { for (T state : states) { this.txService.save(getTxElement(state)); } } else { this.writeDao.save(states); } } public void update(T... states) { if (states == null) { return; } if (isWithinTransaction()) { for (T state : states) { this.txService.update(getTxElement(state)); } } else { this.writeDao.update(states); } } public void delete(T... states) { if (states == null) { return; } if (isWithinTransaction()) { for (T state : states) { this.txService.delete(getTxElement(state)); } } else { this.writeDao.delete(states); } } private boolean isWithinTransaction() { return txManager.getCurrentTransaction() != null; } private TransactionElement<T> getTxElement(T dto) { Transaction tx = txManager.getCurrentTransaction(); if (tx == null) { return null; } TransactionElement<T> element = new TransactionElement<T>(); element.setDto(dto); element.setObjectType(dto.getClass()); element.setReadDao(readDao); element.setWriteDao(writeDao); element.setTxId(tx.getId()); return element; } }