View Javadoc
1   package de.japrost.jabudget.repository.inmemory;
2   
3   import java.util.*;
4   import java.util.stream.Collectors;
5   
6   import de.japrost.jabudget.domain.DomainException;
7   import de.japrost.jabudget.domain.DomainFailure;
8   import de.japrost.jabudget.domain.account.Account;
9   import de.japrost.jabudget.domain.account.Entry;
10  import de.japrost.jabudget.domain.account.EntryBuilder;
11  import de.japrost.jabudget.repository.AccountRepository;
12  
13  /**
14   * {@link AccountRepository} storing in memory without persistence. Mostly for test and development.<br>
15   * This implementation is not thread safe.
16   */
17  public class InMemoryAccountRepository implements AccountRepository {
18  
19  	private final Map<String, Account> storage = new HashMap<>();
20  	private final Map<String, Collection<Entry>> entryStorage = new HashMap<>();
21  
22  	/**
23  	 * {@inheritDoc}
24  	 * <p>
25  	 * <strong>This implementation</strong> stores and gives defensive copies of the given account.
26  	 */
27  	@Override
28  	public Account create(final Account account) throws DomainException {
29  		if (storage.containsKey(account.getId())) {
30  			throw new DomainException(DomainFailure.DUPLICATE_ENTITY);
31  		}
32  		return putInStoreDefensively(account);
33  	}
34  
35  	/**
36  	 * {@inheritDoc}
37  	 * <p>
38  	 * <strong>This implementation</strong> stores and gives defensive copies of the given account.
39  	 */
40  	@Override
41  	public Account update(final Account account) throws DomainException {
42  		if (!storage.containsKey(account.getId())) {
43  			throw new DomainException(DomainFailure.MISSING_ENTITY);
44  		}
45  		return putInStoreDefensively(account);
46  
47  	}
48  
49  	/**
50  	 * {@inheritDoc}
51  	 * <p>
52  	 * <strong>This implementation</strong> clears existing and adds defensive copies to store.
53  	 */
54  	@Override
55  	public void replaceAll(final Set<Account> accounts) {
56  		storage.clear();
57  		entryStorage.clear();
58  		accounts.forEach(this::putInStoreDefensively);
59  	}
60  
61  	private Account putInStoreDefensively(final Account account) {
62  		final Account accountToStore = new Account.Builder(account).build();
63  		storage.put(account.getId(), accountToStore);
64  		if (!entryStorage.containsKey(account.getId())) {
65  			entryStorage.put(account.getId(), new ArrayList<Entry>());
66  		}
67  		return new Account.Builder(account).build();
68  	}
69  
70  	/**
71  	 * {@inheritDoc}
72  	 * <p>
73  	 * <strong>This implementation</strong> gives a defensive copy of the stored accounts.
74  	 */
75  	@Override
76  	public Optional<Account> findById(final String id) {
77  		return Account.Builder.builder(storage.get(id)).buildOptional();
78  	}
79  
80  	/**
81  	 * {@inheritDoc}
82  	 * <p>
83  	 * <strong>This implementation</strong> gives defensive copies of all stored accounts.
84  	 */
85  	@Override
86  	public Set<Account> findAll() {
87  		return storage.values().stream().map(account -> new Account.Builder(account).build()).collect(Collectors.toSet());
88  	}
89  
90  	/**
91  	 * {@inheritDoc}
92  	 * <p>
93  	 * <strong>This implementation</strong> returns {@link Boolean#TRUE} always.
94  	 */
95  	@Override
96  	public Boolean delete(final String accountId) {
97  		storage.remove(accountId);
98  		entryStorage.remove(accountId);
99  		return Boolean.TRUE;
100 	}
101 
102 	@Override
103 	public Entry create(final Entry entry) throws DomainException {
104 		Collection<Entry> entries = entryStorage.get(entry.getAccountId());
105 		if (Objects.isNull(entries)) {
106 			throw new DomainException(DomainFailure.MISSING_ENTITY_REFERENCE);
107 		}
108 		if (entries.contains(entry)) {
109 			throw new DomainException(DomainFailure.DUPLICATE_ENTITY);
110 		}
111 		return putInStoreDefensively(entries, entry);
112 	}
113 
114 	private Entry putInStoreDefensively(final Collection<Entry> entries, final Entry value) {
115 		final Entry toStore = EntryBuilder.builder(value).build();
116 		entries.add(toStore);
117 		return EntryBuilder.builder(toStore).build();
118 	}
119 
120 }