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.reports;
20  
21  import com.fasterxml.jackson.databind.json.JsonMapper;
22  import java.io.Serializable;
23  import java.util.List;
24  import java.util.Optional;
25  import org.apache.syncope.client.console.SyncopeWebApplication;
26  import org.apache.syncope.client.console.panels.BeanPanel;
27  import org.apache.syncope.client.console.panels.search.SearchUtils;
28  import org.apache.syncope.client.console.rest.ImplementationRestClient;
29  import org.apache.syncope.client.console.rest.ReportRestClient;
30  import org.apache.syncope.client.console.tasks.CrontabPanel;
31  import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
32  import org.apache.syncope.client.ui.commons.Constants;
33  import org.apache.syncope.client.ui.commons.MIMETypesLoader;
34  import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
35  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
36  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
37  import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
38  import org.apache.syncope.common.lib.report.ReportConf;
39  import org.apache.syncope.common.lib.to.ImplementationTO;
40  import org.apache.syncope.common.lib.to.ReportTO;
41  import org.apache.syncope.common.lib.types.IdRepoImplementationType;
42  import org.apache.syncope.common.lib.types.ImplementationEngine;
43  import org.apache.wicket.PageReference;
44  import org.apache.wicket.WicketRuntimeException;
45  import org.apache.wicket.ajax.AjaxRequestTarget;
46  import org.apache.wicket.extensions.wizard.WizardModel;
47  import org.apache.wicket.extensions.wizard.WizardStep;
48  import org.apache.wicket.markup.html.basic.Label;
49  import org.apache.wicket.model.IModel;
50  import org.apache.wicket.model.Model;
51  import org.apache.wicket.model.PropertyModel;
52  import org.springframework.beans.BeanWrapper;
53  import org.springframework.beans.PropertyAccessorFactory;
54  
55  public class ReportWizardBuilder extends BaseAjaxWizardBuilder<ReportTO> {
56  
57      private static final long serialVersionUID = 5945391813567245081L;
58  
59      protected static final JsonMapper MAPPER = JsonMapper.builder().findAndAddModules().build();
60  
61      protected final ImplementationRestClient implementationRestClient;
62  
63      protected final ReportRestClient reportRestClient;
64  
65      protected final MIMETypesLoader mimeTypesLoader;
66  
67      protected final Model<ReportConfWrapper> conf = new Model<>();
68  
69      protected CrontabPanel crontabPanel;
70  
71      public ReportWizardBuilder(
72              final ReportTO reportTO,
73              final ImplementationRestClient implementationRestClient,
74              final ReportRestClient reportRestClient,
75              final MIMETypesLoader mimeTypesLoader,
76              final PageReference pageRef) {
77  
78          super(reportTO, pageRef);
79  
80          this.implementationRestClient = implementationRestClient;
81          this.reportRestClient = reportRestClient;
82          this.mimeTypesLoader = mimeTypesLoader;
83      }
84  
85      @Override
86      protected Serializable onApplyInternal(final ReportTO modelObject) {
87          if (conf.getObject() != null) {
88              try {
89                  ImplementationTO implementation = implementationRestClient.read(
90                          IdRepoImplementationType.REPORT_DELEGATE, modelObject.getJobDelegate());
91                  if (implementation.getEngine() == ImplementationEngine.JAVA) {
92                      BeanWrapper confWrapper = PropertyAccessorFactory.forBeanPropertyAccess(conf.getObject().getConf());
93                      conf.getObject().getSCondWrapper().forEach((fieldName, pair) -> confWrapper.setPropertyValue(
94                              fieldName, SearchUtils.buildFIQL(pair.getRight(), pair.getLeft())));
95  
96                      implementation.setBody(MAPPER.writeValueAsString(conf.getObject().getConf()));
97                      implementationRestClient.update(implementation);
98                  }
99              } catch (Exception e) {
100                 throw new WicketRuntimeException(e);
101             }
102         }
103 
104         modelObject.setCronExpression(crontabPanel.getCronExpression());
105 
106         if (modelObject.getKey() == null) {
107             reportRestClient.create(modelObject);
108         } else {
109             reportRestClient.update(modelObject);
110         }
111 
112         return modelObject;
113     }
114 
115     protected void setConf(final String jobDelegate) {
116         try {
117             ImplementationTO implementation = implementationRestClient.read(
118                     IdRepoImplementationType.REPORT_DELEGATE, jobDelegate);
119             if (implementation.getEngine() == ImplementationEngine.JAVA) {
120                 conf.setObject(new ReportConfWrapper());
121                 conf.getObject().setConf(MAPPER.readValue(implementation.getBody(), ReportConf.class));
122             } else {
123                 conf.setObject(null);
124             }
125         } catch (Exception e) {
126             LOG.error("Could not read or parse {}", jobDelegate, e);
127         }
128     }
129 
130     @Override
131     protected WizardModel buildModelSteps(final ReportTO modelObject, final WizardModel wizardModel) {
132         Optional.ofNullable(modelObject.getJobDelegate()).ifPresent(this::setConf);
133 
134         Configuration configuration = new Configuration();
135         wizardModel.add(new Profile(modelObject, configuration));
136         wizardModel.add(configuration);
137         wizardModel.add(new Schedule(modelObject));
138         return wizardModel;
139     }
140 
141     public class Profile extends WizardStep {
142 
143         private static final long serialVersionUID = -3043839139187792810L;
144 
145         private final IModel<List<String>> reportJobDelegates = SyncopeWebApplication.get().
146                 getImplementationInfoProvider().getReportJobDelegates();
147 
148         public Profile(final ReportTO modelObject, final Configuration configuration) {
149             AjaxTextFieldPanel name = new AjaxTextFieldPanel(
150                     Constants.NAME_FIELD_NAME, Constants.NAME_FIELD_NAME,
151                     new PropertyModel<>(modelObject, Constants.NAME_FIELD_NAME), false);
152             add(name.addRequiredLabel().setEnabled(true));
153 
154             AjaxCheckBoxPanel active = new AjaxCheckBoxPanel(
155                     "active", "active", new PropertyModel<>(modelObject, "active"), false);
156             add(active);
157 
158             AjaxTextFieldPanel mimeType = new AjaxTextFieldPanel(
159                     "mimeType", "mimeType", new PropertyModel<>(modelObject, "mimeType"));
160             mimeType.setChoices(mimeTypesLoader.getMimeTypes());
161             add(mimeType.addRequiredLabel());
162 
163             AjaxTextFieldPanel fileExt = new AjaxTextFieldPanel(
164                     "fileExt", "fileExt", new PropertyModel<>(modelObject, "fileExt"));
165             add(fileExt.addRequiredLabel());
166             mimeType.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
167 
168                 private static final long serialVersionUID = -6139318907146065915L;
169 
170                 @Override
171                 protected void onUpdate(final AjaxRequestTarget target) {
172                     Optional.ofNullable(mimeTypesLoader.getFileExt(mimeType.getModelObject())).
173                             ifPresent(fileExt::setModelObject);
174                     target.add(fileExt);
175                 }
176             });
177 
178             AjaxDropDownChoicePanel<String> jobDelegate = new AjaxDropDownChoicePanel<>(
179                     "jobDelegate", "jobDelegate", new PropertyModel<>(modelObject, "jobDelegate"), false);
180             jobDelegate.setChoices(reportJobDelegates.getObject());
181             add(jobDelegate.addRequiredLabel().setEnabled(modelObject.getKey() == null));
182             jobDelegate.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
183 
184                 private static final long serialVersionUID = -6139318907146065915L;
185 
186                 @Override
187                 protected void onUpdate(final AjaxRequestTarget target) {
188                     setConf(jobDelegate.getModelObject());
189                     configuration.update();
190                 }
191             });
192         }
193     }
194 
195     public class Configuration extends WizardStep implements WizardModel.ICondition {
196 
197         private static final long serialVersionUID = -785981096328637758L;
198 
199         public Configuration() {
200             update();
201         }
202 
203         protected void update() {
204             if (conf.getObject() == null) {
205                 addOrReplace(new Label("bean", Model.of()));
206             } else {
207                 addOrReplace(new BeanPanel<>(
208                         "bean",
209                         new PropertyModel<>(conf.getObject(), "conf"),
210                         conf.getObject().getSCondWrapper(),
211                         pageRef).
212                         setRenderBodyOnly(true));
213             }
214         }
215 
216         @Override
217         public boolean evaluate() {
218             return conf.getObject() != null;
219         }
220     }
221 
222     public class Schedule extends WizardStep {
223 
224         private static final long serialVersionUID = -785981096328637758L;
225 
226         public Schedule(final ReportTO modelObject) {
227             crontabPanel = new CrontabPanel(
228                     "schedule", new PropertyModel<>(modelObject, "cronExpression"), modelObject.getCronExpression());
229             add(crontabPanel);
230         }
231     }
232 }