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.ext.client.common.ui.panels;
20  
21  import java.text.ParseException;
22  import java.util.Date;
23  import java.util.List;
24  import java.util.stream.Collectors;
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.commons.lang3.math.NumberUtils;
27  import org.apache.commons.lang3.time.FastDateFormat;
28  import org.apache.syncope.client.ui.commons.MapChoiceRenderer;
29  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
30  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
31  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
32  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
33  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
34  import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
35  import org.apache.syncope.common.lib.to.UserRequestForm;
36  import org.apache.syncope.common.lib.to.UserRequestFormProperty;
37  import org.apache.syncope.common.lib.to.UserRequestFormPropertyValue;
38  import org.apache.syncope.common.lib.types.IdRepoEntitlement;
39  import org.apache.wicket.ajax.AjaxRequestTarget;
40  import org.apache.wicket.ajax.markup.html.AjaxLink;
41  import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
42  import org.apache.wicket.markup.html.list.ListItem;
43  import org.apache.wicket.markup.html.list.ListView;
44  import org.apache.wicket.markup.html.panel.Panel;
45  import org.apache.wicket.model.IModel;
46  import org.apache.wicket.model.LoadableDetachableModel;
47  import org.apache.wicket.model.PropertyModel;
48  import org.slf4j.Logger;
49  import org.slf4j.LoggerFactory;
50  
51  public abstract class UserRequestFormPanel extends Panel {
52  
53      private static final long serialVersionUID = -8847854414429745216L;
54  
55      protected static final Logger LOG = LoggerFactory.getLogger(UserRequestFormPanel.class);
56  
57      public UserRequestFormPanel(final String id, final UserRequestForm form) {
58          this(id, form, true);
59      }
60  
61      public UserRequestFormPanel(final String id, final UserRequestForm form, final boolean showDetails) {
62          super(id);
63  
64          IModel<List<UserRequestFormProperty>> formProps = new LoadableDetachableModel<>() {
65  
66              private static final long serialVersionUID = 3169142472626817508L;
67  
68              @Override
69              protected List<UserRequestFormProperty> load() {
70                  return form.getProperties();
71              }
72          };
73  
74          ListView<UserRequestFormProperty> propView = new ListView<>("propView", formProps) {
75  
76              private static final long serialVersionUID = 9101744072914090143L;
77  
78              @Override
79              @SuppressWarnings({ "unchecked", "rawtypes" })
80              protected void populateItem(final ListItem<UserRequestFormProperty> item) {
81                  final UserRequestFormProperty prop = item.getModelObject();
82  
83                  String label = StringUtils.isBlank(prop.getName()) ? prop.getId() : prop.getName();
84  
85                  FieldPanel field;
86                  switch (prop.getType()) {
87                      case Boolean:
88                          field = new AjaxDropDownChoicePanel("value", label, new PropertyModel<String>(prop, "value") {
89  
90                              private static final long serialVersionUID = -3743432456095828573L;
91  
92                              @Override
93                              public String getObject() {
94                                  return StringUtils.isBlank(prop.getValue())
95                                          ? null
96                                          : prop.getValue().equals("true") ? "Yes" : "No";
97                              }
98  
99                              @Override
100                             public void setObject(final String object) {
101                                 prop.setValue(String.valueOf(object.equalsIgnoreCase("yes")));
102                             }
103 
104                         }, false).setChoices(List.of("Yes", "No"));
105                         break;
106 
107                     case Date:
108                         FastDateFormat formatter = FastDateFormat.getInstance(prop.getDatePattern());
109                         field = new AjaxDateTimeFieldPanel("value", label, new PropertyModel<>(prop, "value") {
110 
111                             private static final long serialVersionUID = -3743432456095828573L;
112 
113                             @Override
114                             public Date getObject() {
115                                 try {
116                                     return StringUtils.isBlank(prop.getValue())
117                                             ? null
118                                             : formatter.parse(prop.getValue());
119                                 } catch (ParseException e) {
120                                     LOG.error("Unparsable date: {}", prop.getValue(), e);
121                                     return null;
122                                 }
123                             }
124 
125                             @Override
126                             public void setObject(final Date object) {
127                                 prop.setValue(formatter.format(object));
128                             }
129                         }, formatter);
130                         break;
131 
132                     case Enum:
133                         field = new AjaxDropDownChoicePanel(
134                                 "value", label, new PropertyModel<String>(prop, "value"), false).
135                                 setChoiceRenderer(new MapChoiceRenderer(prop.getEnumValues().stream().
136                                         collect(Collectors.toMap(
137                                                 UserRequestFormPropertyValue::getKey,
138                                                 UserRequestFormPropertyValue::getValue)))).
139                                 setChoices(prop.getEnumValues().stream().
140                                         map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
141                         break;
142 
143                     case Dropdown:
144                         field = new AjaxDropDownChoicePanel(
145                                 "value", label, new PropertyModel<String>(prop, "value"), false).
146                                 setChoiceRenderer(new MapChoiceRenderer(prop.getDropdownValues().stream().
147                                         collect(Collectors.toMap(
148                                                 UserRequestFormPropertyValue::getKey,
149                                                 UserRequestFormPropertyValue::getValue)))).
150                                 setChoices(prop.getDropdownValues().stream().
151                                         map(UserRequestFormPropertyValue::getKey).collect(Collectors.toList()));
152                         break;
153 
154                     case Long:
155                         field = new AjaxSpinnerFieldPanel.Builder<Long>().build(
156                                 "value",
157                                 label,
158                                 Long.class,
159                                 new PropertyModel<>(prop, "value") {
160 
161                             private static final long serialVersionUID = -7688359318035249200L;
162 
163                             @Override
164                             public Long getObject() {
165                                 return StringUtils.isBlank(prop.getValue())
166                                         ? null
167                                         : NumberUtils.toLong(prop.getValue());
168                             }
169 
170                             @Override
171                             public void setObject(final Long object) {
172                                 prop.setValue(String.valueOf(object));
173                             }
174                         });
175                         break;
176 
177                     case Password:
178                         field = new AjaxPasswordFieldPanel("value", label, new PropertyModel<>(prop, "value"), false);
179                         break;
180 
181                     case String:
182                     default:
183                         field = new AjaxTextFieldPanel("value", label, new PropertyModel<>(prop, "value"), false);
184                         break;
185                 }
186 
187                 field.setReadOnly(!prop.isWritable());
188                 if (prop.isRequired()) {
189                     field.addRequiredLabel();
190                 }
191 
192                 item.add(field);
193             }
194         };
195 
196         AjaxLink<String> userDetails = new AjaxLink<>("userDetails") {
197 
198             private static final long serialVersionUID = -4804368561204623354L;
199 
200             @Override
201             public void onClick(final AjaxRequestTarget target) {
202                 viewDetails(target);
203             }
204         };
205         MetaDataRoleAuthorizationStrategy.authorize(userDetails, ENABLE, IdRepoEntitlement.USER_READ);
206 
207         boolean enabled = form.getUserTO() != null;
208         userDetails.setVisible(enabled && showDetails).setEnabled(enabled);
209 
210         add(propView);
211         add(userDetails);
212     }
213 
214     protected abstract void viewDetails(AjaxRequestTarget target);
215 }