InMemoryAccountRepository.java

  1. package de.japrost.jabudget.repository.inmemory;

  2. import java.util.*;
  3. import java.util.stream.Collectors;

  4. import de.japrost.jabudget.domain.DomainException;
  5. import de.japrost.jabudget.domain.DomainFailure;
  6. import de.japrost.jabudget.domain.account.Account;
  7. import de.japrost.jabudget.domain.account.Entry;
  8. import de.japrost.jabudget.domain.account.EntryBuilder;
  9. import de.japrost.jabudget.repository.AccountRepository;

  10. /**
  11.  * {@link AccountRepository} storing in memory without persistence. Mostly for test and development.<br>
  12.  * This implementation is not thread safe.
  13.  */
  14. public class InMemoryAccountRepository implements AccountRepository {

  15.     private final Map<String, Account> storage = new HashMap<>();
  16.     private final Map<String, Collection<Entry>> entryStorage = new HashMap<>();

  17.     /**
  18.      * {@inheritDoc}
  19.      * <p>
  20.      * <strong>This implementation</strong> stores and gives defensive copies of the given account.
  21.      */
  22.     @Override
  23.     public Account create(final Account account) throws DomainException {
  24.         if (storage.containsKey(account.getId())) {
  25.             throw new DomainException(DomainFailure.DUPLICATE_ENTITY);
  26.         }
  27.         return putInStoreDefensively(account);
  28.     }

  29.     /**
  30.      * {@inheritDoc}
  31.      * <p>
  32.      * <strong>This implementation</strong> stores and gives defensive copies of the given account.
  33.      */
  34.     @Override
  35.     public Account update(final Account account) throws DomainException {
  36.         if (!storage.containsKey(account.getId())) {
  37.             throw new DomainException(DomainFailure.MISSING_ENTITY);
  38.         }
  39.         return putInStoreDefensively(account);

  40.     }

  41.     /**
  42.      * {@inheritDoc}
  43.      * <p>
  44.      * <strong>This implementation</strong> clears existing and adds defensive copies to store.
  45.      */
  46.     @Override
  47.     public void replaceAll(final Set<Account> accounts) {
  48.         storage.clear();
  49.         entryStorage.clear();
  50.         accounts.forEach(this::putInStoreDefensively);
  51.     }

  52.     private Account putInStoreDefensively(final Account account) {
  53.         final Account accountToStore = new Account.Builder(account).build();
  54.         storage.put(account.getId(), accountToStore);
  55.         if (!entryStorage.containsKey(account.getId())) {
  56.             entryStorage.put(account.getId(), new ArrayList<Entry>());
  57.         }
  58.         return new Account.Builder(account).build();
  59.     }

  60.     /**
  61.      * {@inheritDoc}
  62.      * <p>
  63.      * <strong>This implementation</strong> gives a defensive copy of the stored accounts.
  64.      */
  65.     @Override
  66.     public Optional<Account> findById(final String id) {
  67.         return Account.Builder.builder(storage.get(id)).buildOptional();
  68.     }

  69.     /**
  70.      * {@inheritDoc}
  71.      * <p>
  72.      * <strong>This implementation</strong> gives defensive copies of all stored accounts.
  73.      */
  74.     @Override
  75.     public Set<Account> findAll() {
  76.         return storage.values().stream().map(account -> new Account.Builder(account).build()).collect(Collectors.toSet());
  77.     }

  78.     /**
  79.      * {@inheritDoc}
  80.      * <p>
  81.      * <strong>This implementation</strong> returns {@link Boolean#TRUE} always.
  82.      */
  83.     @Override
  84.     public Boolean delete(final String accountId) {
  85.         storage.remove(accountId);
  86.         entryStorage.remove(accountId);
  87.         return Boolean.TRUE;
  88.     }

  89.     @Override
  90.     public Entry create(final Entry entry) throws DomainException {
  91.         Collection<Entry> entries = entryStorage.get(entry.getAccountId());
  92.         if (Objects.isNull(entries)) {
  93.             throw new DomainException(DomainFailure.MISSING_ENTITY_REFERENCE);
  94.         }
  95.         if (entries.contains(entry)) {
  96.             throw new DomainException(DomainFailure.DUPLICATE_ENTITY);
  97.         }
  98.         return putInStoreDefensively(entries, entry);
  99.     }

  100.     private Entry putInStoreDefensively(final Collection<Entry> entries, final Entry value) {
  101.         final Entry toStore = EntryBuilder.builder(value).build();
  102.         entries.add(toStore);
  103.         return EntryBuilder.builder(toStore).build();
  104.     }

  105. }