1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.client.console.panels;
20
21 import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
22 import java.util.ArrayList;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.stream.Collectors;
26 import org.apache.commons.lang3.BooleanUtils;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.syncope.client.console.commons.PropertyList;
29 import org.apache.syncope.client.console.rest.ImplementationRestClient;
30 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
31 import org.apache.syncope.client.ui.commons.Constants;
32 import org.apache.syncope.client.ui.commons.MIMETypesLoader;
33 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
35 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
36 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
37 import org.apache.syncope.common.lib.SyncopeConstants;
38 import org.apache.syncope.common.lib.to.ImplementationTO;
39 import org.apache.syncope.common.lib.to.PlainSchemaTO;
40 import org.apache.syncope.common.lib.types.AttrSchemaType;
41 import org.apache.syncope.common.lib.types.CipherAlgorithm;
42 import org.apache.syncope.common.lib.types.IdRepoImplementationType;
43 import org.apache.wicket.ajax.AjaxRequestTarget;
44 import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
45 import org.apache.wicket.markup.html.WebMarkupContainer;
46 import org.apache.wicket.markup.html.form.DropDownChoice;
47 import org.apache.wicket.model.IModel;
48 import org.apache.wicket.model.LoadableDetachableModel;
49 import org.apache.wicket.model.Model;
50 import org.apache.wicket.model.PropertyModel;
51 import org.apache.wicket.spring.injection.annot.SpringBean;
52 import org.apache.wicket.util.string.Strings;
53
54 public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
55
56 private static final long serialVersionUID = 5378100729213456451L;
57
58 @SpringBean
59 protected MIMETypesLoader mimeTypesLoader;
60
61 @SpringBean
62 protected ImplementationRestClient implementationRestClient;
63
64 protected final MultiFieldPanel<String> enumerationValues;
65
66 protected final MultiFieldPanel<String> enumerationKeys;
67
68 protected final AjaxDropDownChoicePanel<String> validator;
69
70 protected final AjaxDropDownChoicePanel<AttrSchemaType> type;
71
72 public PlainSchemaDetails(final String id, final PlainSchemaTO schemaTO) {
73 super(id, schemaTO);
74
75 type = new AjaxDropDownChoicePanel<>("type", getString("type"), new PropertyModel<>(schemaTO, "type"));
76
77 boolean isCreate = schemaTO == null || schemaTO.getKey() == null || schemaTO.getKey().isEmpty();
78
79 type.setChoices(List.of(AttrSchemaType.values()));
80 type.setEnabled(isCreate);
81 type.addRequiredLabel();
82 add(type);
83
84
85 AjaxTextFieldPanel conversionPattern = new AjaxTextFieldPanel("conversionPattern",
86 getString("conversionPattern"), new PropertyModel<>(schemaTO, "conversionPattern"));
87 add(conversionPattern);
88
89 WebMarkupContainer conversionParams = new WebMarkupContainer("conversionParams");
90 conversionParams.setOutputMarkupPlaceholderTag(true);
91 conversionParams.add(conversionPattern);
92 add(conversionParams);
93
94 WebMarkupContainer typeParams = new WebMarkupContainer("typeParams");
95 typeParams.setOutputMarkupPlaceholderTag(true);
96
97
98 AjaxTextFieldPanel enumerationValuesPanel = new AjaxTextFieldPanel("panel",
99 "enumerationValues", new Model<>(null));
100
101 enumerationValues = new MultiFieldPanel.Builder<>(
102 new PropertyModel<List<String>>(schemaTO, "enumerationValues") {
103
104 private static final long serialVersionUID = -4953564762272833993L;
105
106 @Override
107 public PropertyList<PlainSchemaTO> getObject() {
108 return new PropertyList<>() {
109
110 @Override
111 public String getValues() {
112 return schemaTO.getEnumerationValues();
113 }
114
115 @Override
116 public void setValues(final List<String> list) {
117 schemaTO.setEnumerationValues(getEnumValuesAsString(list));
118 }
119 };
120 }
121
122 @Override
123 public void setObject(final List<String> object) {
124 schemaTO.setEnumerationValues(PropertyList.getEnumValuesAsString(object));
125 }
126 }) {
127
128 private static final long serialVersionUID = -8752965211744734798L;
129
130 @Override
131 protected String newModelObject() {
132 return StringUtils.EMPTY;
133 }
134
135 }.build(
136 "enumerationValues",
137 "enumerationValues",
138 enumerationValuesPanel);
139
140 enumerationKeys = new MultiFieldPanel.Builder<String>(
141 new PropertyModel<List<String>>(schemaTO, "enumerationKeys") {
142
143 private static final long serialVersionUID = -4953564762272833993L;
144
145 @Override
146 public PropertyList<PlainSchemaTO> getObject() {
147 return new PropertyList<PlainSchemaTO>() {
148
149 @Override
150 public String getValues() {
151 return schemaTO.getEnumerationKeys();
152 }
153
154 @Override
155 public void setValues(final List<String> list) {
156 schemaTO.setEnumerationKeys(PropertyList.getEnumValuesAsString(list));
157 }
158 };
159 }
160
161 @Override
162 public void setObject(final List<String> object) {
163 schemaTO.setEnumerationKeys(PropertyList.getEnumValuesAsString(object));
164 }
165 }) {
166
167 private static final long serialVersionUID = -8752965211744734798L;
168
169 @Override
170 protected String newModelObject() {
171 return StringUtils.EMPTY;
172 }
173
174 }.build(
175 "enumerationKeys",
176 "enumerationKeys",
177 new AjaxTextFieldPanel("panel", "enumerationKeys", new Model<>(null)));
178
179 WebMarkupContainer enumParams = new WebMarkupContainer("enumParams");
180 enumParams.setOutputMarkupPlaceholderTag(true);
181 enumParams.add(enumerationValues);
182 enumParams.add(enumerationKeys);
183 typeParams.add(enumParams);
184
185
186 AjaxTextFieldPanel secretKey = new AjaxTextFieldPanel("secretKey",
187 getString("secretKey"), new PropertyModel<>(schemaTO, "secretKey"));
188
189 AjaxDropDownChoicePanel<CipherAlgorithm> cipherAlgorithm = new AjaxDropDownChoicePanel<>(
190 "cipherAlgorithm", getString("cipherAlgorithm"),
191 new PropertyModel<>(schemaTO, "cipherAlgorithm"));
192 cipherAlgorithm.setChoices(List.of(CipherAlgorithm.values()));
193
194 AjaxCheckBoxPanel transparentEncryption = new AjaxCheckBoxPanel(
195 "transparentEncryption", "transparentEncryption", new Model<Boolean>() {
196
197 private static final long serialVersionUID = 5636572627689425575L;
198
199 @Override
200 public Boolean getObject() {
201 return SyncopeConstants.ENCRYPTED_DECODE_CONVERSION_PATTERN.equals(schemaTO.getConversionPattern());
202 }
203
204 @Override
205 public void setObject(final Boolean object) {
206 schemaTO.setConversionPattern(BooleanUtils.isTrue(object)
207 ? SyncopeConstants.ENCRYPTED_DECODE_CONVERSION_PATTERN
208 : null);
209 }
210 }, true);
211
212 WebMarkupContainer encryptedParams = new WebMarkupContainer("encryptedParams");
213 encryptedParams.setOutputMarkupPlaceholderTag(true);
214 encryptedParams.add(secretKey);
215 encryptedParams.add(cipherAlgorithm);
216 encryptedParams.add(transparentEncryption);
217
218 typeParams.add(encryptedParams);
219
220
221 AjaxTextFieldPanel mimeType = new AjaxTextFieldPanel("mimeType",
222 getString("mimeType"), new PropertyModel<>(schemaTO, "mimeType"));
223
224 WebMarkupContainer binaryParams = new WebMarkupContainer("binaryParams");
225 binaryParams.setOutputMarkupPlaceholderTag(true);
226 binaryParams.add(mimeType);
227 typeParams.add(binaryParams);
228 add(typeParams);
229
230
231 showHide(schemaTO, type,
232 conversionParams, conversionPattern,
233 enumParams, enumerationValuesPanel, enumerationValues, enumerationKeys,
234 encryptedParams, secretKey, cipherAlgorithm,
235 binaryParams, mimeType);
236
237 type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
238
239 private static final long serialVersionUID = -1107858522700306810L;
240
241 @Override
242 protected void onUpdate(final AjaxRequestTarget target) {
243 PlainSchemaDetails.this.showHide(schemaTO, type,
244 conversionParams, conversionPattern,
245 enumParams, enumerationValuesPanel, enumerationValues, enumerationKeys,
246 encryptedParams, secretKey, cipherAlgorithm,
247 binaryParams, mimeType);
248 target.add(conversionParams);
249 target.add(typeParams);
250 target.add(validator);
251 }
252 });
253
254 IModel<List<String>> validators = new LoadableDetachableModel<List<String>>() {
255
256 private static final long serialVersionUID = 5275935387613157437L;
257
258 @Override
259 protected List<String> load() {
260 return implementationRestClient.list(IdRepoImplementationType.VALIDATOR).stream().
261 map(ImplementationTO::getKey).sorted().collect(Collectors.toList());
262 }
263 };
264 validator = new AjaxDropDownChoicePanel<>("validator",
265 getString("validator"), new PropertyModel<>(schemaTO, "validator"));
266 validator.setOutputMarkupId(true);
267 ((DropDownChoice) validator.getField()).setNullValid(true);
268 validator.setChoices(validators.getObject());
269 add(validator);
270
271 AutoCompleteTextField<String> mandatoryCondition = new AutoCompleteTextField<String>(
272 "mandatoryCondition", new PropertyModel<>(schemaTO, "mandatoryCondition")) {
273
274 private static final long serialVersionUID = -2428903969518079100L;
275
276 @Override
277 protected Iterator<String> getChoices(final String input) {
278 List<String> choices = new ArrayList<>();
279
280 if (Strings.isEmpty(input)) {
281 choices = List.of();
282 } else if ("true".startsWith(input.toLowerCase())) {
283 choices.add("true");
284 } else if ("false".startsWith(input.toLowerCase())) {
285 choices.add("false");
286 }
287
288 return choices.iterator();
289 }
290 };
291 mandatoryCondition.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
292
293 private static final long serialVersionUID = -1107858522700306810L;
294
295 @Override
296 protected void onUpdate(final AjaxRequestTarget target) {
297 }
298 });
299 add(mandatoryCondition);
300
301 add(Constants.getJEXLPopover(this, TooltipConfig.Placement.right));
302
303 add(new AjaxCheckBoxPanel(
304 "multivalue", getString("multivalue"), new PropertyModel<>(schemaTO, "multivalue")));
305
306 add(new AjaxCheckBoxPanel(
307 "readonly", getString("readonly"), new PropertyModel<>(schemaTO, "readonly")));
308
309 add(new AjaxCheckBoxPanel("uniqueConstraint",
310 getString("uniqueConstraint"), new PropertyModel<>(schemaTO, "uniqueConstraint")).
311 setEnabled(isCreate));
312 }
313
314 private void showHide(final PlainSchemaTO schema, final AjaxDropDownChoicePanel<AttrSchemaType> type,
315 final WebMarkupContainer conversionParams, final AjaxTextFieldPanel conversionPattern,
316 final WebMarkupContainer enumParams, final AjaxTextFieldPanel enumerationValuesPanel,
317 final MultiFieldPanel<String> enumerationValues, final MultiFieldPanel<String> enumerationKeys,
318 final WebMarkupContainer encryptedParams,
319 final AjaxTextFieldPanel secretKey, final AjaxDropDownChoicePanel<CipherAlgorithm> cipherAlgorithm,
320 final WebMarkupContainer binaryParams, final AjaxTextFieldPanel mimeType) {
321
322 int typeOrdinal = -1;
323 try {
324 typeOrdinal = Integer.parseInt(type.getField().getValue());
325 } catch (NumberFormatException e) {
326 LOG.error("Invalid value found: {}", type.getField().getValue(), e);
327 }
328 if (AttrSchemaType.Long.ordinal() == typeOrdinal
329 || AttrSchemaType.Double.ordinal() == typeOrdinal
330 || AttrSchemaType.Date.ordinal() == typeOrdinal) {
331
332 conversionParams.setVisible(true);
333
334 enumParams.setVisible(false);
335 if (enumerationValuesPanel.isRequired()) {
336 enumerationValuesPanel.removeRequiredLabel();
337 }
338 enumerationValues.setModelObject(PropertyList.getEnumValuesAsList(null));
339 enumerationKeys.setModelObject(PropertyList.getEnumValuesAsList(null));
340
341 encryptedParams.setVisible(false);
342 if (secretKey.isRequired()) {
343 secretKey.removeRequiredLabel();
344 }
345 secretKey.setModelObject(null);
346 if (cipherAlgorithm.isRequired()) {
347 cipherAlgorithm.removeRequiredLabel();
348 }
349 cipherAlgorithm.setModelObject(null);
350
351 binaryParams.setVisible(false);
352 mimeType.setModelObject(null);
353 mimeType.setChoices(null);
354 } else if (AttrSchemaType.Enum.ordinal() == typeOrdinal) {
355 conversionParams.setVisible(false);
356 conversionPattern.setModelObject(null);
357
358 enumParams.setVisible(true);
359 if (!enumerationValuesPanel.isRequired()) {
360 enumerationValuesPanel.addRequiredLabel();
361 }
362 enumerationValues.setModelObject(PropertyList.getEnumValuesAsList(schema.getEnumerationValues()));
363 enumerationKeys.setModelObject(PropertyList.getEnumValuesAsList(schema.getEnumerationKeys()));
364
365 encryptedParams.setVisible(false);
366 if (secretKey.isRequired()) {
367 secretKey.removeRequiredLabel();
368 }
369 secretKey.setModelObject(null);
370 if (cipherAlgorithm.isRequired()) {
371 cipherAlgorithm.removeRequiredLabel();
372 }
373 cipherAlgorithm.setModelObject(null);
374
375 binaryParams.setVisible(false);
376 mimeType.setModelObject(null);
377 mimeType.setChoices(null);
378 } else if (AttrSchemaType.Encrypted.ordinal() == typeOrdinal) {
379 conversionParams.setVisible(false);
380
381 enumParams.setVisible(false);
382 if (enumerationValuesPanel.isRequired()) {
383 enumerationValuesPanel.removeRequiredLabel();
384 }
385 enumerationValues.setModelObject(PropertyList.getEnumValuesAsList(null));
386 enumerationKeys.setModelObject(PropertyList.getEnumValuesAsList(null));
387
388 encryptedParams.setVisible(true);
389 if (!secretKey.isRequired()) {
390 secretKey.addRequiredLabel();
391 }
392 if (cipherAlgorithm.isRequired()) {
393 cipherAlgorithm.addRequiredLabel();
394 }
395
396 binaryParams.setVisible(false);
397 mimeType.setModelObject(null);
398 mimeType.setChoices(null);
399 } else if (AttrSchemaType.Binary.ordinal() == typeOrdinal) {
400 conversionParams.setVisible(false);
401 conversionPattern.setModelObject(null);
402
403 enumParams.setVisible(false);
404 if (enumerationValuesPanel.isRequired()) {
405 enumerationValuesPanel.removeRequiredLabel();
406 }
407 enumerationValues.setModelObject(PropertyList.getEnumValuesAsList(null));
408 enumerationKeys.setModelObject(PropertyList.getEnumValuesAsList(null));
409
410 encryptedParams.setVisible(false);
411 if (secretKey.isRequired()) {
412 secretKey.removeRequiredLabel();
413 }
414 secretKey.setModelObject(null);
415 if (cipherAlgorithm.isRequired()) {
416 cipherAlgorithm.removeRequiredLabel();
417 }
418 cipherAlgorithm.setModelObject(null);
419
420 binaryParams.setVisible(true);
421 mimeType.setChoices(mimeTypesLoader.getMimeTypes());
422
423 schema.setValidator("BinaryValidator");
424 } else {
425 conversionParams.setVisible(false);
426 conversionPattern.setModelObject(null);
427
428 enumParams.setVisible(false);
429 if (enumerationValuesPanel.isRequired()) {
430 enumerationValuesPanel.removeRequiredLabel();
431 }
432 enumerationValues.setModelObject(PropertyList.getEnumValuesAsList(null));
433 enumerationKeys.setModelObject(PropertyList.getEnumValuesAsList(null));
434
435 encryptedParams.setVisible(false);
436 if (secretKey.isRequired()) {
437 secretKey.removeRequiredLabel();
438 }
439 secretKey.setModelObject(null);
440 if (cipherAlgorithm.isRequired()) {
441 cipherAlgorithm.removeRequiredLabel();
442 }
443 cipherAlgorithm.setModelObject(null);
444
445 binaryParams.setVisible(false);
446 mimeType.setModelObject(null);
447 mimeType.setChoices(null);
448 }
449
450 if (type.isEnabled() && AttrSchemaType.Binary.ordinal() != typeOrdinal) {
451 schema.setValidator(null);
452 }
453 }
454 }