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.enduser.panels.any;
20  
21  import java.io.Serializable;
22  import java.util.ArrayList;
23  import java.util.Comparator;
24  import java.util.LinkedHashMap;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.stream.Collectors;
28  import org.apache.commons.lang3.tuple.Pair;
29  import org.apache.cxf.common.util.StringUtils;
30  import org.apache.syncope.client.enduser.layout.CustomizationOption;
31  import org.apache.syncope.client.enduser.rest.SchemaRestClient;
32  import org.apache.syncope.client.enduser.rest.SyncopeRestClient;
33  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
34  import org.apache.syncope.client.ui.commons.wizards.any.AnyWrapper;
35  import org.apache.syncope.common.lib.Attr;
36  import org.apache.syncope.common.lib.to.MembershipTO;
37  import org.apache.syncope.common.lib.to.SchemaTO;
38  import org.apache.syncope.common.lib.to.UserTO;
39  import org.apache.syncope.common.lib.types.SchemaType;
40  import org.apache.wicket.event.IEvent;
41  import org.apache.wicket.markup.html.panel.Panel;
42  import org.apache.wicket.model.IModel;
43  import org.apache.wicket.model.util.ListModel;
44  import org.apache.wicket.spring.injection.annot.SpringBean;
45  
46  public abstract class AbstractAttrs<S extends SchemaTO> extends Panel {
47  
48      private static final long serialVersionUID = -5387344116983102292L;
49  
50      protected static final String FORM_SUFFIX = "form_";
51  
52      @SpringBean
53      protected SchemaRestClient schemaRestClient;
54  
55      @SpringBean
56      protected SyncopeRestClient syncopeRestClient;
57  
58      protected final Comparator<Attr> attrComparator = new AttrComparator();
59  
60      protected final UserTO userTO;
61  
62      protected final Map<String, CustomizationOption> whichAttrs;
63  
64      protected final Map<String, S> schemas = new LinkedHashMap<>();
65  
66      protected final Map<String, Map<String, S>> membershipSchemas = new LinkedHashMap<>();
67  
68      protected final IModel<List<Attr>> attrs;
69  
70      protected final IModel<List<MembershipTO>> membershipTOs;
71  
72      private final List<String> anyTypeClasses;
73  
74      public AbstractAttrs(
75              final String id,
76              final AnyWrapper<UserTO> modelObject,
77              final List<String> anyTypeClasses,
78              final Map<String, CustomizationOption> whichAttrs) {
79  
80          super(id);
81          this.anyTypeClasses = anyTypeClasses;
82          this.attrs = new ListModel<>(List.of());
83          this.membershipTOs = new ListModel<>(List.of());
84  
85          this.setOutputMarkupId(true);
86  
87          this.userTO = modelObject.getInnerObject();
88          this.whichAttrs = whichAttrs;
89  
90          evaluate();
91      }
92  
93      protected List<Attr> loadAttrs() {
94          List<String> classes = new ArrayList<>(anyTypeClasses);
95          // just add keys
96          classes.addAll(userTO.getAuxClasses());
97          setSchemas(classes);
98          setAttrs();
99          return AbstractAttrs.this.getAttrsFromTO();
100     }
101 
102     @SuppressWarnings({ "unchecked" })
103     protected List<MembershipTO> loadMembershipAttrs() {
104         List<MembershipTO> memberships = new ArrayList<>();
105 
106         membershipSchemas.clear();
107 
108         for (MembershipTO membership : userTO.getMemberships()) {
109             setSchemas(Pair.of(
110                     membership.getGroupKey(), membership.getGroupName()),
111                     getMembershipAuxClasses(membership));
112             setAttrs(membership);
113 
114             if (AbstractAttrs.this instanceof PlainAttrs && !membership.getPlainAttrs().isEmpty()) {
115                 memberships.add(membership);
116             } else if (AbstractAttrs.this instanceof DerAttrs && !membership.getDerAttrs().isEmpty()) {
117                 memberships.add(membership);
118             } else if (AbstractAttrs.this instanceof VirAttrs && !membership.getVirAttrs().isEmpty()) {
119                 memberships.add(membership);
120             }
121         }
122 
123         return memberships;
124     }
125 
126     protected boolean filterSchemas() {
127         return !whichAttrs.isEmpty();
128     }
129 
130     protected boolean renderAsReadonly(final String schema, final String groupName) {
131         // whether to render the attribute as readonly or not, without considering schema readonly property
132         String schemaName = (org.apache.commons.lang3.StringUtils.isBlank(groupName)
133                 ? org.apache.commons.lang3.StringUtils.EMPTY
134                 : groupName + '#')
135                 + schema;
136         return whichAttrs.get(schemaName) == null ? false : whichAttrs.get(schemaName).isReadonly();
137     }
138 
139     protected List<String> getDefaultValues(final String schema) {
140         return getDefaultValues(schema, null);
141     }
142 
143     protected List<String> getDefaultValues(final String schema, final String groupName) {
144         String schemaName = (org.apache.commons.lang3.StringUtils.isBlank(groupName)
145                 ? org.apache.commons.lang3.StringUtils.EMPTY
146                 : groupName + '#')
147                 + schema;
148         return whichAttrs.get(schemaName) == null
149                 ? List.of()
150                 : whichAttrs.get(schemaName).getDefaultValues();
151     }
152 
153     protected abstract SchemaType getSchemaType();
154 
155     protected void setSchemas(final Pair<String, String> membership, final List<String> anyTypeClasses) {
156         final Map<String, S> mscs;
157 
158         if (membershipSchemas.containsKey(membership.getKey())) {
159             mscs = membershipSchemas.get(membership.getKey());
160         } else {
161             mscs = new LinkedHashMap<>();
162             membershipSchemas.put(membership.getKey(), mscs);
163         }
164         setSchemas(anyTypeClasses, membership.getValue(), mscs);
165     }
166 
167     protected void setSchemas(final List<String> anyTypeClasses) {
168         setSchemas(anyTypeClasses, null, schemas);
169     }
170 
171     protected void setSchemas(final List<String> anyTypeClasses, final String groupName, final Map<String, S> scs) {
172         final List<S> allSchemas;
173         if (anyTypeClasses.isEmpty()) {
174             allSchemas = new ArrayList<>();
175         } else {
176             allSchemas = schemaRestClient.getSchemas(getSchemaType(), null, anyTypeClasses.toArray(String[]::new));
177         }
178 
179         scs.clear();
180 
181         if (filterSchemas()) {
182             // 1. remove attributes not selected for display
183             allSchemas.removeAll(allSchemas.stream().
184                     filter(schemaTO -> org.apache.commons.lang3.StringUtils.isBlank(groupName)
185                     ? !whichAttrs.containsKey(schemaTO.getKey())
186                     : !whichAttrs.containsKey(groupName + '#' + schemaTO.getKey())).collect(Collectors.toSet()));
187         }
188 
189         allSchemas.forEach(schemaTO -> scs.put(schemaTO.getKey(), schemaTO));
190     }
191 
192     public boolean isPanelVisible() {
193         return !attrs.getObject().isEmpty() || !membershipTOs.getObject().isEmpty();
194     }
195 
196     protected abstract void setAttrs();
197 
198     protected abstract void setAttrs(MembershipTO membershipTO);
199 
200     protected abstract List<Attr> getAttrsFromTO();
201 
202     protected abstract List<Attr> getAttrsFromTO(MembershipTO membershipTO);
203 
204     protected List<String> getMembershipAuxClasses(final MembershipTO membershipTO) {
205         try {
206             return syncopeRestClient.searchUserTypeExtensions(membershipTO.getGroupName());
207         } catch (Exception e) {
208             return List.of();
209         }
210     }
211 
212     @Override
213     protected void onInitialize() {
214         evaluate();
215         super.onInitialize();
216     }
217 
218     public boolean evaluate() {
219         this.attrs.setObject(loadAttrs());
220         this.membershipTOs.setObject(loadMembershipAttrs());
221         return !attrs.getObject().isEmpty() || !membershipTOs.getObject().isEmpty();
222     }
223 
224     @Override
225     public void onEvent(final IEvent<?> event) {
226         super.onEvent(event);
227         if (event.getPayload() instanceof AjaxPalettePanel.UpdateActionEvent) {
228             evaluate();
229             AjaxPalettePanel.UpdateActionEvent updateEvent = (AjaxPalettePanel.UpdateActionEvent) event.getPayload();
230             updateEvent.getTarget().add(this);
231         }
232     }
233 
234     protected class AttrComparator implements Comparator<Attr>, Serializable {
235 
236         private static final long serialVersionUID = -5105030477767941060L;
237 
238         @Override
239         public int compare(final Attr left, final Attr right) {
240             if (left == null || StringUtils.isEmpty(left.getSchema())) {
241                 return -1;
242             }
243             if (right == null || StringUtils.isEmpty(right.getSchema())) {
244                 return 1;
245             } else if (AbstractAttrs.this.filterSchemas()) {
246                 int leftIndex = new ArrayList<>(AbstractAttrs.this.whichAttrs.keySet()).indexOf(left.getSchema());
247                 int rightIndex = new ArrayList<>(AbstractAttrs.this.whichAttrs.keySet()).indexOf(right.getSchema());
248 
249                 if (leftIndex > rightIndex) {
250                     return 1;
251                 } else if (leftIndex < rightIndex) {
252                     return -1;
253                 } else {
254                     return 0;
255                 }
256             } else {
257                 return left.getSchema().compareTo(right.getSchema());
258             }
259         }
260     }
261 
262     protected static class Schemas extends Panel {
263 
264         private static final long serialVersionUID = -2447602429647965090L;
265 
266         public Schemas(final String id) {
267             super(id);
268         }
269     }
270 }