View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.client.console.tasks;
20  
21  import java.io.Serializable;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Optional;
25  import java.util.regex.Pattern;
26  import java.util.regex.PatternSyntaxException;
27  import org.apache.commons.lang3.StringUtils;
28  import org.apache.syncope.client.console.SyncopeConsoleSession;
29  import org.apache.syncope.client.console.panels.AbstractModalPanel;
30  import org.apache.syncope.client.console.rest.TaskRestClient;
31  import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
32  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
33  import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
34  import org.apache.syncope.client.ui.commons.Constants;
35  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
36  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
37  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
38  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxGridFieldPanel;
39  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
40  import org.apache.syncope.client.ui.commons.pages.BaseWebPage;
41  import org.apache.syncope.common.lib.form.FormPropertyType;
42  import org.apache.syncope.common.lib.to.FormPropertyDefTO;
43  import org.apache.syncope.common.lib.to.MacroTaskTO;
44  import org.apache.syncope.common.lib.types.TaskType;
45  import org.apache.wicket.PageReference;
46  import org.apache.wicket.ajax.AjaxRequestTarget;
47  import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
48  import org.apache.wicket.markup.html.WebMarkupContainer;
49  import org.apache.wicket.markup.html.list.ListItem;
50  import org.apache.wicket.markup.html.list.ListView;
51  import org.apache.wicket.model.IModel;
52  import org.apache.wicket.model.PropertyModel;
53  import org.apache.wicket.model.util.ListModel;
54  import org.apache.wicket.spring.injection.annot.SpringBean;
55  import org.apache.wicket.validation.IValidatable;
56  import org.apache.wicket.validation.IValidator;
57  import org.apache.wicket.validation.ValidationError;
58  
59  public class FormPropertyDefsPanel extends AbstractModalPanel<MacroTaskTO> {
60  
61      private static final long serialVersionUID = 6991001927367507753L;
62  
63      @SpringBean
64      protected TaskRestClient taskRestClient;
65  
66      protected final MacroTaskTO task;
67  
68      protected final IModel<List<FormPropertyDefTO>> model;
69  
70      public FormPropertyDefsPanel(
71              final MacroTaskTO task,
72              final BaseModal<MacroTaskTO> modal,
73              final PageReference pageRef) {
74  
75          super(modal, pageRef);
76          this.task = task;
77  
78          WebMarkupContainer propertyDefContainer = new WebMarkupContainer("propertyDefContainer");
79          add(propertyDefContainer.setOutputMarkupId(true));
80  
81          model = new ListModel<>(new ArrayList<>());
82          model.getObject().addAll(task.getFormPropertyDefs());
83  
84          ListView<FormPropertyDefTO> propertyDefs = new ListView<>("propertyDefs", model) {
85  
86              private static final long serialVersionUID = 1814616131938968887L;
87  
88              @Override
89              protected void populateItem(final ListItem<FormPropertyDefTO> item) {
90                  FormPropertyDefTO fpd = item.getModelObject();
91  
92                  AjaxTextFieldPanel key = new AjaxTextFieldPanel(
93                          "key",
94                          "key",
95                          new PropertyModel<>(fpd, "key"),
96                          true);
97                  item.add(key.setRequired(true).hideLabel());
98  
99                  AjaxTextFieldPanel name = new AjaxTextFieldPanel(
100                         "name",
101                         "name",
102                         new PropertyModel<>(fpd, "name"),
103                         true);
104                 item.add(name.setRequired(true).hideLabel());
105 
106                 AjaxCheckBoxPanel readable = new AjaxCheckBoxPanel(
107                         "readable",
108                         "readable",
109                         new PropertyModel<>(fpd, "readable"),
110                         true);
111                 item.add(readable.hideLabel());
112 
113                 AjaxCheckBoxPanel writable = new AjaxCheckBoxPanel(
114                         "writable",
115                         "writable",
116                         new PropertyModel<>(fpd, "writable"),
117                         true);
118                 item.add(writable.hideLabel());
119 
120                 AjaxCheckBoxPanel required = new AjaxCheckBoxPanel(
121                         "required",
122                         "required",
123                         new PropertyModel<>(fpd, "required"),
124                         true);
125                 item.add(required.hideLabel());
126 
127                 AjaxDropDownChoicePanel<FormPropertyType> type = new AjaxDropDownChoicePanel<>(
128                         "type",
129                         "type",
130                         new PropertyModel<>(fpd, "type"),
131                         true);
132                 type.setChoices(List.of(FormPropertyType.values())).setNullValid(false);
133                 item.add(type.setRequired(true).hideLabel());
134 
135                 AjaxTextFieldPanel stringRegEx = new AjaxTextFieldPanel(
136                         "stringRegEx",
137                         "stringRegEx",
138                         new IModel<String>() {
139 
140                     private static final long serialVersionUID = 1015030402166681242L;
141 
142                     @Override
143                     public String getObject() {
144                         return Optional.ofNullable(fpd.getStringRegEx()).map(Pattern::pattern).orElse(null);
145                     }
146 
147                     @Override
148                     public void setObject(final String object) {
149                         fpd.setStringRegEx(Optional.ofNullable(object).map(Pattern::compile).orElse(null));
150                     }
151                 }, true);
152                 stringRegEx.getField().add(new IValidator<String>() {
153 
154                     private static final long serialVersionUID = 3978328825079032964L;
155 
156                     @Override
157                     public void validate(final IValidatable<String> validatable) {
158                         try {
159                             Pattern.compile(validatable.getValue());
160                         } catch (PatternSyntaxException e) {
161                             validatable.error(new ValidationError(fpd.getKey() + ": invalid RegEx"));
162                         }
163                     }
164                 });
165                 stringRegEx.setVisible(fpd.getType() == FormPropertyType.String);
166                 item.add(stringRegEx.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
167 
168                 AjaxTextFieldPanel datePattern = new AjaxTextFieldPanel(
169                         "datePattern",
170                         "datePattern",
171                         new PropertyModel<>(fpd, "datePattern"),
172                         true);
173                 datePattern.setVisible(fpd.getType() == FormPropertyType.Date);
174                 item.add(datePattern.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
175 
176                 AjaxGridFieldPanel<String, String, String> enumValues = new AjaxGridFieldPanel<>(
177                         "enumValues",
178                         "enumValues",
179                         new PropertyModel<>(fpd, "enumValues"));
180                 enumValues.setVisible(fpd.getType() == FormPropertyType.Enum);
181                 item.add(enumValues.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
182 
183                 WebMarkupContainer dropdownConf = new WebMarkupContainer("dropdownConf");
184                 dropdownConf.setVisible(fpd.getType() == FormPropertyType.Dropdown);
185                 item.add(dropdownConf.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
186                 AjaxCheckBoxPanel dropdownSingleSelection = new AjaxCheckBoxPanel(
187                         "dropdownSingleSelection",
188                         "dropdownSingleSelection",
189                         new PropertyModel<>(fpd, "dropdownSingleSelection"),
190                         true);
191                 dropdownConf.add(dropdownSingleSelection.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
192                 AjaxCheckBoxPanel dropdownFreeForm = new AjaxCheckBoxPanel(
193                         "dropdownFreeForm",
194                         "dropdownFreeForm",
195                         new PropertyModel<>(fpd, "dropdownFreeForm"),
196                         true);
197                 dropdownConf.add(dropdownFreeForm.setOutputMarkupId(true).setOutputMarkupPlaceholderTag(true));
198 
199                 type.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
200 
201                     private static final long serialVersionUID = -1107858522700306810L;
202 
203                     @Override
204                     protected void onUpdate(final AjaxRequestTarget target) {
205                         switch (type.getModelObject()) {
206                             case String:
207                                 stringRegEx.setVisible(true);
208                                 datePattern.setVisible(false);
209                                 enumValues.setVisible(false);
210                                 fpd.getEnumValues().clear();
211                                 dropdownConf.setVisible(false);
212                                 break;
213 
214                             case Date:
215                                 stringRegEx.setVisible(false);
216                                 fpd.setStringRegEx(null);
217                                 datePattern.setVisible(true);
218                                 enumValues.setVisible(false);
219                                 fpd.getEnumValues().clear();
220                                 dropdownConf.setVisible(false);
221                                 break;
222 
223                             case Enum:
224                                 stringRegEx.setVisible(false);
225                                 fpd.setStringRegEx(null);
226                                 datePattern.setVisible(false);
227                                 enumValues.setVisible(true);
228                                 dropdownConf.setVisible(false);
229                                 break;
230 
231                             case Dropdown:
232                                 stringRegEx.setVisible(false);
233                                 fpd.setStringRegEx(null);
234                                 datePattern.setVisible(false);
235                                 enumValues.setVisible(false);
236                                 fpd.getEnumValues().clear();
237                                 dropdownConf.setVisible(true);
238                                 break;
239 
240                             default:
241                                 stringRegEx.setVisible(false);
242                                 fpd.setStringRegEx(null);
243                                 datePattern.setVisible(false);
244                                 enumValues.setVisible(false);
245                                 fpd.getEnumValues().clear();
246                                 dropdownConf.setVisible(false);
247                         }
248 
249                         target.add(stringRegEx);
250                         target.add(datePattern);
251                         target.add(enumValues);
252                         target.add(dropdownConf);
253                     }
254                 });
255 
256                 ActionsPanel<Serializable> actions = new ActionsPanel<>("actions", null);
257                 item.add(actions);
258                 actions.add(new ActionLink<>() {
259 
260                     private static final long serialVersionUID = -3722207913631435501L;
261 
262                     @Override
263                     public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
264                         model.getObject().remove(item.getIndex());
265 
266                         item.getParent().removeAll();
267                         target.add(propertyDefContainer);
268                     }
269                 }, ActionLink.ActionType.DELETE, StringUtils.EMPTY, true).hideLabel();
270                 if (model.getObject().size() > 1) {
271                     if (item.getIndex() > 0) {
272                         actions.add(new ActionLink<>() {
273 
274                             private static final long serialVersionUID = 2041211756396714619L;
275 
276                             @Override
277                             public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
278                                 FormPropertyDefTO pre = model.getObject().get(item.getIndex() - 1);
279                                 model.getObject().set(item.getIndex(), pre);
280                                 model.getObject().set(item.getIndex() - 1, fpd);
281 
282                                 item.getParent().removeAll();
283                                 target.add(propertyDefContainer);
284                             }
285                         }, ActionLink.ActionType.UP, StringUtils.EMPTY).hideLabel();
286                     }
287                     if (item.getIndex() < model.getObject().size() - 1) {
288                         actions.add(new ActionLink<>() {
289 
290                             private static final long serialVersionUID = 2041211756396714619L;
291 
292                             @Override
293                             public void onClick(final AjaxRequestTarget target, final Serializable ignore) {
294                                 FormPropertyDefTO post = model.getObject().get(item.getIndex() + 1);
295                                 model.getObject().set(item.getIndex(), post);
296                                 model.getObject().set(item.getIndex() + 1, fpd);
297 
298                                 item.getParent().removeAll();
299                                 target.add(propertyDefContainer);
300                             }
301                         }, ActionLink.ActionType.DOWN, StringUtils.EMPTY).hideLabel();
302                     }
303                 }
304             }
305         };
306         propertyDefContainer.add(propertyDefs.setReuseItems(true));
307 
308         IndicatingAjaxButton addPropertyDef = new IndicatingAjaxButton("addPropertyDef") {
309 
310             private static final long serialVersionUID = -4804368561204623354L;
311 
312             @Override
313             protected void onSubmit(final AjaxRequestTarget target) {
314                 model.getObject().add(new FormPropertyDefTO());
315                 target.add(propertyDefContainer);
316             }
317         };
318         addPropertyDef.setDefaultFormProcessing(false);
319         propertyDefContainer.add(addPropertyDef);
320     }
321 
322     @Override
323     public void onSubmit(final AjaxRequestTarget target) {
324         task.getFormPropertyDefs().clear();
325         task.getFormPropertyDefs().addAll(model.getObject());
326         try {
327             taskRestClient.update(TaskType.MACRO, task);
328 
329             SyncopeConsoleSession.get().success(getString(Constants.OPERATION_SUCCEEDED));
330             modal.close(target);
331         } catch (Exception e) {
332             LOG.error("While updating Macro Task {}", task.getKey(), e);
333             SyncopeConsoleSession.get().onException(e);
334         }
335         ((BaseWebPage) pageRef.getPage()).getNotificationPanel().refresh(target);
336     }
337 }