1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.security.app.dialog.field;
35
36 import java.util.ArrayList;
37 import java.util.List;
38 import java.util.Map;
39
40 import com.vaadin.ui.Button;
41 import com.vaadin.ui.Component;
42 import com.vaadin.v7.data.Property;
43 import com.vaadin.v7.data.Validator;
44 import com.vaadin.v7.data.util.ObjectProperty;
45 import com.vaadin.v7.ui.AbstractField;
46 import com.vaadin.v7.ui.CustomField;
47 import com.vaadin.v7.ui.Field;
48 import com.vaadin.v7.ui.HorizontalLayout;
49 import com.vaadin.v7.ui.Label;
50 import com.vaadin.v7.ui.VerticalLayout;
51
52
53
54
55
56
57
58 public class AccessControlListField extends CustomField<AccessControlList> {
59 private final Map<Long, String> permissions;
60 private final NewEntryHandler newEntryHandler;
61
62 private VerticalLayout layout;
63 private List<Field<AccessControlList.Entry>> entryFields = new ArrayList<>();
64 private ValueChangeListener valueChangeListener;
65
66 private String addButtonCaption = "Add";
67 private String removeButtonCaption = "Remove";
68 private String emptyPlaceholderCaption = "No access";
69 private EntryFieldFactory entryFieldFactory;
70
71
72
73
74
75
76
77 public AccessControlListField(Map<Long, String> permissions, NewEntryHandler newEntryHandler) {
78 this.permissions = permissions;
79 this.newEntryHandler = newEntryHandler;
80 }
81
82 @Override
83 protected Component initContent() {
84 layout = new VerticalLayout();
85 layout.setSpacing(false);
86
87 AccessControlList<AccessControlList.Entry> acl = getValue();
88 List<Component> entryRows = buildEntryRows(acl);
89 layout.addComponents(entryRows.toArray(new Component[0]));
90
91 if (acl.getEntries().isEmpty()) {
92 layout.addComponent(new Label(emptyPlaceholderCaption));
93 }
94
95 if (newEntryHandler != null) {
96 final Button addButton = new Button(addButtonCaption);
97 addButton.addClickListener(new Button.ClickListener() {
98 @Override
99 public void buttonClick(Button.ClickEvent event) {
100 AccessControlList.Entry entry = newEntryHandler.createEntry();
101 AccessControlList<AccessControlList.Entry> value = getValue();
102 if (value == null) {
103 value = new AccessControlList<>();
104 setValue(value);
105 }
106 value.addEntry(entry);
107
108 Field<AccessControlList.Entry> entryField = getEntryFieldFactory().createField(entry);
109
110 if (entryField instanceof AbstractField) {
111 ((AbstractField) entryField).setValidationVisible(isValidationVisible());
112 }
113
114
115 entryFields.add(entryField);
116 layout.addComponent(buildEntryRow(entryField), layout.getComponentCount() - 1);
117 if (layout.getComponent(0) instanceof Label) {
118 layout.removeComponent(layout.getComponent(0));
119 }
120 }
121 });
122 layout.addComponent(addButton);
123 }
124 return layout;
125 }
126
127 protected List<Component> buildEntryRows(AccessControlList<AccessControlList.Entry> acl) {
128 List<Component> entryRows = new ArrayList<>();
129 if (acl != null) {
130 for (final AccessControlList.Entry entry : acl.getEntries()) {
131 Field<AccessControlList.Entry> entryField = getEntryFieldFactory().createField(entry);
132
133 if (entryField instanceof AbstractField) {
134 ((AbstractField) entryField).setValidationVisible(isValidationVisible());
135 }
136
137 entryFields.add(entryField);
138 entryRows.add(buildEntryRow(entryField));
139 }
140 }
141 return entryRows;
142 }
143
144 protected Component buildEntryRow(final Field<AccessControlList.Entry> entryField) {
145 final HorizontalLayout entryRow = new HorizontalLayout();
146 entryRow.setSpacing(true);
147 entryRow.setWidth("100%");
148
149 Button deleteButton = new Button();
150 deleteButton.setHtmlContentAllowed(true);
151 deleteButton.setCaption("<span class=\"" + "icon-trash" + "\"></span>");
152 deleteButton.addStyleName("inline");
153 deleteButton.setDescription(removeButtonCaption);
154 deleteButton.addClickListener(new Button.ClickListener() {
155
156 @Override
157 public void buttonClick(Button.ClickEvent event) {
158 AccessControlList<AccessControlList.Entry> acl = getValue();
159 acl.removeEntry(entryField.getValue());
160 entryFields.remove(entryField);
161 if (isValidationVisible()) {
162
163 fireValueChange(false);
164 }
165
166
167 layout.removeComponent(entryRow);
168 if (acl.getEntries().size() == 0) {
169 layout.addComponentAsFirst(new Label(emptyPlaceholderCaption));
170 }
171 }
172 });
173
174 entryRow.addComponents(entryField, deleteButton);
175 entryRow.setExpandRatio(entryField, 1f);
176 return entryRow;
177 }
178
179 public String getAddButtonCaption() {
180 return addButtonCaption;
181 }
182
183 public void setAddButtonCaption(String addButtonCaption) {
184 this.addButtonCaption = addButtonCaption;
185 }
186
187 public String getRemoveButtonCaption() {
188 return removeButtonCaption;
189 }
190
191 public void setRemoveButtonCaption(String removeButtonCaption) {
192 this.removeButtonCaption = removeButtonCaption;
193 }
194
195 public String getEmptyPlaceholderCaption() {
196 return emptyPlaceholderCaption;
197 }
198
199 public void setEmptyPlaceholderCaption(String emptyPlaceholderCaption) {
200 this.emptyPlaceholderCaption = emptyPlaceholderCaption;
201 }
202
203 @Override
204 public Class<AccessControlList> getType() {
205 return AccessControlList.class;
206 }
207
208 @Override
209 public AccessControlList<AccessControlList.Entry> getValue() {
210 return super.getValue();
211 }
212
213 @Override
214 protected void validate(AccessControlList fieldValue) throws Validator.InvalidValueException {
215 List<Validator.InvalidValueException> causes = new ArrayList<>();
216
217 try {
218 super.validate(fieldValue);
219 } catch (Validator.InvalidValueException e) {
220 causes.add(e);
221 }
222
223
224 for (Field<AccessControlList.Entry> entryField : entryFields) {
225 try {
226 entryField.validate();
227 } catch (Validator.InvalidValueException e) {
228 causes.add(e);
229 }
230 }
231
232 if (!causes.isEmpty()) {
233
234
235 throw new Validator.InvalidValueException(null, causes.toArray(new Validator.InvalidValueException[0]));
236 }
237 }
238
239
240
241
242
243 @Override
244 public void setValidationVisible(boolean validateAutomatically) {
245 super.setValidationVisible(validateAutomatically);
246 for (Field<?> entryField : entryFields) {
247 if (entryField instanceof AbstractField) {
248 ((AbstractField) entryField).setValidationVisible(isValidationVisible());
249 }
250 }
251
252 if (validateAutomatically && valueChangeListener == null) {
253 valueChangeListener = new ValueChangeListener() {
254 @Override
255 public void valueChange(Property.ValueChangeEvent event) {
256 fireValueChange(false);
257 }
258 };
259 for (Field<?> entryField : entryFields) {
260 entryField.addValueChangeListener(valueChangeListener);
261 }
262 } else if (!validateAutomatically && valueChangeListener != null) {
263 for (Field<?> entryField : entryFields) {
264 entryField.removeValueChangeListener(valueChangeListener);
265 }
266 valueChangeListener = null;
267 }
268 }
269
270 public EntryFieldFactory getEntryFieldFactory() {
271 if (entryFieldFactory == null) {
272 this.entryFieldFactory = new DefaultEntryFieldFactory();
273 }
274 return entryFieldFactory;
275 }
276
277 public void setEntryFieldFactory(EntryFieldFactory entryFieldFactory) {
278 this.entryFieldFactory = entryFieldFactory;
279 }
280
281
282
283
284 public interface NewEntryHandler {
285
286
287
288 AccessControlList.Entry createEntry();
289 }
290
291
292
293
294 public interface EntryFieldFactory {
295
296
297
298 Field<AccessControlList.Entry> createField(AccessControlList.Entry entry);
299 }
300
301
302
303
304 public class DefaultEntryFieldFactory implements EntryFieldFactory {
305 @Override
306 public Field<AccessControlList.Entry> createField(AccessControlList.Entry entry) {
307 AccessControlField entryField = new AccessControlField(permissions);
308 entryField.setPropertyDataSource(new ObjectProperty<>(entry));
309 return entryField;
310 }
311 }
312 }