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 org.apache.commons.lang3.StringUtils;
22 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
23 import org.apache.syncope.common.lib.SyncopeClientException;
24 import org.apache.syncope.common.lib.to.DerSchemaTO;
25 import org.apache.syncope.common.lib.to.PlainSchemaTO;
26 import org.apache.syncope.common.lib.to.Provision;
27 import org.apache.syncope.common.lib.to.VirSchemaTO;
28 import org.apache.syncope.common.lib.types.AnyTypeKind;
29 import org.apache.syncope.common.lib.types.ClientExceptionType;
30 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
31 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
32 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
33 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
34 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
35 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
36 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
37 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
38 import org.apache.syncope.core.persistence.api.entity.AnyType;
39 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
40 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
41 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
42 import org.apache.syncope.core.persistence.api.entity.DerSchema;
43 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
44 import org.apache.syncope.core.persistence.api.entity.ExternalResource;
45 import org.apache.syncope.core.persistence.api.entity.Implementation;
46 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
47 import org.apache.syncope.core.persistence.api.entity.VirSchema;
48 import org.apache.syncope.core.provisioning.api.data.SchemaDataBinder;
49 import org.apache.syncope.core.provisioning.api.jexl.JexlUtils;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class SchemaDataBinderImpl implements SchemaDataBinder {
54
55 protected static final Logger LOG = LoggerFactory.getLogger(SchemaDataBinder.class);
56
57 protected final AnyTypeClassDAO anyTypeClassDAO;
58
59 protected final PlainSchemaDAO plainSchemaDAO;
60
61 protected final DerSchemaDAO derSchemaDAO;
62
63 protected final VirSchemaDAO virSchemaDAO;
64
65 protected final ExternalResourceDAO resourceDAO;
66
67 protected final AnyTypeDAO anyTypeDAO;
68
69 protected final ImplementationDAO implementationDAO;
70
71 protected final EntityFactory entityFactory;
72
73 protected final AnyUtilsFactory anyUtilsFactory;
74
75 public SchemaDataBinderImpl(
76 final AnyTypeClassDAO anyTypeClassDAO,
77 final PlainSchemaDAO plainSchemaDAO,
78 final DerSchemaDAO derSchemaDAO,
79 final VirSchemaDAO virSchemaDAO,
80 final ExternalResourceDAO resourceDAO,
81 final AnyTypeDAO anyTypeDAO,
82 final ImplementationDAO implementationDAO,
83 final EntityFactory entityFactory,
84 final AnyUtilsFactory anyUtilsFactory) {
85
86 this.anyTypeClassDAO = anyTypeClassDAO;
87 this.plainSchemaDAO = plainSchemaDAO;
88 this.derSchemaDAO = derSchemaDAO;
89 this.virSchemaDAO = virSchemaDAO;
90 this.resourceDAO = resourceDAO;
91 this.anyTypeDAO = anyTypeDAO;
92 this.implementationDAO = implementationDAO;
93 this.entityFactory = entityFactory;
94 this.anyUtilsFactory = anyUtilsFactory;
95 }
96
97
98 protected PlainSchema fill(final PlainSchema schema, final PlainSchemaTO schemaTO) {
99 if (!JexlUtils.isExpressionValid(schemaTO.getMandatoryCondition())) {
100 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidValues);
101 sce.getElements().add(schemaTO.getMandatoryCondition());
102 throw sce;
103 }
104
105 schema.setKey(schemaTO.getKey());
106 schema.setType(schemaTO.getType());
107 schema.setCipherAlgorithm(schemaTO.getCipherAlgorithm());
108 schema.setConversionPattern(schemaTO.getConversionPattern());
109 schema.setEnumerationKeys(schemaTO.getEnumerationKeys());
110 schema.setEnumerationValues(schemaTO.getEnumerationValues());
111 schema.setMandatoryCondition(schemaTO.getMandatoryCondition());
112 schema.setMimeType(schemaTO.getMimeType());
113 schema.setMultivalue(schemaTO.isMultivalue());
114 schema.setReadonly(schemaTO.isReadonly());
115 schema.setSecretKey(schemaTO.getSecretKey());
116 schema.setUniqueConstraint(schemaTO.isUniqueConstraint());
117
118 schema.getLabels().clear();
119 schema.getLabels().putAll(schemaTO.getLabels());
120
121 if (schemaTO.getValidator() == null) {
122 schema.setValidator(null);
123 } else {
124 Implementation validator = implementationDAO.find(schemaTO.getValidator());
125 if (validator == null) {
126 LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
127 schemaTO.getValidator());
128 } else {
129 schema.setValidator(validator);
130 }
131 }
132
133 PlainSchema merged = plainSchemaDAO.save(schema);
134
135 if (schemaTO.getAnyTypeClass() != null
136 && (merged.getAnyTypeClass() == null
137 || !schemaTO.getAnyTypeClass().equals(merged.getAnyTypeClass().getKey()))) {
138
139 AnyTypeClass anyTypeClass = anyTypeClassDAO.find(schemaTO.getAnyTypeClass());
140 if (anyTypeClass == null) {
141 LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName()
142 + "{}, ignoring...", schemaTO.getAnyTypeClass());
143 } else {
144 anyTypeClass.add(merged);
145 merged.setAnyTypeClass(anyTypeClass);
146 }
147 } else if (schemaTO.getAnyTypeClass() == null && merged.getAnyTypeClass() != null) {
148 merged.getAnyTypeClass().getPlainSchemas().remove(merged);
149 merged.setAnyTypeClass(null);
150 }
151
152 return merged;
153 }
154
155 @Override
156 public PlainSchema create(final PlainSchemaTO schemaTO) {
157 return fill(entityFactory.newEntity(PlainSchema.class), schemaTO);
158 }
159
160 @Override
161 public PlainSchema update(final PlainSchemaTO schemaTO, final PlainSchema schema) {
162 SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
163
164 boolean hasAttrs = false;
165 for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
166 AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
167 hasAttrs |= plainSchemaDAO.hasAttrs(schema, anyUtils.plainAttrClass());
168 }
169
170 if (hasAttrs) {
171 if (schema.getType() != schemaTO.getType()) {
172 SyncopeClientException e = SyncopeClientException.build(ClientExceptionType.InvalidPlainSchema);
173 e.getElements().add("Cannot change type since " + schema.getKey() + " has attributes");
174
175 scce.addException(e);
176 }
177 if (schema.isUniqueConstraint() != schemaTO.isUniqueConstraint()) {
178 SyncopeClientException e = SyncopeClientException.build(ClientExceptionType.InvalidPlainSchema);
179 e.getElements().add("Cannot alter unique contraint since " + schema.getKey() + " has attributes");
180
181 scce.addException(e);
182 }
183 }
184
185 if (scce.hasExceptions()) {
186 throw scce;
187 }
188
189 return fill(schema, schemaTO);
190 }
191
192 @Override
193 public PlainSchemaTO getPlainSchemaTO(final String key) {
194 PlainSchema schema = plainSchemaDAO.find(key);
195 if (schema == null) {
196 throw new NotFoundException("Schema '" + key + '\'');
197 }
198
199 PlainSchemaTO schemaTO = new PlainSchemaTO();
200 schemaTO.setKey(schema.getKey());
201 schemaTO.setType(schema.getType());
202 schemaTO.setCipherAlgorithm(schema.getCipherAlgorithm());
203 schemaTO.setConversionPattern(schema.getConversionPattern());
204 schemaTO.setEnumerationKeys(schema.getEnumerationKeys());
205 schemaTO.setEnumerationValues(schema.getEnumerationValues());
206 schemaTO.setMandatoryCondition(schema.getMandatoryCondition());
207 schemaTO.setMimeType(schema.getMimeType());
208 schemaTO.setMultivalue(schema.isMultivalue());
209 schemaTO.setReadonly(schema.isReadonly());
210 schemaTO.setSecretKey(schema.getSecretKey());
211 schemaTO.setUniqueConstraint(schema.isUniqueConstraint());
212 schemaTO.getLabels().putAll(schema.getLabels());
213 schemaTO.setAnyTypeClass(schema.getAnyTypeClass() == null ? null : schema.getAnyTypeClass().getKey());
214 if (schema.getValidator() != null) {
215 schemaTO.setValidator(schema.getValidator().getKey());
216 }
217
218 return schemaTO;
219 }
220
221
222 protected DerSchema fill(final DerSchema schema, final DerSchemaTO schemaTO) {
223 SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
224
225 if (StringUtils.isBlank(schemaTO.getExpression())) {
226 SyncopeClientException requiredValuesMissing =
227 SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
228 requiredValuesMissing.getElements().add("expression");
229
230 scce.addException(requiredValuesMissing);
231 } else if (!JexlUtils.isExpressionValid(schemaTO.getExpression())) {
232 SyncopeClientException e = SyncopeClientException.build(ClientExceptionType.InvalidValues);
233 e.getElements().add(schemaTO.getExpression());
234
235 scce.addException(e);
236 }
237
238 if (scce.hasExceptions()) {
239 throw scce;
240 }
241
242 schema.setKey(schemaTO.getKey());
243 schema.setExpression(schemaTO.getExpression());
244
245 schema.getLabels().clear();
246 schema.getLabels().putAll(schemaTO.getLabels());
247
248 DerSchema merged = derSchemaDAO.save(schema);
249
250 if (schemaTO.getAnyTypeClass() != null
251 && (merged.getAnyTypeClass() == null
252 || !schemaTO.getAnyTypeClass().equals(merged.getAnyTypeClass().getKey()))) {
253
254 AnyTypeClass anyTypeClass = anyTypeClassDAO.find(schemaTO.getAnyTypeClass());
255 if (anyTypeClass == null) {
256 LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName()
257 + "{}, ignoring...", schemaTO.getAnyTypeClass());
258 } else {
259 anyTypeClass.add(merged);
260 merged.setAnyTypeClass(anyTypeClass);
261 }
262 } else if (schemaTO.getAnyTypeClass() == null && merged.getAnyTypeClass() != null) {
263 merged.getAnyTypeClass().getDerSchemas().remove(merged);
264 merged.setAnyTypeClass(null);
265 }
266
267 return merged;
268 }
269
270 @Override
271 public DerSchema create(final DerSchemaTO schemaTO) {
272 return fill(entityFactory.newEntity(DerSchema.class), schemaTO);
273 }
274
275 @Override
276 public DerSchema update(final DerSchemaTO schemaTO, final DerSchema schema) {
277 return fill(schema, schemaTO);
278 }
279
280 @Override
281 public DerSchemaTO getDerSchemaTO(final String key) {
282 DerSchema schema = derSchemaDAO.find(key);
283 if (schema == null) {
284 throw new NotFoundException("Derived schema '" + key + '\'');
285 }
286
287 DerSchemaTO schemaTO = new DerSchemaTO();
288 schemaTO.setKey(schema.getKey());
289 schemaTO.setExpression(schema.getExpression());
290 schemaTO.getLabels().putAll(schema.getLabels());
291 schemaTO.setAnyTypeClass(schema.getAnyTypeClass() == null ? null : schema.getAnyTypeClass().getKey());
292 return schemaTO;
293 }
294
295
296 protected VirSchema fill(final VirSchema schema, final VirSchemaTO schemaTO) {
297 schema.setKey(schemaTO.getKey());
298 schema.setExtAttrName(schemaTO.getExtAttrName());
299 schema.setReadonly(schemaTO.isReadonly());
300
301 schema.getLabels().clear();
302 schema.getLabels().putAll(schemaTO.getLabels());
303
304 if (schemaTO.getAnyTypeClass() != null
305 && (schema.getAnyTypeClass() == null
306 || !schemaTO.getAnyTypeClass().equals(schema.getAnyTypeClass().getKey()))) {
307
308 AnyTypeClass anyTypeClass = anyTypeClassDAO.find(schemaTO.getAnyTypeClass());
309 if (anyTypeClass == null) {
310 LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName()
311 + "{}, ignoring...", schemaTO.getAnyTypeClass());
312 } else {
313 anyTypeClass.add(schema);
314 schema.setAnyTypeClass(anyTypeClass);
315 }
316 } else if (schemaTO.getAnyTypeClass() == null && schema.getAnyTypeClass() != null) {
317 schema.getAnyTypeClass().getVirSchemas().remove(schema);
318 schema.setAnyTypeClass(null);
319 }
320
321 ExternalResource resource = resourceDAO.find(schemaTO.getResource());
322 if (resource == null) {
323 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSchemaDefinition);
324 sce.getElements().add("Resource " + schemaTO.getResource() + " not found");
325 throw sce;
326 }
327 AnyType anyType = anyTypeDAO.find(schemaTO.getAnyType());
328 if (anyType == null) {
329 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSchemaDefinition);
330 sce.getElements().add("AnyType " + schemaTO.getAnyType() + " not found");
331 throw sce;
332 }
333 Provision provision = resource.getProvisionByAnyType(anyType.getKey()).orElse(null);
334 if (provision == null) {
335 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSchemaDefinition);
336 sce.getElements().add("Provision for AnyType" + schemaTO.getAnyType()
337 + " not found in " + schemaTO.getResource());
338 throw sce;
339 }
340 schema.setResource(resource);
341 schema.setAnyType(anyType);
342
343 return virSchemaDAO.save(schema);
344 }
345
346 @Override
347 public VirSchema create(final VirSchemaTO schemaTO) {
348 return fill(entityFactory.newEntity(VirSchema.class), schemaTO);
349 }
350
351 @Override
352 public VirSchema update(final VirSchemaTO schemaTO, final VirSchema schema) {
353 return fill(schema, schemaTO);
354 }
355
356 @Override
357 public VirSchemaTO getVirSchemaTO(final String key) {
358 VirSchema schema = virSchemaDAO.find(key);
359 if (schema == null) {
360 throw new NotFoundException("Virtual Schema '" + key + '\'');
361 }
362
363 VirSchemaTO schemaTO = new VirSchemaTO();
364 schemaTO.setKey(schema.getKey());
365 schemaTO.setExtAttrName(schema.getExtAttrName());
366 schemaTO.setReadonly(schema.isReadonly());
367 schemaTO.getLabels().putAll(schema.getLabels());
368 schemaTO.setAnyTypeClass(schema.getAnyTypeClass() == null ? null : schema.getAnyTypeClass().getKey());
369 schemaTO.setResource(schema.getResource().getKey());
370 schemaTO.setAnyType(schema.getAnyType().getKey());
371 return schemaTO;
372 }
373 }