1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.data.ldaptive;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.LinkedHashSet;
23 import java.util.List;
24 import java.util.Set;
25 import java.util.stream.Collectors;
26 import javax.validation.constraints.NotNull;
27 import org.ldaptive.AttributeModification;
28 import org.ldaptive.AttributeModification.Type;
29 import org.ldaptive.LdapAttribute;
30 import org.ldaptive.LdapEntry;
31 import org.ldaptive.ModifyRequest;
32 import org.ldaptive.beans.LdapEntryMapper;
33 import org.ldaptive.transcode.ValueTranscoder;
34 import org.springframework.lang.Nullable;
35 import org.springframework.validation.annotation.Validated;
36
37
38
39
40
41
42
43 @Validated
44 public interface LdaptiveEntryMapper<T> extends LdapEntryMapper<T> {
45
46
47
48
49
50
51
52 String[] getObjectClasses();
53
54 @Override
55 String mapDn(T domainObject);
56
57
58
59
60
61
62
63 @Nullable
64 T map(@Nullable LdapEntry ldapEntry);
65
66 @Override
67 void map(LdapEntry source, T destination);
68
69 @Override
70 default void map(T source, LdapEntry destination) {
71 mapAndComputeModifications(source, destination);
72 }
73
74
75
76
77
78
79
80
81 AttributeModification[] mapAndComputeModifications(
82 @NotNull T source,
83 @NotNull LdapEntry destination);
84
85
86
87
88
89
90
91
92 default ModifyRequest mapAndComputeModifyRequest(
93 @NotNull T source,
94 @NotNull LdapEntry destination) {
95 return new ModifyRequest(destination.getDn(), mapAndComputeModifications(source, destination));
96 }
97
98
99
100
101
102
103
104
105
106
107
108 static <T> T getAttributeValue(
109 @Nullable final LdapEntry ldapEntry,
110 @NotNull final String name,
111 final ValueTranscoder<T> valueTranscoder,
112 final T defaultValue) {
113 final LdapAttribute attr = ldapEntry == null ? null : ldapEntry.getAttribute(name);
114 final T value = attr != null ? attr.getValue(valueTranscoder.decoder()) : null;
115 return value != null ? value : defaultValue;
116 }
117
118
119
120
121
122
123
124
125
126
127 static <T> Collection<T> getAttributeValues(
128 @Nullable final LdapEntry ldapEntry,
129 @NotNull final String name,
130 final ValueTranscoder<T> valueTranscoder) {
131 final LdapAttribute attr = ldapEntry == null ? null : ldapEntry.getAttribute(name);
132 final Collection<T> values = attr != null ? attr.getValues(valueTranscoder.decoder()) : null;
133 return values != null ? values : new ArrayList<>();
134 }
135
136
137
138
139
140
141
142
143
144
145 static <T> Set<T> getAttributeValuesAsSet(
146 @Nullable final LdapEntry ldapEntry,
147 @NotNull final String name,
148 final ValueTranscoder<T> valueTranscoder) {
149 return new LinkedHashSet<>(getAttributeValues(ldapEntry, name, valueTranscoder));
150 }
151
152
153
154
155
156
157
158
159
160
161 static <T> List<T> getAttributeValuesAsList(
162 @Nullable final LdapEntry ldapEntry,
163 @NotNull final String name,
164 final ValueTranscoder<T> valueTranscoder) {
165 return new ArrayList<>(getAttributeValues(ldapEntry, name, valueTranscoder));
166 }
167
168
169
170
171
172
173
174
175
176
177
178
179 static <T> void setAttribute(
180 @NotNull final LdapEntry ldapEntry,
181 @NotNull final String name,
182 @Nullable final T value,
183 final boolean isBinary,
184 final ValueTranscoder<T> valueTranscoder,
185 @NotNull final List<AttributeModification> modifications) {
186
187 setAttributes(
188 ldapEntry,
189 name,
190 value != null ? Collections.singleton(value) : null,
191 isBinary,
192 valueTranscoder,
193 modifications);
194 }
195
196
197
198
199
200
201
202
203
204
205
206
207 static <T> void setAttributes(
208 @NotNull final LdapEntry ldapEntry,
209 @NotNull final String name,
210 @Nullable final Collection<T> values,
211 final boolean isBinary,
212 final ValueTranscoder<T> valueTranscoder,
213 @NotNull final List<AttributeModification> modifications) {
214
215 final Collection<T> realValues = values == null ? null : values.stream()
216 .filter(value -> {
217 if (value instanceof CharSequence) {
218 return ((CharSequence) value).length() > 0;
219 }
220 return value != null;
221 })
222 .collect(Collectors.toList());
223 LdapAttribute attr = ldapEntry.getAttribute(name);
224 if (attr == null && realValues != null && !realValues.isEmpty()) {
225 addAttributes(ldapEntry, name, realValues, isBinary, valueTranscoder, modifications);
226 } else if (attr != null) {
227 if (realValues == null || realValues.isEmpty()) {
228 ldapEntry.removeAttribute(name);
229 modifications.add(
230 new AttributeModification(
231 Type.DELETE,
232 attr));
233 } else if (!new ArrayList<>(realValues)
234 .equals(new ArrayList<>(attr.getValues(valueTranscoder.decoder())))) {
235 final LdapAttribute newAttr = new LdapAttribute();
236 newAttr.setBinary(isBinary);
237 newAttr.setName(name);
238 newAttr.addValues(valueTranscoder.encoder(), realValues);
239 ldapEntry.addAttributes(newAttr);
240 modifications.add(
241 new AttributeModification(
242 Type.REPLACE,
243 newAttr));
244 }
245 }
246 }
247
248
249
250
251
252
253
254
255
256
257
258
259 static <T> void addAttribute(
260 @NotNull final LdapEntry ldapEntry,
261 @NotNull final String name,
262 @Nullable final T value,
263 final boolean isBinary,
264 @NotNull final ValueTranscoder<T> valueTranscoder,
265 @NotNull final List<AttributeModification> modifications) {
266 addAttributes(
267 ldapEntry,
268 name,
269 value != null ? Collections.singleton(value) : null,
270 isBinary,
271 valueTranscoder,
272 modifications);
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286 static <T> void addAttributes(
287 @NotNull final LdapEntry ldapEntry,
288 @NotNull final String name,
289 @Nullable final Collection<T> values,
290 final boolean isBinary,
291 @NotNull final ValueTranscoder<T> valueTranscoder,
292 @NotNull final List<AttributeModification> modifications) {
293 final Collection<T> realValues = values == null ? null : values.stream()
294 .filter(value -> {
295 if (value instanceof CharSequence) {
296 return ((CharSequence) value).length() > 0;
297 }
298 return value != null;
299 })
300 .collect(Collectors.toList());
301 if (realValues == null || realValues.isEmpty()) {
302 return;
303 }
304 final LdapAttribute attr = ldapEntry.getAttribute(name);
305 if (attr == null) {
306 final LdapAttribute newAttr = new LdapAttribute();
307 newAttr.setBinary(isBinary);
308 newAttr.setName(name);
309 newAttr.addValues(valueTranscoder.encoder(), realValues);
310 ldapEntry.addAttributes(newAttr);
311 modifications.add(
312 new AttributeModification(
313 Type.ADD,
314 newAttr));
315 } else {
316 final List<T> newValues = new ArrayList<>(
317 getAttributeValues(ldapEntry, name, valueTranscoder));
318 newValues.addAll(realValues);
319 setAttributes(ldapEntry, name, newValues, attr.isBinary(), valueTranscoder, modifications);
320 }
321 }
322
323
324
325
326
327
328
329
330 static void removeAttribute(
331 @NotNull final LdapEntry ldapEntry,
332 @NotNull final String name,
333 @NotNull final List<AttributeModification> modifications) {
334 final LdapAttribute attr = ldapEntry.getAttribute(name);
335 if (attr == null) {
336 return;
337 }
338 ldapEntry.removeAttributes(attr);
339 modifications.add(
340 new AttributeModification(
341 Type.DELETE,
342 attr));
343 }
344
345
346
347
348
349
350
351
352
353
354
355 static <T> void removeAttribute(
356 @NotNull final LdapEntry ldapEntry,
357 @NotNull final String name,
358 @Nullable final T value,
359 final ValueTranscoder<T> valueTranscoder,
360 @NotNull final List<AttributeModification> modifications) {
361 LdapAttribute attr = ldapEntry.getAttribute(name);
362 if (attr == null) {
363 return;
364 }
365 if (value == null) {
366 removeAttribute(ldapEntry, name, modifications);
367 } else {
368 removeAttributes(ldapEntry, name, Collections.singleton(value), valueTranscoder,
369 modifications);
370 }
371 }
372
373
374
375
376
377
378
379
380
381
382
383 static <T> void removeAttributes(
384 @NotNull final LdapEntry ldapEntry,
385 @NotNull final String name,
386 @Nullable final Collection<T> values,
387 final ValueTranscoder<T> valueTranscoder,
388 @NotNull final List<AttributeModification> modifications) {
389
390 final LdapAttribute attr = ldapEntry.getAttribute(name);
391 if (attr == null || values == null || values.isEmpty()) {
392 return;
393 }
394 final List<T> newValues = new ArrayList<>(getAttributeValues(ldapEntry, name, valueTranscoder));
395 newValues.removeAll(values);
396 setAttributes(ldapEntry, name, newValues, attr.isBinary(), valueTranscoder, modifications);
397 }
398
399
400
401
402
403
404
405
406
407 static String createDn(
408 @NotNull final String rdn,
409 @NotNull final String rdnValue,
410 @NotNull final String baseDn) {
411 return rdn + "=" + rdnValue + "," + baseDn;
412 }
413
414
415
416
417
418
419
420 static String getRdn(final String dn) {
421 if (dn == null) {
422 return null;
423 }
424 int start = dn.indexOf('=');
425 if (start < 0) {
426 return dn;
427 }
428 int end = dn.indexOf(',', start);
429 if (end < 0) {
430 return dn.substring(start + 1).trim();
431 }
432 return dn.substring(start + 1, end).trim();
433 }
434
435 }