/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openengsb.ui.admin.sendEventPage;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.openengsb.core.api.DomainProvider;
import org.openengsb.core.api.Event;
import org.openengsb.core.api.OsgiUtilsService;
import org.openengsb.core.api.context.ContextHolder;
import org.openengsb.core.api.descriptor.AttributeDefinition;
import org.openengsb.core.api.security.annotation.SecurityAttribute;
import org.openengsb.core.workflow.api.RuleManager;
import org.openengsb.core.workflow.api.WorkflowException;
import org.openengsb.core.workflow.api.WorkflowService;
import org.openengsb.domain.auditing.AuditingDomain;
import org.openengsb.ui.admin.basePage.BasePage;
import org.openengsb.ui.admin.ruleEditorPanel.RuleEditorPanel;
import org.openengsb.ui.admin.ruleEditorPanel.RuleManagerProvider;
import org.openengsb.ui.admin.util.ValueConverter;
import org.openengsb.ui.common.editor.AttributeEditorUtil;
import org.openengsb.ui.common.util.MethodUtil;
import org.openengsb.ui.common.workflow.WorkflowStartPanel;
import org.ops4j.pax.wicket.api.PaxWicketMountPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SecurityAttribute(key = "org.openengsb.ui.component", value = "WORKFLOW_USER")
@PaxWicketMountPoint(mountPoint = "events")
public class SendEventPage extends BasePage implements RuleManagerProvider {
private static final long serialVersionUID = -6450762722099473732L;
private static final Logger LOGGER = LoggerFactory.getLogger(SendEventPage.class);
public static final String PAGE_NAME_KEY = "sendEventPage.title";
public static final String PAGE_DESCRIPTION_KEY = "sendEventPage.description";
@Inject
@Named("osgiUtilsService")
private OsgiUtilsService serviceUtils;
@Inject
@Named("eventService")
private WorkflowService eventService;
private DropDownChoice<Class<?>> dropDownChoice;
@Inject
@Named("ruleManager")
private RuleManager ruleManager;
@Inject
@Named("auditing")
private AuditingDomain auditing;
private RepeatingView fieldList;
private final ValueConverter valueConverter = new ValueConverter();
private final Map<String, String> realValues = new HashMap<String, String>();
public SendEventPage() {
initContent();
}
public SendEventPage(PageParameters parameters) {
super(parameters, PAGE_NAME_KEY);
initContent();
}
private void initContent() {
List<Class<? extends Event>> classes = new ArrayList<Class<? extends Event>>();
classes.add(Event.class);
for (DomainProvider domain : serviceUtils.listServices(DomainProvider.class)) {
classes.addAll(domain.getEvents());
}
init(classes);
}
//TODO: OPENENGSB-3272: Extract this into an own component
private Component createProjectChoice() {
DropDownChoice<String> dropDownChoice = new DropDownChoice<String>("projectChoice", new IModel<String>() {
private static final long serialVersionUID = -5776062054709043273L;
@Override
public String getObject() {
return getSessionContextId();
}
@Override
public void setObject(String object) {
ContextHolder.get().setCurrentContextId(object);
}
@Override
public void detach() {
}
}, getAvailableContexts()) {
private static final long serialVersionUID = 1L;
@Override
protected boolean wantOnSelectionChangedNotifications() {
return true;
}
@Override
protected void onModelChanged() {
setResponsePage(SendEventPage.this.getClass());
}
};
return dropDownChoice;
}
public SendEventPage(List<Class<? extends Event>> classes) {
init(classes);
}
@SuppressWarnings("serial")
private void init(List<? extends Class<?>> classes) {
Form<Object> form = new Form<Object>("form");
add(form);
ChoiceRenderer<Class<?>> choiceRenderer = new ChoiceRenderer<Class<?>>("canonicalName", "simpleName");
final WebMarkupContainer container = new WebMarkupContainer("fieldContainer");
dropDownChoice = new DropDownChoice<Class<?>>("dropdown", classes, choiceRenderer);
dropDownChoice.setModel(new Model<Class<?>>(classes.get(0)));
dropDownChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
@Override
protected void onUpdate(AjaxRequestTarget target) {
Class<?> theClass = dropDownChoice.getModelObject();
fieldList.removeAll();
container.replace(createEditorPanelForClass(theClass));
target.add(container);
}
});
form.add(dropDownChoice);
form.add(container);
container.add(createEditorPanelForClass(classes.get(0)));
container.setOutputMarkupId(true);
form.add(new FeedbackPanel("feedback"));
Form<?> pc = new Form<Object>("projectChoiceForm");
pc.add(createProjectChoice());
add(pc);
final WebMarkupContainer auditsContainer = new WebMarkupContainer("auditsContainer");
auditsContainer.setOutputMarkupId(true);
AjaxButton submitButton = new IndicatingAjaxButton("submitButton", form) {
@Override
protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
Event event = buildEvent(dropDownChoice.getModelObject(), realValues);
if (event != null) {
try {
eventService.processEvent(event);
info(new StringResourceModel("send.event.success", SendEventPage.this, null).getString());
} catch (WorkflowException e) {
StringResourceModel resourceModel =
new StringResourceModel("send.event.error.process", SendEventPage.this, null);
error(resourceModel.getString());
}
} else {
error(new StringResourceModel("send.event.error.build", SendEventPage.this, null).getString());
}
target.add(form);
target.add(auditsContainer);
}
@Override
protected void onError(AjaxRequestTarget target, Form<?> form) {
target.add(form);
}
};
submitButton.setOutputMarkupId(true);
form.add(submitButton);
List<Event> audits = new ArrayList<Event>();
try {
audits = auditing.getAllAudits();
} catch (Exception e) {
LOGGER.error("Audits cannot be loaded", e);
}
ListView<Event> listView = new ListView<Event>("audits", audits) {
@Override
protected void populateItem(ListItem<Event> item) {
item.add(new Label("audit", item.getModelObject().getName()));
}
};
auditsContainer.add(listView);
add(auditsContainer);
add(new WorkflowStartPanel("workflowStartPanel"));
add(new RuleEditorPanel("ruleEditor", this));
}
private RepeatingView createEditorPanelForClass(Class<?> theClass) {
realValues.clear();
List<AttributeDefinition> attributes = MethodUtil.buildAttributesList(theClass);
moveNameToFront(attributes);
fieldList = AttributeEditorUtil.createFieldList("fields", attributes, realValues);
return fieldList;
}
private List<AttributeDefinition> moveNameToFront(List<AttributeDefinition> attributes) {
int i = 0;
for (AttributeDefinition a : attributes) {
if ("name".equals(a.getId())) {
break;
}
i++;
}
AttributeDefinition tmp = attributes.get(0);
attributes.set(0, attributes.get(i));
attributes.set(i, tmp);
return attributes;
}
private Event buildEvent(Class<?> eventClass, Map<String, String> values) {
try {
Event obj = (Event) eventClass.newInstance();
BeanInfo beanInfo = Introspector.getBeanInfo(eventClass);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
if (propertyDescriptor.getWriteMethod() == null
|| !Modifier.isPublic(propertyDescriptor.getWriteMethod().getModifiers())) {
continue;
}
String string = values.get(propertyDescriptor.getName());
Object converted = valueConverter.convert(propertyDescriptor.getPropertyType(), string);
propertyDescriptor.getWriteMethod().invoke(obj, converted);
}
return obj;
} catch (Exception e) {
LOGGER.error("building event instance failed", e);
return null;
}
}
@Override
public RuleManager getRuleManager() {
return ruleManager;
}
}