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.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 }