package sushi.application.pages.transformation.patternbuilder.externalknowledge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.markup.html.repeater.data.table.AbstractColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DefaultDataTable;
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
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.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import sushi.application.components.form.WarnOnExitForm;
import sushi.application.components.table.SelectEntryPanel;
import sushi.application.pages.input.model.EventAttributeProvider;
import sushi.application.pages.transformation.patternbuilder.model.AttributeSelectionPanel;
import sushi.application.pages.transformation.patternbuilder.model.CriteriaValuePanel;
import sushi.event.SushiEventType;
import sushi.event.attribute.SushiAttribute;
import sushi.event.attribute.SushiAttributeTypeEnum;
import sushi.transformation.collection.SushiPatternTree;
import sushi.transformation.element.externalknowledge.ExternalKnowledgeExpression;
import sushi.transformation.element.externalknowledge.ExternalKnowledgeExpressionSet;
public class ExternalKnowledgePanel extends Panel {
private static final long serialVersionUID = -1960020152680528731L;
private WarnOnExitForm layoutForm;
private SushiAttribute attributeToFill;
private SushiPatternTree patternTree;
private ListView<ExternalKnowledgeExpression> criteriaAttributesAndValuesListView;
private WebMarkupContainer container;
private String attributeIdentifier;
private Map<String, String> attributeIdentifiersAndExpressions;
private Map<String, ExternalKnowledgeExpressionSet> attributeIdentifiersWithExternalKnowledge;
private List<ExternalKnowledgeExpression> coalesceExpressions;
private TextField<String> defaultValueInput;
private ExternalKnowledgeExpressionSet externalKnowledgeExpressionSet;
private AttributeSelectionPanel parentPanel;
public ExternalKnowledgePanel(String id) {
super(id);
this.patternTree = new SushiPatternTree();
this.attributeToFill = new SushiAttribute("default", SushiAttributeTypeEnum.STRING);
this.attributeIdentifier = attributeToFill.getAttributeExpression();
layoutForm = new WarnOnExitForm("layoutForm");
add(layoutForm);
this.coalesceExpressions = new ArrayList<ExternalKnowledgeExpression>();
this.coalesceExpressions.add(new ExternalKnowledgeExpression());
buildHeader();
buildCriteriaAttributesAndValuesListView();
buildFooter();
}
private void buildHeader() {
Label attributeToFillLabel = new Label("attributeToFillLabel", "Attribute: " +
attributeToFill.getAttributeExpression() + " (" + attributeToFill.getType() + ")");
layoutForm.addOrReplace(attributeToFillLabel);
AjaxButton addCriteriaAttributesAndValuesButton = new AjaxButton("addCriteriaAttributesAndValuesButton", layoutForm) {
private static final long serialVersionUID = 6456362459418575615L;
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
coalesceExpressions.add(new ExternalKnowledgeExpression());
criteriaAttributesAndValuesListView.setList(coalesceExpressions);
target.add(container);
}
};
layoutForm.addOrReplace(addCriteriaAttributesAndValuesButton);
}
private void buildCriteriaAttributesAndValuesListView() {
criteriaAttributesAndValuesListView = new ListView<ExternalKnowledgeExpression>("criteriaAttributesAndValuesListView", coalesceExpressions) {
private static final long serialVersionUID = -553434279906525757L;
private DropDownChoice<SushiEventType> eventTypeDropDownChoice;
private DropDownChoice<SushiAttribute> desiredAttributeDropDownChoice;
private Component criteriaAttributesAndValuesTable;
private ArrayList<IColumn<SushiAttribute, String>> criteriaAttributeAndValueColumns;
@Override
protected void populateItem(ListItem<ExternalKnowledgeExpression> item) {
ExternalKnowledgeExpression expression = item.getModelObject();
buildComponents(item, expression);
}
private void buildComponents(final ListItem<ExternalKnowledgeExpression> item, final ExternalKnowledgeExpression expression) {
ListView<ExternalKnowledgeExpression> listView = this;
List<SushiEventType> eventTypes = SushiEventType.findAll();
final EventAttributeProvider eventAttributeProvider;
final Map<String, String> criteriaAttributesAndValues;
if (expression.getCriteriaAttributesAndValues() == null || expression.getCriteriaAttributesAndValues().isEmpty()) {
criteriaAttributesAndValues = new HashMap<String, String>();
} else {
criteriaAttributesAndValues = expression.getCriteriaAttributesAndValues();
}
eventTypeDropDownChoice = new DropDownChoice<SushiEventType>("eventTypeDropDownChoice", new Model<SushiEventType>(), eventTypes);
eventTypeDropDownChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
private static final long serialVersionUID = 1L;
@Override
protected void onUpdate(AjaxRequestTarget target) {
if (eventTypeDropDownChoice.getModelObject() != null) {
List<SushiAttribute> relevantAttributes = new ArrayList<SushiAttribute>();
for (SushiAttribute attribute : eventTypeDropDownChoice.getModelObject().getValueTypes()) {
if (attributeToFill.getType() == attribute.getType()) {
relevantAttributes.add(attribute);
}
}
desiredAttributeDropDownChoice.setChoices(relevantAttributes);
} else {
desiredAttributeDropDownChoice.setChoices(new ArrayList<SushiAttribute>());
}
target.add(desiredAttributeDropDownChoice);
final EventAttributeProvider eventAttributeProvider = new EventAttributeProvider(new ArrayList<SushiAttribute>());
renderOrUpdateTable(item, eventAttributeProvider);
target.add(criteriaAttributesAndValuesTable);
}
});
eventTypeDropDownChoice.setModelObject(expression.getEventType());
item.add(eventTypeDropDownChoice);
desiredAttributeDropDownChoice = new DropDownChoice<SushiAttribute>("desiredAttributeDropDownChoice", new Model<SushiAttribute>(), new ArrayList<SushiAttribute>(),
new ChoiceRenderer<SushiAttribute>() {
private static final long serialVersionUID = -1940950340293620814L;
@Override
public Object getDisplayValue(SushiAttribute element) {
return element.getAttributeExpression();
}
}
);
desiredAttributeDropDownChoice.setOutputMarkupId(true);
desiredAttributeDropDownChoice.add(new AjaxFormComponentUpdatingBehavior("onChange"){
private static final long serialVersionUID = -6864036894506127410L;
@Override
protected void onUpdate(AjaxRequestTarget target) {
List<SushiAttribute> attributes = eventTypeDropDownChoice.getModelObject().getValueTypes();
attributes.remove(desiredAttributeDropDownChoice.getModelObject());
final EventAttributeProvider eventAttributeProvider = new EventAttributeProvider(attributes);
renderOrUpdateTable(item, eventAttributeProvider);
target.add(criteriaAttributesAndValuesTable);
for (SushiAttribute expression : attributes) {
criteriaAttributesAndValues.put(expression.getAttributeExpression(), null);
}
}
});
if (eventTypeDropDownChoice.getModelObject() != null) {
desiredAttributeDropDownChoice.setChoices(eventTypeDropDownChoice.getModelObject().getValueTypes());
desiredAttributeDropDownChoice.setModelObject(expression.getDesiredAttribute());
}
item.add(desiredAttributeDropDownChoice);
if (eventTypeDropDownChoice.getModelObject() == null) {
eventAttributeProvider = new EventAttributeProvider(new ArrayList<SushiAttribute>());
} else {
List<SushiAttribute> attributes = eventTypeDropDownChoice.getModelObject().getValueTypes();
attributes.remove(desiredAttributeDropDownChoice.getModelObject());
ArrayList<SushiAttribute> selectedAttributes = new ArrayList<SushiAttribute>();
for (SushiAttribute attribute : attributes) {
if (expression.getCriteriaAttributesAndValues().get(attribute.getAttributeExpression()) != null) {
selectedAttributes.add(attribute);
}
}
eventAttributeProvider = new EventAttributeProvider(attributes, selectedAttributes);
}
criteriaAttributeAndValueColumns = new ArrayList<IColumn<SushiAttribute, String>>();
criteriaAttributeAndValueColumns.add(new AbstractColumn<SushiAttribute, String>(new Model<String>("")) {
private static final long serialVersionUID = -9120188492434788547L;
@Override
public void populateItem(Item cellItem, String componentId, IModel rowModel) {
int entryId = ((SushiAttribute) rowModel.getObject()).getID();
cellItem.add(new SelectEntryPanel(componentId, entryId, eventAttributeProvider));
}
});
criteriaAttributeAndValueColumns.add(new PropertyColumn<SushiAttribute, String>(Model.of("Attribute"), "attributeExpression"));
criteriaAttributeAndValueColumns.add(new AbstractColumn<SushiAttribute, String>(new Model<String>("Value")) {
private static final long serialVersionUID = -5994858051827872697L;
@Override
public void populateItem(Item cellItem, String componentId, final IModel rowModel) {
String attributeExpression = ((SushiAttribute) rowModel.getObject()).getAttributeExpression();
cellItem.add(new CriteriaValuePanel(componentId, attributeExpression, criteriaAttributesAndValues, patternTree));
}
});
renderOrUpdateTable(item, eventAttributeProvider);
AjaxButton saveCoalesceExpressionButton = new AjaxButton("saveCoalesceExpressionButton", layoutForm) {
private static final long serialVersionUID = 6456362459418575615L;
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
Map<String, String> newCriteriaAttributesAndValues = new HashMap<String, String>();
for (String criteriaAttribute : criteriaAttributesAndValues.keySet()) {
if (eventAttributeProvider.getSelectedAttributeExpressions().contains(criteriaAttribute)) {
newCriteriaAttributesAndValues.put(criteriaAttribute, criteriaAttributesAndValues.get(criteriaAttribute));
}
}
coalesceExpressions.remove(item.getModelObject());
coalesceExpressions.add(new ExternalKnowledgeExpression(eventTypeDropDownChoice.getModelObject(), desiredAttributeDropDownChoice.getModelObject(), newCriteriaAttributesAndValues));
criteriaAttributesAndValuesListView.setList(coalesceExpressions);
target.add(container);
}
};
item.add(saveCoalesceExpressionButton);
AjaxButton removeCoalesceExpressionButton = new AjaxButton("removeCoalesceExpressionButton", layoutForm) {
private static final long serialVersionUID = 6456362459418575615L;
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
coalesceExpressions.remove(item.getModelObject());
criteriaAttributesAndValuesListView.setList(coalesceExpressions);
target.add(container);
}
};
item.add(removeCoalesceExpressionButton);
}
private void renderOrUpdateTable(ListItem<ExternalKnowledgeExpression> item, EventAttributeProvider eventAttributeProvider) {
criteriaAttributesAndValuesTable = new DefaultDataTable<SushiAttribute, String>("criteriaAttributesAndValuesTable", criteriaAttributeAndValueColumns, eventAttributeProvider, 20);
criteriaAttributesAndValuesTable.setOutputMarkupId(true);
item.addOrReplace(criteriaAttributesAndValuesTable);
}
};
criteriaAttributesAndValuesListView.setOutputMarkupId(true);
container = new WebMarkupContainer("criteriaAttributesAndValuesContainer");
container.addOrReplace(criteriaAttributesAndValuesListView);
container.setOutputMarkupId(true);
layoutForm.addOrReplace(container);
}
private void buildFooter() {
defaultValueInput = new TextField<String>("defaultValueInput", new Model<String>());
defaultValueInput.setOutputMarkupId(true);
if (externalKnowledgeExpressionSet != null) {
defaultValueInput.setModelObject(externalKnowledgeExpressionSet.getDefaultValue());
} else {
defaultValueInput.setModelObject("");
}
layoutForm.addOrReplace(defaultValueInput);
final Label feedbackLabel = new Label("feedbackLabel", new Model<String>());
feedbackLabel.setEscapeModelStrings(false);
feedbackLabel.setOutputMarkupId(true);
layoutForm.addOrReplace(feedbackLabel);
AjaxButton removeExpressionButton = new AjaxButton("removeExpressionButton", layoutForm) {
private static final long serialVersionUID = 6456362459418575615L;
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
attributeIdentifiersWithExternalKnowledge.remove(attributeIdentifier);
parentPanel.enableAllComponents(target);
}
};
layoutForm.addOrReplace(removeExpressionButton);
AjaxButton saveExpressionButton = new AjaxButton("saveExpressionButton", layoutForm) {
private static final long serialVersionUID = 6456362459418575615L;
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
if (coalesceExpressions.isEmpty()) {
feedbackLabel.setDefaultModelObject("<font color=\"red\">Please provide external knowledge.</font>");
target.add(feedbackLabel);
return;
} else {
for (ExternalKnowledgeExpression expression : coalesceExpressions) {
if (expression.getEventType() == null) {
feedbackLabel.setDefaultModelObject("<font color=\"red\">Please choose an event type.</font>");
target.add(feedbackLabel);
return;
} else if (expression.getDesiredAttribute() == null) {
feedbackLabel.setDefaultModelObject("<font color=\"red\">Please choose a desired attribute.</font>");
target.add(feedbackLabel);
return;
} else if (expression.getCriteriaAttributesAndValues().isEmpty()) {
feedbackLabel.setDefaultModelObject("<font color=\"red\">Please provide at least one attribute with a value.</font>");
target.add(feedbackLabel);
return;
}
}
}
if (externalKnowledgeExpressionSet == null) {
externalKnowledgeExpressionSet = new ExternalKnowledgeExpressionSet(attributeToFill.getType(), attributeIdentifier);
}
externalKnowledgeExpressionSet.setDefaultValue(defaultValueInput.getModelObject());
externalKnowledgeExpressionSet.setResultingType(attributeToFill.getType());
externalKnowledgeExpressionSet.setExternalKnowledgeExpressions(coalesceExpressions);
attributeIdentifiersWithExternalKnowledge.put(attributeIdentifier, externalKnowledgeExpressionSet);
attributeIdentifiersAndExpressions.put(attributeIdentifier, null);
parentPanel.disableAllComponents(target);
feedbackLabel.setDefaultModelObject("<font color=\"green\">Information about external knowledge saved.</font>");
target.add(feedbackLabel);
}
};
layoutForm.addOrReplace(saveExpressionButton);
}
public SushiAttribute getAttributeToFill() {
return attributeToFill;
}
public void setAttributeToFill(SushiAttribute attributeToFill) {
this.attributeToFill = attributeToFill;
if (attributeToFill.isTimestamp()) {
this.attributeIdentifier = "Timestamp";
} else {
this.attributeIdentifier = attributeToFill.getAttributeExpression();
}
}
public Map<String, String> getAttributeIdentifiersAndExpressions() {
return attributeIdentifiersAndExpressions;
}
public void setAttributeIdentifiersAndExpressions(
Map<String, String> attributeIdentifiersAndExpressions) {
this.attributeIdentifiersAndExpressions = attributeIdentifiersAndExpressions;
}
public Map<String, ExternalKnowledgeExpressionSet> getAttributeIdentifiersWithExternalKnowledge() {
return attributeIdentifiersWithExternalKnowledge;
}
public void setAttributeIdentifiersWithExternalKnowledge(Map<String, ExternalKnowledgeExpressionSet> attributeIdentifiersWithExternalKnowledge) {
this.attributeIdentifiersWithExternalKnowledge = attributeIdentifiersWithExternalKnowledge;
this.externalKnowledgeExpressionSet = attributeIdentifiersWithExternalKnowledge.get(attributeIdentifier);
if (externalKnowledgeExpressionSet == null) {
this.coalesceExpressions = new ArrayList<ExternalKnowledgeExpression>();
this.coalesceExpressions.add(new ExternalKnowledgeExpression());
} else {
this.coalesceExpressions = externalKnowledgeExpressionSet.getExternalKnowledgeExpressions();
}
}
public SushiPatternTree getPatternTree() {
return patternTree;
}
public void setPatternTree(SushiPatternTree patternTree) {
this.patternTree = patternTree;
}
public AttributeSelectionPanel getParentPanel() {
return parentPanel;
}
public void setParentPanel(AttributeSelectionPanel parentPanel) {
this.parentPanel = parentPanel;
}
public void update(AjaxRequestTarget target) {
buildHeader();
buildCriteriaAttributesAndValuesListView();
buildFooter();
target.add(container);
target.add(defaultValueInput);
}
}