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.wizards.any;
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.util.ArrayList;
24 import java.util.Collection;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.stream.Collectors;
30 import org.apache.syncope.client.console.commons.LinkedAccountPlainAttrProperty;
31 import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
32 import org.apache.syncope.client.ui.commons.Constants;
33 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
34 import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel;
35 import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
36 import org.apache.syncope.client.ui.commons.wicket.markup.html.bootstrap.tabs.Accordion;
37 import org.apache.syncope.client.ui.commons.wizards.AjaxWizard;
38 import org.apache.syncope.client.ui.commons.wizards.any.EntityWrapper;
39 import org.apache.syncope.common.lib.Attr;
40 import org.apache.syncope.common.lib.EntityTOUtils;
41 import org.apache.syncope.common.lib.to.AnyTO;
42 import org.apache.syncope.common.lib.to.LinkedAccountTO;
43 import org.apache.syncope.common.lib.to.PlainSchemaTO;
44 import org.apache.syncope.common.lib.to.UserTO;
45 import org.apache.syncope.common.lib.types.SchemaType;
46 import org.apache.wicket.ajax.AjaxRequestTarget;
47 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
48 import org.apache.wicket.markup.ComponentTag;
49 import org.apache.wicket.markup.html.WebMarkupContainer;
50 import org.apache.wicket.markup.html.form.CheckBox;
51 import org.apache.wicket.markup.html.form.FormComponent;
52 import org.apache.wicket.markup.html.list.ListItem;
53 import org.apache.wicket.markup.html.list.ListView;
54 import org.apache.wicket.model.IModel;
55 import org.apache.wicket.model.Model;
56 import org.apache.wicket.model.PropertyModel;
57 import org.apache.wicket.model.ResourceModel;
58
59 public class LinkedAccountPlainAttrsPanel extends AbstractAttrsWizardStep<PlainSchemaTO> {
60
61 private static final long serialVersionUID = -6664931684253730934L;
62
63 protected final LinkedAccountTO linkedAccountTO;
64
65 protected final UserTO userTO;
66
67 protected final Set<Attr> fixedAttrs = new HashSet<>();
68
69 protected final List<LinkedAccountPlainAttrProperty> accountPlainAttrProperties = new ArrayList<>();
70
71 public <T extends AnyTO> LinkedAccountPlainAttrsPanel(
72 final EntityWrapper<LinkedAccountTO> modelObject,
73 final UserTO userTO,
74 final List<String> anyTypeClasses,
75 final List<String> whichPlainAttrs) throws IllegalArgumentException {
76
77 super(userTO,
78 AjaxWizard.Mode.EDIT,
79 anyTypeClasses,
80 whichPlainAttrs);
81
82 this.linkedAccountTO = modelObject.getInnerObject();
83 this.fixedAttrs.addAll(this.linkedAccountTO.getPlainAttrs().stream().
84 filter(attrTO -> checkIsReadonlyAttr(attrTO.getSchema())).
85 collect(Collectors.toList()));
86 this.userTO = userTO;
87
88 add(new Accordion("plainSchemas", List.of(new AbstractTab(
89 new ResourceModel("attributes.accordion", "Plain Attributes")) {
90
91 private static final long serialVersionUID = -7078941093668723016L;
92
93 @Override
94 public WebMarkupContainer getPanel(final String panelId) {
95 return new PlainSchemasOwn(panelId, schemas, attrs);
96 }
97 }), Model.of(0)).setOutputMarkupId(true));
98 }
99
100 @Override
101 protected FormComponent<?> checkboxToggle(
102 final Attr attrTO,
103 final AbstractFieldPanel<?> panel,
104 final boolean isMultivalue) {
105
106 LinkedAccountPlainAttrProperty property = accountPlainAttrProperties.stream().filter(
107 existingProperty -> {
108 return existingProperty.getSchema().equals(attrTO.getSchema());
109 }).findFirst().orElseGet(() -> {
110 LinkedAccountPlainAttrProperty newProperty = new LinkedAccountPlainAttrProperty();
111 newProperty.setOverridable(linkedAccountTO.getPlainAttr(attrTO.getSchema()).isPresent());
112 newProperty.setSchema(attrTO.getSchema());
113 newProperty.getValues().addAll(attrTO.getValues());
114 accountPlainAttrProperties.add(newProperty);
115 return newProperty;
116 });
117
118 final BootstrapToggleConfig config = new BootstrapToggleConfig().
119 withOnStyle(BootstrapToggleConfig.Style.success).
120 withOffStyle(BootstrapToggleConfig.Style.danger).
121 withSize(BootstrapToggleConfig.Size.mini);
122
123 return new BootstrapToggle("externalAction", new PropertyModel<>(property, "overridable"), config) {
124
125 private static final long serialVersionUID = -875219845189261873L;
126
127 @Override
128 protected CheckBox newCheckBox(final String id, final IModel<Boolean> model) {
129 final CheckBox checkBox = super.newCheckBox(id, model);
130 checkBox.add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
131
132 private static final long serialVersionUID = -1107858522700306810L;
133
134 @Override
135 protected void onUpdate(final AjaxRequestTarget target) {
136 if (isMultivalue) {
137 MultiFieldPanel.class.cast(panel).setFormReadOnly(!model.getObject());
138 } else {
139 FieldPanel.class.cast(panel).setReadOnly(!model.getObject());
140 }
141
142 updateAccountPlainSchemas(property, model.getObject());
143 target.add(panel);
144 }
145 });
146 return checkBox;
147 }
148
149 @Override
150 protected IModel<String> getOnLabel() {
151 return Model.of("Override");
152 }
153
154 @Override
155 protected IModel<String> getOffLabel() {
156 return Model.of("Override?");
157 }
158
159 @Override
160 protected void onComponentTag(final ComponentTag tag) {
161 super.onComponentTag(tag);
162 tag.append("class", "overridable", " ");
163 }
164 };
165 }
166
167 private void updateAccountPlainSchemas(final LinkedAccountPlainAttrProperty property, final Boolean modelObject) {
168 Set<Attr> withoutCurrentSchema = new HashSet<>(linkedAccountTO.getPlainAttrs().stream().
169 filter(attrTO -> !attrTO.getSchema().equals(property.getSchema())
170 && checkIsReadonlyAttr(attrTO.getSchema())).
171 collect(Collectors.toSet()));
172 linkedAccountTO.getPlainAttrs().clear();
173 linkedAccountTO.getPlainAttrs().addAll(withoutCurrentSchema);
174 if (modelObject) {
175 linkedAccountTO.getPlainAttrs().add(
176 fixedAttrs.stream().filter(attrTO -> attrTO.getSchema().equals(property.getSchema())).findFirst().
177 orElseGet(() -> new Attr.Builder(property.getSchema()).
178 values(property.getValues()).build()));
179 }
180 }
181
182 @Override
183 protected SchemaType getSchemaType() {
184 return SchemaType.PLAIN;
185 }
186
187 @Override
188 protected void setAttrs() {
189 List<Attr> attrs = new ArrayList<>();
190 List<PlainSchemaTO> notReadonlyValues = schemas.values().stream().
191 filter(schema -> checkIsReadonlyAttr(schema.getKey())).
192 collect(Collectors.toList());
193 setFixedAttr(notReadonlyValues);
194 Map<String, Attr> attrMap = EntityTOUtils.buildAttrMap(fixedAttrs);
195
196 attrs.addAll(notReadonlyValues.stream().
197 map(schema -> {
198 Attr attrTO = new Attr();
199 attrTO.setSchema(schema.getKey());
200 if (attrMap.get(schema.getKey()) == null || attrMap.get(schema.getKey()).getValues().isEmpty()) {
201 attrTO.getValues().add("");
202 } else {
203 attrTO = attrMap.get(schema.getKey());
204 }
205 return attrTO;
206 }).
207 collect(Collectors.toList()));
208
209 fixedAttrs.clear();
210 fixedAttrs.addAll(attrs);
211 }
212
213 @Override
214 protected List<Attr> getAttrsFromTO() {
215 return fixedAttrs.stream().sorted(attrComparator).collect(Collectors.toList());
216 }
217
218 private void setFixedAttr(final Collection<PlainSchemaTO> values) {
219 values.forEach(schema -> linkedAccountTO.getPlainAttr(schema.getKey()).ifPresentOrElse(
220 fixedAttrs::add,
221 () -> userTO.getPlainAttr(schema.getKey()).ifPresent(fixedAttrs::add)));
222 }
223
224 private boolean checkIsReadonlyAttr(final String schema) {
225 return schemas.isEmpty() ? true : !schemas.get(schema).isReadonly();
226 }
227
228 private class PlainSchemasOwn extends PlainSchemas<List<Attr>> {
229
230 private static final long serialVersionUID = -4730563859116024676L;
231
232 PlainSchemasOwn(
233 final String id,
234 final Map<String, PlainSchemaTO> schemas,
235 final IModel<List<Attr>> attrTOs) {
236
237 super(id);
238
239 add(new ListView<>("schemas", attrTOs) {
240
241 private static final long serialVersionUID = 9101744072914090143L;
242
243 @Override
244 protected void populateItem(final ListItem<Attr> item) {
245 Attr attrTO = item.getModelObject();
246 final boolean isMultivalue = schemas.get(attrTO.getSchema()).isMultivalue();
247
248 AbstractFieldPanel<?> panel = setPanel(
249 schemas,
250 item,
251 linkedAccountTO.getPlainAttr(attrTO.getSchema()).isEmpty());
252
253 panel.showExternAction(checkboxToggle(attrTO, panel, isMultivalue));
254 }
255 });
256 }
257 }
258 }