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.wizards.any;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.LinkedHashMap;
24  import java.util.List;
25  import java.util.Map;
26  import org.apache.commons.lang3.StringUtils;
27  import org.apache.commons.lang3.tuple.Pair;
28  import org.apache.commons.lang3.tuple.Triple;
29  import org.apache.syncope.client.console.SyncopeWebApplication;
30  import org.apache.syncope.client.console.panels.ListViewPanel;
31  import org.apache.syncope.client.console.panels.MultilevelPanel;
32  import org.apache.syncope.client.console.panels.PropagationErrorPanel;
33  import org.apache.syncope.client.console.panels.RemoteObjectPanel;
34  import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
35  import org.apache.syncope.client.ui.commons.Constants;
36  import org.apache.syncope.client.ui.commons.status.ConnObjectWrapper;
37  import org.apache.syncope.client.ui.commons.status.Status;
38  import org.apache.syncope.client.ui.commons.status.StatusBean;
39  import org.apache.syncope.client.ui.commons.status.StatusUtils;
40  import org.apache.syncope.common.lib.to.AnyTO;
41  import org.apache.syncope.common.lib.to.ConnObject;
42  import org.apache.syncope.common.lib.to.GroupTO;
43  import org.apache.syncope.common.lib.to.UserTO;
44  import org.apache.wicket.Component;
45  import org.apache.wicket.PageReference;
46  import org.apache.wicket.ajax.AjaxRequestTarget;
47  import org.apache.wicket.markup.html.panel.Panel;
48  import org.apache.wicket.model.IModel;
49  import org.apache.wicket.model.ResourceModel;
50  import org.slf4j.Logger;
51  import org.slf4j.LoggerFactory;
52  
53  public class StatusPanel extends Panel {
54  
55      private static final long serialVersionUID = -4013796607157549641L;
56  
57      protected static final Logger LOG = LoggerFactory.getLogger(StatusPanel.class);
58  
59      protected Map<String, StatusBean> initialStatusBeanMap;
60  
61      protected ListViewPanel<?> listViewPanel;
62  
63      public <T extends AnyTO> StatusPanel(
64              final String id,
65              final T any,
66              final IModel<List<StatusBean>> model,
67              final PageReference pageRef) {
68  
69          super(id);
70          init(any, model,
71                  SyncopeWebApplication.get().getStatusProvider().get(any, any.getResources()), pageRef, false);
72      }
73  
74      public <T extends AnyTO> StatusPanel(
75              final String id,
76              final T any,
77              final IModel<List<StatusBean>> model,
78              final List<Triple<ConnObject, ConnObjectWrapper, String>> connObjects,
79              final PageReference pageRef) {
80  
81          super(id);
82          init(any, model, connObjects, pageRef, true);
83      }
84  
85      protected void init(
86              final AnyTO any,
87              final IModel<List<StatusBean>> model,
88              final List<Triple<ConnObject, ConnObjectWrapper, String>> connObjects,
89              final PageReference pageRef,
90              final boolean enableConnObjectLink) {
91  
92          final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1);
93          initialStatusBeanMap = new LinkedHashMap<>(connObjects.size() + 1);
94  
95          final StatusBean syncope = new StatusBean(any, Constants.SYNCOPE);
96  
97          if (any instanceof UserTO) {
98              syncope.setConnObjectLink(((UserTO) any).getUsername());
99  
100             Status syncopeStatus = Status.UNDEFINED;
101             if (((UserTO) any).getStatus() != null) {
102                 try {
103                     syncopeStatus = Status.valueOf(((UserTO) any).getStatus().toUpperCase());
104                 } catch (IllegalArgumentException e) {
105                     LOG.warn("Unexpected status found: {}", ((UserTO) any).getStatus(), e);
106                 }
107             }
108             syncope.setStatus(syncopeStatus);
109         } else if (any instanceof GroupTO) {
110             syncope.setConnObjectLink(((GroupTO) any).getName());
111             syncope.setStatus(Status.ACTIVE);
112         }
113 
114         statusBeans.add(syncope);
115         initialStatusBeanMap.put(syncope.getResource(), syncope);
116 
117         Map<String, String> failureReasons = new HashMap<>();
118         connObjects.forEach(triple -> {
119             ConnObjectWrapper connObjectWrapper = triple.getMiddle();
120             StatusBean statusBean = StatusUtils.getStatusBean(connObjectWrapper.getAny(),
121                     connObjectWrapper.getResource(),
122                     connObjectWrapper.getConnObjectTO(),
123                     any instanceof GroupTO);
124 
125             initialStatusBeanMap.put(connObjectWrapper.getResource(), statusBean);
126             statusBeans.add(statusBean);
127 
128             if (StringUtils.isNotBlank(triple.getRight())) {
129                 failureReasons.put(connObjectWrapper.getResource(), triple.getRight());
130             }
131         });
132 
133         MultilevelPanel mlp = new MultilevelPanel("resources");
134         add(mlp);
135 
136         ListViewPanel.Builder<StatusBean> builder = new ListViewPanel.Builder<>(StatusBean.class, pageRef) {
137 
138             private static final long serialVersionUID = -6809736686861678498L;
139 
140             @Override
141             protected Component getValueComponent(final String key, final StatusBean bean) {
142                 if ("status".equalsIgnoreCase(key)) {
143                     return StatusUtils.getStatusImagePanel("field", bean.getStatus());
144                 } else {
145                     return super.getValueComponent(key, bean);
146                 }
147             }
148         };
149         builder.setModel(model);
150         builder.setItems(statusBeans);
151         builder.includes("resource", "connObjectLink", "status");
152         builder.withChecks(ListViewPanel.CheckAvailability.NONE);
153         builder.setReuseItem(false);
154 
155         ActionLink<StatusBean> connObjectLink = new ActionLink<>() {
156 
157             private static final long serialVersionUID = -3722207913631435501L;
158 
159             @Override
160             protected boolean statusCondition(final StatusBean bean) {
161                 Pair<ConnObject, ConnObject> pair =
162                         getConnObjectTOs(bean.getKey(), bean.getResource(), connObjects);
163                 return pair != null && pair.getRight() != null;
164             }
165 
166             @Override
167             public void onClick(final AjaxRequestTarget target, final StatusBean bean) {
168                 mlp.next(bean.getResource(), new RemoteAnyPanel(bean, connObjects), target);
169             }
170         };
171         if (!enableConnObjectLink) {
172             connObjectLink.disable();
173         }
174         SyncopeWebApplication.get().getStatusProvider().addConnObjectLink(builder, connObjectLink);
175 
176         builder.addAction(new ActionLink<>() {
177 
178             private static final long serialVersionUID = -3722207913631435501L;
179 
180             @Override
181             protected boolean statusCondition(final StatusBean bean) {
182                 return failureReasons.containsKey(bean.getResource());
183             }
184 
185             @Override
186             public void onClick(final AjaxRequestTarget target, final StatusBean bean) {
187                 mlp.next(bean.getResource(), new PropagationErrorPanel(failureReasons.get(bean.getResource())), target);
188             }
189         }, ActionLink.ActionType.PROPAGATION_TASKS, StringUtils.EMPTY);
190 
191         listViewPanel = ListViewPanel.class.cast(builder.build(MultilevelPanel.FIRST_LEVEL_ID));
192         mlp.setFirstLevel(listViewPanel);
193     }
194 
195     public void setCheckAvailability(final ListViewPanel.CheckAvailability check) {
196         listViewPanel.setCheckAvailability(check);
197     }
198 
199     public Map<String, StatusBean> getInitialStatusBeanMap() {
200         return initialStatusBeanMap;
201     }
202 
203     protected static Pair<ConnObject, ConnObject> getConnObjectTOs(
204             final String anyKey,
205             final String resource,
206             final List<Triple<ConnObject, ConnObjectWrapper, String>> objects) {
207 
208         for (Triple<ConnObject, ConnObjectWrapper, String> object : objects) {
209             if (anyKey.equals(object.getMiddle().getAny().getKey())
210                     && resource.equalsIgnoreCase(object.getMiddle().getResource())) {
211 
212                 return Pair.of(object.getLeft(), object.getMiddle().getConnObjectTO());
213             }
214         }
215 
216         return null;
217     }
218 
219     static class RemoteAnyPanel extends RemoteObjectPanel {
220 
221         private static final long serialVersionUID = 4303365227411467563L;
222 
223         protected final StatusBean bean;
224 
225         protected final List<Triple<ConnObject, ConnObjectWrapper, String>> connObjects;
226 
227         RemoteAnyPanel(final StatusBean bean, final List<Triple<ConnObject, ConnObjectWrapper, String>> connObjects) {
228             this.bean = bean;
229             this.connObjects = connObjects;
230 
231             add(new ConnObjectPanel(
232                     REMOTE_OBJECT_PANEL_ID,
233                     Pair.<IModel<?>, IModel<?>>of(new ResourceModel("before"), new ResourceModel("after")),
234                     getConnObjectTOs(),
235                     false));
236         }
237 
238         @Override
239         protected final Pair<ConnObject, ConnObject> getConnObjectTOs() {
240             return StatusPanel.getConnObjectTOs(bean.getKey(), bean.getResource(), connObjects);
241         }
242     }
243 }