1 package com.guinetik.hexafun.hexa;
2
3 import java.nio.file.DirectoryStream.Filter;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.function.Function;
9 import java.util.stream.Collectors;
10
11 import com.guinetik.hexafun.fun.Result;
12
13
14
15
16
17
18
19 public class InMemoryHexaRepo<T> implements HexaRepo<T> {
20
21 private final Map<String, T> storage = new HashMap<>();
22 private final Function<T, String> idExtractor;
23 private final Function<T, T> idGenerator;
24
25
26
27
28
29
30
31 public InMemoryHexaRepo(Function<T, String> idExtractor, Function<T, T> idGenerator) {
32 this.idExtractor = idExtractor;
33 this.idGenerator = idGenerator;
34 }
35
36
37
38
39
40
41
42
43 public InMemoryHexaRepo(Function<T, String> idExtractor) {
44 this.idExtractor = idExtractor;
45 this.idGenerator = entity -> {
46
47
48
49 return entity;
50 };
51 }
52
53
54
55
56
57
58 public InMemoryHexaRepo() {
59 this.idExtractor = entity -> {
60 for (Map.Entry<String, T> entry : storage.entrySet()) {
61 if (entry.getValue().equals(entity)) {
62 return entry.getKey();
63 }
64 }
65 return String.valueOf(storage.size() + 1);
66 };
67 this.idGenerator = entity -> entity;
68 }
69
70
71
72
73
74 @Override
75 public Result<T> save(T entity) {
76 try {
77 String id = idExtractor.apply(entity);
78
79
80 if (id == null || id.isEmpty()) {
81 entity = idGenerator.apply(entity);
82 id = idExtractor.apply(entity);
83 }
84
85 storage.put(id, entity);
86 return Result.ok(entity);
87 } catch (Exception e) {
88 return Result.fail("Failed to save entity: " + e.getMessage());
89 }
90 }
91
92 @Override
93 public Result<List<T>> saveAll(List<T> entities) {
94 try {
95 List<T> savedEntities = new ArrayList<>();
96 for (T entity : entities) {
97 Result<T> result = save(entity);
98 if (result.isFailure()) {
99 return Result.fail("Failed to save entities: " + result.error());
100 }
101 savedEntities.add(result.get());
102 }
103 return Result.ok(savedEntities);
104 } catch (Exception e) {
105 return Result.fail("Failed to save entities: " + e.getMessage());
106 }
107 }
108
109
110
111
112
113 @Override
114 public Result<T> findById(String id) {
115 if (id == null || id.isEmpty()) {
116 return Result.fail("ID cannot be null or empty");
117 }
118
119 T entity = storage.get(id);
120 if (entity == null) {
121 return Result.fail("Entity not found with ID: " + id);
122 }
123
124 return Result.ok(entity);
125 }
126
127 @Override
128 public Result<List<T>> findAll() {
129 return Result.ok(new ArrayList<>(storage.values()));
130 }
131
132 @Override
133 public Result<List<T>> findBy(Filter<T> filter) {
134 try {
135
136
137 List<T> result = storage.values().stream()
138 .filter(entity -> {
139 try {
140 return filter.accept(entity);
141 } catch (Exception e) {
142 return false;
143 }
144 })
145 .collect(Collectors.toList());
146
147 return Result.ok(result);
148 } catch (Exception e) {
149 return Result.fail("Failed to filter entities: " + e.getMessage());
150 }
151 }
152
153 @Override
154 public Result<List<T>> findAll(int offset, int limit) {
155 if (offset < 0) {
156 return Result.fail("Offset cannot be negative");
157 }
158 if (limit < 0) {
159 return Result.fail("Limit cannot be negative");
160 }
161
162 List<T> allEntities = new ArrayList<>(storage.values());
163 int fromIndex = Math.min(offset, allEntities.size());
164 int toIndex = Math.min(offset + limit, allEntities.size());
165
166 return Result.ok(allEntities.subList(fromIndex, toIndex));
167 }
168
169 @Override
170 public Result<Long> count() {
171 return Result.ok((long) storage.size());
172 }
173
174
175
176
177
178 @Override
179 public Result<T> update(String id, T entity) {
180 if (id == null || id.isEmpty()) {
181 return Result.fail("ID cannot be null or empty");
182 }
183
184 if (!storage.containsKey(id)) {
185 return Result.fail("Cannot update: Entity not found with ID: " + id);
186 }
187
188 try {
189
190 String entityId = idExtractor.apply(entity);
191 if (entityId == null || !entityId.equals(id)) {
192 return Result.fail("Entity ID doesn't match the provided ID");
193 }
194
195 storage.put(id, entity);
196 return Result.ok(entity);
197 } catch (Exception e) {
198 return Result.fail("Failed to update entity: " + e.getMessage());
199 }
200 }
201
202
203
204
205
206 @Override
207 public Result<Boolean> deleteById(String id) {
208 if (id == null || id.isEmpty()) {
209 return Result.fail("ID cannot be null or empty");
210 }
211
212 if (!storage.containsKey(id)) {
213 return Result.ok(false);
214 }
215
216 storage.remove(id);
217 return Result.ok(true);
218 }
219
220 @Override
221 public Result<Void> deleteAllById(List<String> ids) {
222 if (ids == null) {
223 return Result.fail("IDs list cannot be null");
224 }
225
226 for (String id : ids) {
227 if (id != null && !id.isEmpty()) {
228 storage.remove(id);
229 }
230 }
231
232 return Result.ok(null);
233 }
234
235 @Override
236 public Result<Void> clear() {
237 storage.clear();
238 return Result.ok(null);
239 }
240 }