1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.provisioning.java.data;
20
21 import java.text.ParseException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Optional;
29 import java.util.Set;
30 import java.util.stream.Collectors;
31 import org.apache.commons.lang3.StringUtils;
32 import org.apache.commons.lang3.tuple.Pair;
33 import org.apache.syncope.common.lib.Attr;
34 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
35 import org.apache.syncope.common.lib.SyncopeClientException;
36 import org.apache.syncope.common.lib.request.AnyCR;
37 import org.apache.syncope.common.lib.request.AnyUR;
38 import org.apache.syncope.common.lib.request.AttrPatch;
39 import org.apache.syncope.common.lib.request.StringPatchItem;
40 import org.apache.syncope.common.lib.to.AnyTO;
41 import org.apache.syncope.common.lib.to.ConnObject;
42 import org.apache.syncope.common.lib.to.MembershipTO;
43 import org.apache.syncope.common.lib.to.Provision;
44 import org.apache.syncope.common.lib.to.RelationshipTO;
45 import org.apache.syncope.common.lib.types.AttrSchemaType;
46 import org.apache.syncope.common.lib.types.ClientExceptionType;
47 import org.apache.syncope.common.lib.types.PatchOperation;
48 import org.apache.syncope.common.lib.types.ResourceOperation;
49 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
50 import org.apache.syncope.core.persistence.api.attrvalue.validation.PlainAttrValidationManager;
51 import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
52 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
53 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
54 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
55 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
56 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
57 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
58 import org.apache.syncope.core.persistence.api.dao.PlainAttrValueDAO;
59 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
60 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
61 import org.apache.syncope.core.persistence.api.dao.RelationshipTypeDAO;
62 import org.apache.syncope.core.persistence.api.dao.UserDAO;
63 import org.apache.syncope.core.persistence.api.entity.Any;
64 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
65 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
66 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
67 import org.apache.syncope.core.persistence.api.entity.DerSchema;
68 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
69 import org.apache.syncope.core.persistence.api.entity.ExternalResource;
70 import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
71 import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
72 import org.apache.syncope.core.persistence.api.entity.Membership;
73 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
74 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
75 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
76 import org.apache.syncope.core.persistence.api.entity.Realm;
77 import org.apache.syncope.core.persistence.api.entity.VirSchema;
78 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
79 import org.apache.syncope.core.provisioning.api.AccountGetter;
80 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
81 import org.apache.syncope.core.provisioning.api.IntAttrName;
82 import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
83 import org.apache.syncope.core.provisioning.api.MappingManager;
84 import org.apache.syncope.core.provisioning.api.PlainAttrGetter;
85 import org.apache.syncope.core.provisioning.api.PropagationByResource;
86 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
87 import org.apache.syncope.core.provisioning.api.jexl.JexlUtils;
88 import org.apache.syncope.core.provisioning.java.pushpull.OutboundMatcher;
89 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
90 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
91 import org.identityconnectors.framework.common.objects.Attribute;
92 import org.identityconnectors.framework.common.objects.AttributeBuilder;
93 import org.identityconnectors.framework.common.objects.ConnectorObject;
94 import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
95 import org.identityconnectors.framework.common.objects.Uid;
96 import org.slf4j.Logger;
97 import org.slf4j.LoggerFactory;
98
99 abstract class AbstractAnyDataBinder {
100
101 protected static final Logger LOG = LoggerFactory.getLogger(AbstractAnyDataBinder.class);
102
103 protected final AnyTypeDAO anyTypeDAO;
104
105 protected final RealmDAO realmDAO;
106
107 protected final AnyTypeClassDAO anyTypeClassDAO;
108
109 protected final AnyObjectDAO anyObjectDAO;
110
111 protected final UserDAO userDAO;
112
113 protected final GroupDAO groupDAO;
114
115 protected final PlainSchemaDAO plainSchemaDAO;
116
117 protected final PlainAttrDAO plainAttrDAO;
118
119 protected final PlainAttrValueDAO plainAttrValueDAO;
120
121 protected final ExternalResourceDAO resourceDAO;
122
123 protected final RelationshipTypeDAO relationshipTypeDAO;
124
125 protected final EntityFactory entityFactory;
126
127 protected final AnyUtilsFactory anyUtilsFactory;
128
129 protected final DerAttrHandler derAttrHandler;
130
131 protected final VirAttrHandler virAttrHandler;
132
133 protected final MappingManager mappingManager;
134
135 protected final IntAttrNameParser intAttrNameParser;
136
137 protected final OutboundMatcher outboundMatcher;
138
139 protected final PlainAttrValidationManager validator;
140
141 protected AbstractAnyDataBinder(
142 final AnyTypeDAO anyTypeDAO,
143 final RealmDAO realmDAO,
144 final AnyTypeClassDAO anyTypeClassDAO,
145 final AnyObjectDAO anyObjectDAO,
146 final UserDAO userDAO,
147 final GroupDAO groupDAO,
148 final PlainSchemaDAO plainSchemaDAO,
149 final PlainAttrDAO plainAttrDAO,
150 final PlainAttrValueDAO plainAttrValueDAO,
151 final ExternalResourceDAO resourceDAO,
152 final RelationshipTypeDAO relationshipTypeDAO,
153 final EntityFactory entityFactory,
154 final AnyUtilsFactory anyUtilsFactory,
155 final DerAttrHandler derAttrHandler,
156 final VirAttrHandler virAttrHandler,
157 final MappingManager mappingManager,
158 final IntAttrNameParser intAttrNameParser,
159 final OutboundMatcher outboundMatcher,
160 final PlainAttrValidationManager validator) {
161
162 this.anyTypeDAO = anyTypeDAO;
163 this.realmDAO = realmDAO;
164 this.anyTypeClassDAO = anyTypeClassDAO;
165 this.anyObjectDAO = anyObjectDAO;
166 this.userDAO = userDAO;
167 this.groupDAO = groupDAO;
168 this.plainSchemaDAO = plainSchemaDAO;
169 this.plainAttrDAO = plainAttrDAO;
170 this.plainAttrValueDAO = plainAttrValueDAO;
171 this.resourceDAO = resourceDAO;
172 this.relationshipTypeDAO = relationshipTypeDAO;
173 this.entityFactory = entityFactory;
174 this.anyUtilsFactory = anyUtilsFactory;
175 this.derAttrHandler = derAttrHandler;
176 this.virAttrHandler = virAttrHandler;
177 this.mappingManager = mappingManager;
178 this.intAttrNameParser = intAttrNameParser;
179 this.outboundMatcher = outboundMatcher;
180 this.validator = validator;
181 }
182
183 protected void setRealm(final Any<?> any, final AnyUR anyUR) {
184 if (anyUR.getRealm() != null && StringUtils.isNotBlank(anyUR.getRealm().getValue())) {
185 Realm newRealm = realmDAO.findByFullPath(anyUR.getRealm().getValue());
186 if (newRealm == null) {
187 LOG.debug("Invalid realm specified: {}, ignoring", anyUR.getRealm().getValue());
188 } else {
189 any.setRealm(newRealm);
190 }
191 }
192 }
193
194 protected Map<String, ConnObject> onResources(
195 final Any<?> any,
196 final Collection<String> resources,
197 final String password,
198 final boolean changePwd) {
199
200 Map<String, ConnObject> onResources = new HashMap<>();
201
202 resources.stream().map(resourceDAO::find).filter(Objects::nonNull).forEach(resource -> {
203 resource.getProvisionByAnyType(any.getType().getKey()).
204 ifPresent(provision -> MappingUtils.getConnObjectKeyItem(provision).ifPresent(keyItem -> {
205
206 Pair<String, Set<Attribute>> prepared = mappingManager.prepareAttrsFromAny(
207 any, password, changePwd, true, resource, provision);
208
209 ConnObject connObjectTO;
210 if (StringUtils.isBlank(prepared.getLeft())) {
211 connObjectTO = ConnObjectUtils.getConnObjectTO(null, prepared.getRight());
212 } else {
213 ConnectorObject connectorObject = new ConnectorObjectBuilder().
214 addAttributes(prepared.getRight()).
215 addAttribute(new Uid(prepared.getLeft())).
216 addAttribute(AttributeBuilder.build(keyItem.getExtAttrName(), prepared.getLeft())).
217 build();
218
219 connObjectTO = ConnObjectUtils.getConnObjectTO(
220 outboundMatcher.getFIQL(connectorObject, resource, provision),
221 connectorObject.getAttributes());
222 }
223
224 onResources.put(resource.getKey(), connObjectTO);
225 }));
226 });
227
228 return onResources;
229 }
230
231 protected PlainSchema getPlainSchema(final String schemaName) {
232 PlainSchema schema = null;
233 if (StringUtils.isNotBlank(schemaName)) {
234 schema = plainSchemaDAO.find(schemaName);
235
236
237 if (schema == null) {
238 LOG.debug("Ignoring invalid schema {}", schemaName);
239 } else if (schema.isReadonly()) {
240 schema = null;
241 LOG.debug("Ignoring readonly schema {}", schemaName);
242 }
243 }
244
245 return schema;
246 }
247
248 protected void fillAttr(
249 final List<String> values,
250 final AnyUtils anyUtils,
251 final PlainSchema schema,
252 final PlainAttr<?> attr,
253 final SyncopeClientException invalidValues) {
254
255
256
257 List<String> valuesProvided = schema.isMultivalue()
258 ? values
259 : (values.isEmpty() || values.get(0) == null
260 ? List.of()
261 : List.of(values.get(0)));
262
263 valuesProvided.forEach(value -> {
264 if (StringUtils.isBlank(value)) {
265 LOG.debug("Null value for {}, ignoring", schema.getKey());
266 } else {
267 try {
268 attr.add(validator, value, anyUtils);
269 } catch (InvalidPlainAttrValueException e) {
270 LOG.warn("Invalid value for attribute {}: {}",
271 schema.getKey(), StringUtils.abbreviate(value, 20), e);
272
273 invalidValues.getElements().add(schema.getKey() + ": " + value + " - " + e.getMessage());
274 }
275 }
276 });
277 }
278
279 protected List<String> evaluateMandatoryCondition(
280 final ExternalResource resource, final Provision provision, final Any<?> any) {
281
282 List<String> missingAttrNames = new ArrayList<>();
283
284 MappingUtils.getPropagationItems(provision.getMapping().getItems().stream()).forEach(mapItem -> {
285 IntAttrName intAttrName = null;
286 try {
287 intAttrName = intAttrNameParser.parse(mapItem.getIntAttrName(), any.getType().getKind());
288 } catch (ParseException e) {
289 LOG.error("Invalid intAttrName '{}', ignoring", mapItem.getIntAttrName(), e);
290 }
291 if (intAttrName != null && intAttrName.getSchema() != null) {
292 AttrSchemaType schemaType = intAttrName.getSchema() instanceof PlainSchema
293 ? intAttrName.getSchema().getType()
294 : AttrSchemaType.String;
295
296 Pair<AttrSchemaType, List<PlainAttrValue>> intValues = mappingManager.getIntValues(
297 resource,
298 provision,
299 mapItem,
300 intAttrName,
301 schemaType,
302 any,
303 AccountGetter.DEFAULT,
304 PlainAttrGetter.DEFAULT);
305 if (intValues.getRight().isEmpty()
306 && JexlUtils.evaluateMandatoryCondition(mapItem.getMandatoryCondition(), any, derAttrHandler)) {
307
308 missingAttrNames.add(mapItem.getIntAttrName());
309 }
310 }
311 });
312
313 return missingAttrNames;
314 }
315
316 private SyncopeClientException checkMandatoryOnResources(
317 final Any<?> any, final Collection<? extends ExternalResource> resources) {
318
319 SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
320
321 resources.forEach(resource -> {
322 Optional<Provision> provision = resource.getProvisionByAnyType(any.getType().getKey());
323 if (resource.isEnforceMandatoryCondition() && provision.isPresent()) {
324 List<String> missingAttrNames = evaluateMandatoryCondition(resource, provision.get(), any);
325 if (!missingAttrNames.isEmpty()) {
326 LOG.error("Mandatory schemas {} not provided with values", missingAttrNames);
327
328 reqValMissing.getElements().addAll(missingAttrNames);
329 }
330 }
331 });
332
333 return reqValMissing;
334 }
335
336 private void checkMandatory(
337 final PlainSchema schema,
338 final PlainAttr<?> attr,
339 final Any<?> any,
340 final SyncopeClientException reqValMissing) {
341
342 if (attr == null
343 && !schema.isReadonly()
344 && JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any, derAttrHandler)) {
345
346 LOG.error("Mandatory schema " + schema.getKey() + " not provided with values");
347
348 reqValMissing.getElements().add(schema.getKey());
349 }
350 }
351
352 private SyncopeClientException checkMandatory(final Any<?> any, final AnyUtils anyUtils) {
353 SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
354
355
356 AllowedSchemas<PlainSchema> allowedPlainSchemas = anyUtils.dao().findAllowedSchemas(any, PlainSchema.class);
357 allowedPlainSchemas.getForSelf().forEach(schema -> checkMandatory(
358 schema, any.getPlainAttr(schema.getKey()).orElse(null), any, reqValMissing));
359 if (any instanceof GroupableRelatable) {
360 allowedPlainSchemas.getForMemberships().forEach((group, schemas) -> {
361 GroupableRelatable<?, ?, ?, ?, ?> groupable = GroupableRelatable.class.cast(any);
362 Membership<?> membership = groupable.getMembership(group.getKey()).orElse(null);
363 schemas.forEach(schema -> checkMandatory(
364 schema,
365 groupable.getPlainAttr(schema.getKey(), membership).orElse(null),
366 any,
367 reqValMissing));
368 });
369 }
370
371 return reqValMissing;
372 }
373
374 @SuppressWarnings({ "unchecked", "rawtypes" })
375 protected void processAttrPatch(
376 final Any any,
377 final AttrPatch patch,
378 final PlainSchema schema,
379 final PlainAttr<?> attr,
380 final AnyUtils anyUtils,
381 final SyncopeClientException invalidValues) {
382
383 switch (patch.getOperation()) {
384 case ADD_REPLACE:
385
386 if (attr.getSchema().isUniqueConstraint()) {
387 if (attr.getUniqueValue() != null
388 && !patch.getAttr().getValues().isEmpty()
389 && !patch.getAttr().getValues().get(0).equals(attr.getUniqueValue().getValueAsString())) {
390
391 plainAttrValueDAO.deleteAll(attr, anyUtils);
392 }
393 } else {
394 plainAttrValueDAO.deleteAll(attr, anyUtils);
395 }
396
397
398 List<String> valuesToBeAdded = patch.getAttr().getValues();
399 if (!valuesToBeAdded.isEmpty()
400 && (!schema.isUniqueConstraint() || attr.getUniqueValue() == null
401 || !valuesToBeAdded.get(0).equals(attr.getUniqueValue().getValueAsString()))) {
402
403 fillAttr(valuesToBeAdded, anyUtils, schema, attr, invalidValues);
404 }
405
406
407 if (attr.getValuesAsStrings().isEmpty()) {
408 plainAttrDAO.delete(attr);
409 }
410 break;
411
412 case DELETE:
413 default:
414 any.remove(attr);
415 plainAttrDAO.delete(attr);
416 }
417 }
418
419 @SuppressWarnings({ "unchecked", "rawtypes" })
420 protected void fill(
421 final Any any,
422 final AnyUR anyUR,
423 final AnyUtils anyUtils,
424 final SyncopeClientCompositeException scce) {
425
426
427 for (StringPatchItem patch : anyUR.getAuxClasses()) {
428 AnyTypeClass auxClass = anyTypeClassDAO.find(patch.getValue());
429 if (auxClass == null) {
430 LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + " {}, ignoring...", patch.getValue());
431 } else {
432 switch (patch.getOperation()) {
433 case ADD_REPLACE:
434 any.add(auxClass);
435 break;
436
437 case DELETE:
438 default:
439 any.getAuxClasses().remove(auxClass);
440 }
441 }
442 }
443
444
445 for (StringPatchItem patch : anyUR.getResources()) {
446 ExternalResource resource = resourceDAO.find(patch.getValue());
447 if (resource == null) {
448 LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + " {}, ignoring...", patch.getValue());
449 } else {
450 switch (patch.getOperation()) {
451 case ADD_REPLACE:
452 any.add(resource);
453 break;
454
455 case DELETE:
456 default:
457 any.getResources().remove(resource);
458 }
459 }
460 }
461
462 Set<ExternalResource> resources = anyUtils.getAllResources(any);
463 SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
464
465
466 anyUR.getPlainAttrs().stream().filter(patch -> patch.getAttr() != null).forEach(patch -> {
467 PlainSchema schema = getPlainSchema(patch.getAttr().getSchema());
468 if (schema == null) {
469 LOG.debug("Invalid " + PlainSchema.class.getSimpleName() + " {}, ignoring...",
470 patch.getAttr().getSchema());
471 } else {
472 PlainAttr<?> attr = (PlainAttr<?>) any.getPlainAttr(schema.getKey()).orElse(null);
473 if (attr == null) {
474 LOG.debug("No plain attribute found for schema {}", schema);
475
476 if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
477 attr = anyUtils.newPlainAttr();
478 ((PlainAttr) attr).setOwner(any);
479 attr.setSchema(schema);
480 any.add(attr);
481 }
482 }
483 if (attr != null) {
484 processAttrPatch(any, patch, schema, attr, anyUtils, invalidValues);
485 }
486 }
487 });
488 if (!invalidValues.isEmpty()) {
489 scce.addException(invalidValues);
490 }
491
492 SyncopeClientException requiredValuesMissing = checkMandatory(any, anyUtils);
493 if (!requiredValuesMissing.isEmpty()) {
494 scce.addException(requiredValuesMissing);
495 }
496 requiredValuesMissing = checkMandatoryOnResources(any, resources);
497 if (!requiredValuesMissing.isEmpty()) {
498 scce.addException(requiredValuesMissing);
499 }
500 }
501
502 protected PropagationByResource<String> propByRes(
503 final Map<String, ConnObject> before,
504 final Map<String, ConnObject> after) {
505
506 PropagationByResource<String> propByRes = new PropagationByResource<>();
507
508 after.forEach((resource, connObject) -> {
509 if (before.containsKey(resource)) {
510 ConnObject beforeObject = before.get(resource);
511 if (!beforeObject.equals(connObject)) {
512 propByRes.add(ResourceOperation.UPDATE, resource);
513
514 beforeObject.getAttr(Uid.NAME).map(attr -> attr.getValues().get(0)).
515 ifPresent(value -> propByRes.addOldConnObjectKey(resource, value));
516 }
517 } else {
518 propByRes.add(ResourceOperation.CREATE, resource);
519 }
520 });
521 propByRes.addAll(
522 ResourceOperation.DELETE,
523 before.keySet().stream().filter(resource -> !after.containsKey(resource)).collect(Collectors.toSet()));
524
525 return propByRes;
526 }
527
528 @SuppressWarnings({ "unchecked", "rawtypes" })
529 protected void fill(
530 final Any any,
531 final AnyCR anyCR,
532 final AnyUtils anyUtils,
533 final SyncopeClientCompositeException scce) {
534
535
536 any.getAuxClasses().clear();
537 anyCR.getAuxClasses().stream().
538 map(className -> anyTypeClassDAO.find(className)).
539 forEach(auxClass -> {
540 if (auxClass == null) {
541 LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + " {}, ignoring...", auxClass);
542 } else {
543 any.add(auxClass);
544 }
545 });
546
547
548 SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
549
550 anyCR.getPlainAttrs().stream().
551 filter(attrTO -> !attrTO.getValues().isEmpty()).
552 forEach(attrTO -> {
553 PlainSchema schema = getPlainSchema(attrTO.getSchema());
554 if (schema != null) {
555 PlainAttr<?> attr = (PlainAttr<?>) any.getPlainAttr(schema.getKey()).orElse(null);
556 if (attr == null) {
557 attr = anyUtils.newPlainAttr();
558 ((PlainAttr) attr).setOwner(any);
559 attr.setSchema(schema);
560 }
561 fillAttr(attrTO.getValues(), anyUtils, schema, attr, invalidValues);
562
563 if (attr.getValuesAsStrings().isEmpty()) {
564 attr.setOwner(null);
565 } else {
566 any.add(attr);
567 }
568 }
569 });
570
571 if (!invalidValues.isEmpty()) {
572 scce.addException(invalidValues);
573 }
574
575 SyncopeClientException requiredValuesMissing = checkMandatory(any, anyUtils);
576 if (!requiredValuesMissing.isEmpty()) {
577 scce.addException(requiredValuesMissing);
578 }
579
580
581 anyCR.getResources().forEach(resourceKey -> {
582 ExternalResource resource = resourceDAO.find(resourceKey);
583 if (resource == null) {
584 LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + " {}, ignoring...", resourceKey);
585 } else {
586 any.add(resource);
587 }
588 });
589
590 requiredValuesMissing = checkMandatoryOnResources(any, anyUtils.getAllResources(any));
591 if (!requiredValuesMissing.isEmpty()) {
592 scce.addException(requiredValuesMissing);
593 }
594 }
595
596 @SuppressWarnings({ "unchecked", "rawtypes" })
597 protected void fill(
598 final Any any,
599 final Membership membership,
600 final MembershipTO membershipTO,
601 final AnyUtils anyUtils,
602 final SyncopeClientCompositeException scce) {
603
604 SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
605
606 membershipTO.getPlainAttrs().stream().
607 filter(attrTO -> !attrTO.getValues().isEmpty()).
608 forEach(attrTO -> Optional.ofNullable(getPlainSchema(attrTO.getSchema())).ifPresent(schema -> {
609
610 GroupablePlainAttr attr = (GroupablePlainAttr) GroupableRelatable.class.cast(any).
611 getPlainAttr(schema.getKey(), membership).
612 orElseGet(() -> {
613 GroupablePlainAttr gpa = anyUtils.newPlainAttr();
614 gpa.setOwner(any);
615 gpa.setMembership(membership);
616 gpa.setSchema(schema);
617 return gpa;
618 });
619 fillAttr(attrTO.getValues(), anyUtils, schema, attr, invalidValues);
620
621 if (attr.getValuesAsStrings().isEmpty()) {
622 attr.setOwner(null);
623 } else {
624 any.add(attr);
625 }
626 }));
627
628 if (!invalidValues.isEmpty()) {
629 scce.addException(invalidValues);
630 }
631 }
632
633 protected static void fillTO(
634 final AnyTO anyTO,
635 final String realmFullPath,
636 final Collection<? extends AnyTypeClass> auxClasses,
637 final Collection<? extends PlainAttr<?>> plainAttrs,
638 final Map<DerSchema, String> derAttrs,
639 final Map<VirSchema, List<String>> virAttrs,
640 final Collection<? extends ExternalResource> resources) {
641
642 anyTO.setRealm(realmFullPath);
643
644 anyTO.getAuxClasses().addAll(auxClasses.stream().map(AnyTypeClass::getKey).collect(Collectors.toList()));
645
646 plainAttrs
647 .forEach(plainAttr -> anyTO.getPlainAttrs().add(new Attr.Builder(plainAttr.getSchema().getKey())
648 .values(plainAttr.getValuesAsStrings()).build()));
649
650 derAttrs.forEach((schema, value) -> anyTO.getDerAttrs()
651 .add(new Attr.Builder(schema.getKey()).value(value).build()));
652
653 virAttrs.forEach((schema, values) -> anyTO.getVirAttrs()
654 .add(new Attr.Builder(schema.getKey()).values(values).build()));
655
656 anyTO.getResources().addAll(resources.stream().map(ExternalResource::getKey).collect(Collectors.toSet()));
657 }
658
659 protected static RelationshipTO getRelationshipTO(final String relationshipType, final AnyObject otherEnd) {
660 return new RelationshipTO.Builder(relationshipType).
661 otherEnd(otherEnd.getType().getKey(), otherEnd.getKey(), otherEnd.getName()).
662 build();
663 }
664
665 protected static MembershipTO getMembershipTO(
666 final Collection<? extends PlainAttr<?>> plainAttrs,
667 final Map<DerSchema, String> derAttrs,
668 final Map<VirSchema, List<String>> virAttrs,
669 final Membership<? extends Any<?>> membership) {
670
671 MembershipTO membershipTO = new MembershipTO.Builder(membership.getRightEnd().getKey())
672 .groupName(membership.getRightEnd().getName())
673 .build();
674
675 plainAttrs.forEach(plainAttr -> membershipTO.getPlainAttrs()
676 .add(new Attr.Builder(plainAttr.getSchema().getKey())
677 .values(plainAttr.getValuesAsStrings()).
678 build()));
679
680 derAttrs.forEach((schema, value) -> membershipTO.getDerAttrs().add(new Attr.Builder(schema.getKey()).
681 value(value).
682 build()));
683
684 virAttrs.forEach((schema, values) -> membershipTO.getVirAttrs().add(new Attr.Builder(schema.getKey()).
685 values(values).
686 build()));
687
688 return membershipTO;
689 }
690 }