package sushi.application.pages.transformation.patternbuilder;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.apache.wicket.ajax.AjaxRequestTarget;
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.HeadersToolbar;
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.extensions.markup.html.repeater.tree.table.TreeColumn;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
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 org.apache.wicket.model.PropertyModel;
import sushi.application.components.form.WarnOnExitForm;
import sushi.application.components.tree.TreeExpansion;
import sushi.application.components.tree.TreeExpansionModel;
import sushi.application.components.tree.TreeTableProvider;
import sushi.application.pages.transformation.AdvancedTransformationRuleEditorPanel;
import sushi.application.pages.transformation.patternbuilder.model.ElementOptionsPanel;
import sushi.application.pages.transformation.patternbuilder.model.EventTypeAliasPanel;
import sushi.application.pages.transformation.patternbuilder.model.EventTypeElementOptionsPanel;
import sushi.application.pages.transformation.patternbuilder.model.EveryDistinctPatternOperatorPanel;
import sushi.application.pages.transformation.patternbuilder.model.FilterExpressionPanel;
import sushi.application.pages.transformation.patternbuilder.model.PatternElementTreeTable;
import sushi.application.pages.transformation.patternbuilder.model.RepeatPatternOperatorRangePanel;
import sushi.application.pages.transformation.patternbuilder.model.UntilPatternOperatorRangePanel;
import sushi.event.SushiEventType;
import sushi.event.collection.SushiTreeElement;
import sushi.transformation.collection.SushiPatternTree;
import sushi.transformation.element.EventTypeElement;
import sushi.transformation.element.FilterExpressionConnectorElement;
import sushi.transformation.element.FilterExpressionConnectorEnum;
import sushi.transformation.element.FilterExpressionElement;
import sushi.transformation.element.PatternOperatorElement;
import sushi.transformation.element.PatternOperatorEnum;
public class PatternBuilderPanel extends Panel {
private static final long serialVersionUID = -3517674159437927655L;
private SushiEventType selectedEventType;
private Form<Void> layoutForm;
private DropDownChoice<PatternOperatorEnum> patternOperatorDropDownChoice;
private PatternOperatorEnum selectedPatternOperator;
private DropDownChoice<SushiEventType> eventTypeDropDownChoice;
private TreeTableProvider<Serializable> patternTreeTableProvider;
private PatternElementTreeTable patternTreeTable;
private SushiPatternTree patternTree;
private PatternBuilderPanel patternBuilderPanel;
private AdvancedTransformationRuleEditorPanel advancedRuleEditorPanel;
private DropDownChoice<FilterExpressionConnectorEnum> filterExpressionConnectorDropDownChoice;
private FilterExpressionConnectorEnum filterExpressionConnector;
public PatternBuilderPanel(String id, final AdvancedTransformationRuleEditorPanel advancedRuleEditorPanel) {
super(id);
this.advancedRuleEditorPanel = advancedRuleEditorPanel;
this.patternBuilderPanel = this;
layoutForm = new WarnOnExitForm("layoutForm");
add(layoutForm);
patternTree = new SushiPatternTree();
patternTreeTableProvider = new TreeTableProvider<Serializable>(patternTree.getRoots());
buildEventTypeDropDownChoice();
buildPatternOperatorDropDownChoice();
buildFilterExpressionConnectorDropDownChoice();
buildButtons();
buildPatternTreeTable();
}
private void buildEventTypeDropDownChoice() {
List<SushiEventType> eventTypes = SushiEventType.findAll();
eventTypeDropDownChoice = new DropDownChoice<SushiEventType>("eventTypeDropDownChoice", new PropertyModel<SushiEventType>(this, "selectedEventType"), eventTypes);
eventTypeDropDownChoice.setOutputMarkupId(true);
layoutForm.add(eventTypeDropDownChoice);
}
private void buildPatternOperatorDropDownChoice() {
patternOperatorDropDownChoice = new DropDownChoice<PatternOperatorEnum>("patternOperatorDropDownChoice", new PropertyModel<PatternOperatorEnum>(this, "selectedPatternOperator"), Arrays.asList(PatternOperatorEnum.values()));
patternOperatorDropDownChoice.setOutputMarkupId(true);
patternOperatorDropDownChoice.setEnabled(false);
layoutForm.add(patternOperatorDropDownChoice);
}
private void buildFilterExpressionConnectorDropDownChoice() {
filterExpressionConnectorDropDownChoice = new DropDownChoice<FilterExpressionConnectorEnum>("filterExpressionConnectorDropDownChoice", new PropertyModel<FilterExpressionConnectorEnum>(this, "filterExpressionConnector"), Arrays.asList(FilterExpressionConnectorEnum.values()));
filterExpressionConnectorDropDownChoice.setOutputMarkupId(true);
filterExpressionConnectorDropDownChoice.setEnabled(false);
layoutForm.add(filterExpressionConnectorDropDownChoice);
}
private void buildButtons() {
AjaxButton addButton = new AjaxButton("addButton", layoutForm) {
private static final long serialVersionUID = 1L;
@Override
public void onSubmit(AjaxRequestTarget target, Form<?> form) {
SushiTreeElement<Serializable> newTreeElement;
Iterator<SushiTreeElement<Serializable>> iterator;
if (eventTypeDropDownChoice.isEnabled() && selectedEventType != null) {
newTreeElement = new EventTypeElement(patternTreeTableProvider.getNextID(), selectedEventType);
if (patternTreeTable.getSelectedElements().isEmpty()) {
patternTree.addElement(newTreeElement);
patternTreeTableProvider.setRootElements(patternTree.getRoots());
target.add(advancedRuleEditorPanel.getAttributeTreePanel().getAttributeTreeTable());
}
} else {
if (patternOperatorDropDownChoice.isEnabled() && selectedPatternOperator != null) {
newTreeElement = new PatternOperatorElement(patternTreeTableProvider.getNextID(), selectedPatternOperator);
} else if (filterExpressionConnectorDropDownChoice.isEnabled() && filterExpressionConnector != null) {
newTreeElement = new FilterExpressionConnectorElement(patternTreeTableProvider.getNextID(), filterExpressionConnector);
} else {
return;
}
iterator = patternTreeTable.getSelectedElements().iterator();
SushiTreeElement<Serializable> parentOfSelectedElements = iterator.next().getParent();
iterator = patternTreeTable.getSelectedElements().iterator();
while (iterator.hasNext()) {
iterator.next().setParent(newTreeElement);
}
if (parentOfSelectedElements != null) {
newTreeElement.setParent(parentOfSelectedElements);
iterator = patternTreeTable.getSelectedElements().iterator();
while (iterator.hasNext()) {
parentOfSelectedElements.removeChild(iterator.next());
}
}
patternTree.addElement(newTreeElement);
patternTreeTableProvider.setRootElements(patternTree.getRoots());
}
patternTreeTable.getSelectedElements().clear();
target.add(patternTreeTable);
updateOnTreeElementSelection(target);
}
};
layoutForm.add(addButton);
}
public DropDownChoice<SushiEventType> getEventTypeDropDownChoice() {
return eventTypeDropDownChoice;
}
public DropDownChoice<PatternOperatorEnum> getPatternOperatorDropDownChoice() {
return patternOperatorDropDownChoice;
}
public DropDownChoice<FilterExpressionConnectorEnum> getFilterExpressionConnectorDropDownChoice() {
return filterExpressionConnectorDropDownChoice;
}
public TreeTableProvider<Serializable> getPatternTreeTableProvider() {
return patternTreeTableProvider;
}
public PatternElementTreeTable getPatternTreeTable() {
return patternTreeTable;
}
public SushiPatternTree getPatternTree() {
return patternTree;
}
public void setPatternTree(SushiPatternTree patternTree) {
this.patternTree = patternTree;
}
public AdvancedTransformationRuleEditorPanel getAdvancedRuleEditorPanel() {
return advancedRuleEditorPanel;
}
private void buildPatternTreeTable() {
List<IColumn<SushiTreeElement<Serializable>, String>> columns = createColumns();
patternTreeTable = new PatternElementTreeTable(
"patternTreeTable",
columns,
patternTreeTableProvider,
Integer.MAX_VALUE,
new TreeExpansionModel<Serializable>(),
this);
patternTreeTable.setOutputMarkupId(true);
TreeExpansion.get().expandAll();
patternTreeTable.getTable().addTopToolbar(new HeadersToolbar<String>(patternTreeTable.getTable(), patternTreeTableProvider));
layoutForm.addOrReplace(patternTreeTable);
}
private List<IColumn<SushiTreeElement<Serializable>, String>> createColumns() {
List<IColumn<SushiTreeElement<Serializable>, String>> columns = new ArrayList<IColumn<SushiTreeElement<Serializable>, String>>();
columns.add(new PropertyColumn<SushiTreeElement<Serializable>, String>(Model.of("ID"), "ID"));
columns.add(new TreeColumn<SushiTreeElement<Serializable>, String>(Model.of("Elements")));
columns.add(new AbstractColumn<SushiTreeElement<Serializable>, String>(new Model("")) {
@Override
public void populateItem(Item cellItem, String componentId, IModel rowModel) {
Object treeTableElement = rowModel.getObject();
if (treeTableElement instanceof EventTypeElement) {
EventTypeElement eventTypeElement = (EventTypeElement) treeTableElement;
cellItem.add(new EventTypeAliasPanel(componentId, eventTypeElement, advancedRuleEditorPanel));
} else {
cellItem.add(new Label(componentId));
}
}
});
columns.add(new AbstractColumn<SushiTreeElement<Serializable>, String>(new Model("")) {
@Override
public void populateItem(Item cellItem, String componentId, IModel rowModel) {
Object treeTableElement = rowModel.getObject();
if (treeTableElement instanceof EventTypeElement) {
final EventTypeElement eventTypeElement = (EventTypeElement) treeTableElement;
cellItem.add(new EventTypeElementOptionsPanel(componentId, eventTypeElement, patternTree, patternTreeTableProvider, patternTreeTable, patternBuilderPanel));
} else if (treeTableElement instanceof FilterExpressionElement) {
FilterExpressionElement filterExpressionElement = (FilterExpressionElement) treeTableElement;
cellItem.add(new FilterExpressionPanel(componentId, filterExpressionElement, patternBuilderPanel));
} else if (treeTableElement instanceof PatternOperatorElement) {
PatternOperatorElement poElement = (PatternOperatorElement) treeTableElement;
if (poElement.getValue() == PatternOperatorEnum.UNTIL) {
cellItem.add(new UntilPatternOperatorRangePanel(componentId, poElement));
} else if (poElement.getValue() == PatternOperatorEnum.REPEAT) {
cellItem.add(new RepeatPatternOperatorRangePanel(componentId, poElement, advancedRuleEditorPanel));
} else if (poElement.getValue() == PatternOperatorEnum.EVERY_DISTINCT) {
cellItem.add(new EveryDistinctPatternOperatorPanel(componentId, poElement, advancedRuleEditorPanel));
} else {
cellItem.add(new Label(componentId));
}
} else {
cellItem.add(new Label(componentId));
}
}
});
columns.add(new AbstractColumn<SushiTreeElement<Serializable>, String>(new Model("")) {
@Override
public void populateItem(Item cellItem, String componentId, IModel rowModel) {
SushiTreeElement<Serializable> treeTableElement = (SushiTreeElement<Serializable>) rowModel.getObject();
cellItem.add(new ElementOptionsPanel(componentId, treeTableElement, patternBuilderPanel));
}
});
return columns;
}
public void updatePatternTreeTable(AjaxRequestTarget target) {
patternTreeTableProvider.setRootElements(patternTree.getRoots());
patternTreeTable.getSelectedElements().clear();
target.add(patternTreeTable);
updateOnTreeElementSelection(target);
}
public void updateOnTreeElementSelection(AjaxRequestTarget target) {
int numberOfSelectedElements = patternTreeTable.numberOfSelectedElements();
List<PatternOperatorEnum> operators;
List<FilterExpressionConnectorEnum> connectors;
SushiTreeElement<Serializable> firstSelectedElement;
if (numberOfSelectedElements == 0) {
eventTypeDropDownChoice.setEnabled(true);
patternOperatorDropDownChoice.setEnabled(false);
filterExpressionConnectorDropDownChoice.setEnabled(false);
} else if (numberOfSelectedElements == 1) {
firstSelectedElement = patternTreeTable.getSelectedElements().iterator().next();
if (firstSelectedElement instanceof FilterExpressionElement || firstSelectedElement instanceof FilterExpressionConnectorElement) {
connectors = FilterExpressionConnectorEnum.getUnaryOperators();
filterExpressionConnectorDropDownChoice.setChoices(connectors);
filterExpressionConnectorDropDownChoice.setEnabled(true);
patternOperatorDropDownChoice.setEnabled(false);
} else {
operators = PatternOperatorEnum.getUnaryOperators();
patternOperatorDropDownChoice.setChoices(operators);
filterExpressionConnectorDropDownChoice.setEnabled(false);
patternOperatorDropDownChoice.setEnabled(true);
}
eventTypeDropDownChoice.setEnabled(false);
} else if (numberOfSelectedElements == 2) {
firstSelectedElement = patternTreeTable.getSelectedElements().iterator().next();
if (firstSelectedElement instanceof FilterExpressionElement || firstSelectedElement instanceof FilterExpressionConnectorElement) {
connectors = FilterExpressionConnectorEnum.getBinaryOperators();
filterExpressionConnectorDropDownChoice.setChoices(connectors);
filterExpressionConnectorDropDownChoice.setEnabled(true);
patternOperatorDropDownChoice.setEnabled(false);
} else {
operators = PatternOperatorEnum.getBinaryOperators();
patternOperatorDropDownChoice.setChoices(operators);
filterExpressionConnectorDropDownChoice.setEnabled(false);
patternOperatorDropDownChoice.setEnabled(true);
}
eventTypeDropDownChoice.setEnabled(false);
} else {
patternOperatorDropDownChoice.setEnabled(false);
eventTypeDropDownChoice.setEnabled(false);
}
target.add(filterExpressionConnectorDropDownChoice);
target.add(patternOperatorDropDownChoice);
target.add(eventTypeDropDownChoice);
}
public void clear(AjaxRequestTarget target) {
eventTypeDropDownChoice.setEnabled(true);
patternOperatorDropDownChoice.setEnabled(false);
filterExpressionConnectorDropDownChoice.setEnabled(false);
target.add(eventTypeDropDownChoice);
target.add(patternOperatorDropDownChoice);
target.add(filterExpressionConnectorDropDownChoice);
patternTree = new SushiPatternTree();
patternTreeTableProvider.setRootElements(patternTree.getRoots());
target.add(patternTreeTable);
}
}