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.wicket.markup.html.list;
20
21 import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.checkbox.bootstraptoggle.BootstrapToggle;
22 import de.agilecoders.wicket.extensions.markup.html.bootstrap.form.checkbox.bootstraptoggle.BootstrapToggleConfig;
23 import java.io.Serializable;
24 import java.util.List;
25 import org.apache.commons.lang3.ClassUtils;
26 import org.apache.commons.lang3.StringUtils;
27 import org.apache.syncope.client.console.commons.IdMConstants;
28 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
29 import org.apache.syncope.client.ui.commons.Constants;
30 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
31 import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
32 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
33 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
35 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
36 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
37 import org.apache.syncope.common.lib.types.ConnConfProperty;
38 import org.apache.wicket.ajax.AjaxRequestTarget;
39 import org.apache.wicket.markup.ComponentTag;
40 import org.apache.wicket.markup.head.IHeaderResponse;
41 import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
42 import org.apache.wicket.markup.html.form.CheckBox;
43 import org.apache.wicket.markup.html.form.FormComponent;
44 import org.apache.wicket.markup.html.form.PasswordTextField;
45 import org.apache.wicket.markup.html.list.ListItem;
46 import org.apache.wicket.markup.html.list.ListView;
47 import org.apache.wicket.model.IModel;
48 import org.apache.wicket.model.Model;
49 import org.apache.wicket.model.PropertyModel;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 public class ConnConfPropertyListView extends ListView<ConnConfProperty> {
54
55 private static final long serialVersionUID = -5239334900329150316L;
56
57 private static final Logger LOG = LoggerFactory.getLogger(ConnConfPropertyListView.class);
58
59 private final boolean withOverridable;
60
61 public ConnConfPropertyListView(
62 final String id,
63 final IModel<? extends List<ConnConfProperty>> model,
64 final boolean withOverridable) {
65
66 super(id, model);
67 this.withOverridable = withOverridable;
68 }
69
70 @Override
71 @SuppressWarnings({ "unchecked", "rawtypes" })
72 protected void populateItem(final ListItem<ConnConfProperty> item) {
73 final ConnConfProperty property = item.getModelObject();
74
75 final String label = StringUtils.isBlank(property.getSchema().getDisplayName())
76 ? property.getSchema().getName() : property.getSchema().getDisplayName();
77
78 final FieldPanel<? extends Serializable> field;
79 boolean required = false;
80 boolean isArray = false;
81
82 if (property.getSchema().isConfidential()
83 || IdMConstants.GUARDED_STRING.equalsIgnoreCase(property.getSchema().getType())
84 || IdMConstants.GUARDED_BYTE_ARRAY.equalsIgnoreCase(property.getSchema().getType())) {
85
86 field = new AjaxPasswordFieldPanel("panel", label, Model.of(), false);
87 ((PasswordTextField) field.getField()).setResetPassword(false);
88
89 required = property.getSchema().isRequired();
90 } else {
91 Class<?> propertySchemaClass;
92 try {
93 propertySchemaClass = ClassUtils.getClass(property.getSchema().getType());
94 if (ClassUtils.isPrimitiveOrWrapper(propertySchemaClass)) {
95 propertySchemaClass = ClassUtils.primitiveToWrapper(propertySchemaClass);
96 }
97 } catch (ClassNotFoundException e) {
98 LOG.error("Error parsing attribute type", e);
99 propertySchemaClass = String.class;
100 }
101
102 if (ClassUtils.isAssignable(Number.class, propertySchemaClass)) {
103 @SuppressWarnings("unchecked")
104 Class<Number> numberClass = (Class<Number>) propertySchemaClass;
105 field = new AjaxSpinnerFieldPanel.Builder<>().build("panel", label, numberClass, new Model<>());
106 required = property.getSchema().isRequired();
107 } else if (ClassUtils.isAssignable(Boolean.class, propertySchemaClass)) {
108 field = new AjaxCheckBoxPanel("panel", label, new Model<>());
109 } else {
110 field = new AjaxTextFieldPanel("panel", label, new Model<>());
111 required = property.getSchema().isRequired();
112 }
113
114 if (propertySchemaClass.isArray()) {
115 isArray = true;
116 }
117 }
118
119 field.setIndex(item.getIndex());
120 field.setTitle(property.getSchema().getHelpMessage(), true);
121
122 final AbstractFieldPanel<? extends Serializable> fieldPanel;
123 if (isArray) {
124 final MultiFieldPanel multiFieldPanel = new MultiFieldPanel.Builder(
125 new PropertyModel<>(property, "values")).setEventTemplate(true).build("panel", label, field);
126 item.add(multiFieldPanel);
127 fieldPanel = multiFieldPanel;
128 } else {
129 setNewFieldModel(field, property.getValues());
130 item.add(field);
131 fieldPanel = field;
132 }
133
134 if (required) {
135 fieldPanel.addRequiredLabel();
136 }
137
138 if (withOverridable) {
139 fieldPanel.showExternAction(addCheckboxToggle(property));
140 }
141 }
142
143 @SuppressWarnings({ "unchecked", "rawtypes" })
144 private static void setNewFieldModel(final FieldPanel field, final List<Object> values) {
145 field.setNewModel(values);
146 }
147
148 private static FormComponent<?> addCheckboxToggle(final ConnConfProperty property) {
149 final BootstrapToggleConfig config = new BootstrapToggleConfig().
150 withOnStyle(BootstrapToggleConfig.Style.success).
151 withOffStyle(BootstrapToggleConfig.Style.danger).
152 withSize(BootstrapToggleConfig.Size.mini);
153
154 return new BootstrapToggle("externalAction", new PropertyModel<>(property, "overridable"), config) {
155
156 private static final long serialVersionUID = -875219845189261873L;
157
158 @Override
159 protected CheckBox newCheckBox(final String id, final IModel<Boolean> model) {
160 final CheckBox checkBox = super.newCheckBox(id, model);
161 checkBox.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
162
163 private static final long serialVersionUID = -1107858522700306810L;
164
165 @Override
166 protected void onUpdate(final AjaxRequestTarget target) {
167 }
168 });
169 return checkBox;
170 }
171
172 @Override
173 protected IModel<String> getOnLabel() {
174 return Model.of("Override");
175 }
176
177 @Override
178 protected IModel<String> getOffLabel() {
179 return Model.of("Override?");
180 }
181
182 @Override
183 protected void onComponentTag(final ComponentTag tag) {
184 super.onComponentTag(tag);
185 tag.append("class", "overridable", " ");
186 }
187 };
188 }
189
190 @Override
191 public void renderHead(final IHeaderResponse response) {
192 super.renderHead(response);
193 if (getModelObject().isEmpty()) {
194 response.render(OnDomReadyHeaderItem.forScript(
195 String.format("$('#emptyPlaceholder').append(\"%s\")", getString("property.empty.list"))));
196 }
197 }
198 }