package sushi.application.pages.transformation;
import java.util.ArrayList;
import java.util.List;
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.tree.AbstractTree;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
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.TreeProvider;
import sushi.application.components.tree.SushiSelectTree;
import sushi.application.pages.AbstractSushiPage;
import sushi.event.SushiEventType;
import sushi.event.attribute.SushiAttribute;
import sushi.event.collection.SushiTree;
import sushi.event.collection.SushiTreeElement;
import sushi.transformation.TransformationManager;
import sushi.transformation.TransformationRule;
import com.espertech.esper.client.EPException;
public class BasicTransformationRuleEditorPanel extends Panel {
private static final long serialVersionUID = -3517674159437927655L;
private String selectedEventTypeName;
private SushiEventType selectedEventType;
private String transformationRule;
private TextField<String> transformationRuleNameTextField;
private String transformationRuleName;
private Form<Void> layoutForm;
private TextArea<String> transformationRuleTextArea;
private SushiSelectTree<SushiTreeElement<String>> transformationRuleTree;
private SushiTree<String> transformationRuleTreeStructure;
private DropDownChoice<String> eventTypeDropDownChoice;
private TransformationPage transformationPage;
private TransformationManager transformationManager;
public BasicTransformationRuleEditorPanel(String id, final TransformationPage transformationPage) {
super(id);
this.transformationPage = transformationPage;
this.transformationManager = transformationPage.getTransformationManager();
layoutForm = new WarnOnExitForm("layoutForm");
add(layoutForm);
buildTextFields();
buildTransformationRuleTree();
buildButtons();
}
private void buildTextFields() {
transformationRuleNameTextField = new TextField<String>("transformationRuleNameTextField", new PropertyModel<String>(this, "transformationRuleName"));
transformationRuleNameTextField.setOutputMarkupId(true);
layoutForm.add(transformationRuleNameTextField);
List<String> eventTypes = SushiEventType.getAllTypeNames();
eventTypeDropDownChoice = new DropDownChoice<String>("eventTypeDropDownChoice", new PropertyModel<String>(this, "selectedEventTypeName"), eventTypes);
eventTypeDropDownChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
private static final long serialVersionUID = 1L;
@Override
protected void onUpdate(AjaxRequestTarget target) {
updateOnChangeOfDropDownChoice(target);
}
});
layoutForm.add(eventTypeDropDownChoice);
transformationRuleTextArea = new TextArea<String>("transformationRuleTextArea", new PropertyModel<String>(this, "transformationRule"));
transformationRuleTextArea.setOutputMarkupId(true);
layoutForm.add(transformationRuleTextArea);
}
protected void updateOnChangeOfDropDownChoice(AjaxRequestTarget target) {
selectedEventType = SushiEventType.findByTypeName(selectedEventTypeName);
if (selectedEventType != null) {
// inform user about rule schema
List<SushiAttribute> selectedEventTypeAttributes = selectedEventType.getValueTypes();
StringBuffer transformationSuggestionBuffer = new StringBuffer();
transformationSuggestionBuffer.append("Your transformation rule may start with: SELECT ");
if (selectedEventType.getTimestampName() != null) {
transformationSuggestionBuffer.append("[...] AS Timestamp, ");
}
for (int i = 0; i < selectedEventTypeAttributes.size(); i++) {
transformationSuggestionBuffer.append("[...] AS " + selectedEventTypeAttributes.get(i).getAttributeExpression());
if (i == selectedEventTypeAttributes.size() - 1) {
transformationSuggestionBuffer.append(" ");
} else {
transformationSuggestionBuffer.append(", ");
}
}
transformationPage.getFeedbackPanel().info(transformationSuggestionBuffer.toString());
target.add(transformationPage.getFeedbackPanel());
} else {
target.add(transformationPage.getFeedbackPanel());
}
}
private void buildButtons() {
AjaxButton editButton = new AjaxButton("editButton") {
private static final long serialVersionUID = 1L;
@Override
public void onSubmit(AjaxRequestTarget target, Form form) {
if (transformationRuleTree.getSelectedElement() != null) {
selectedEventTypeName = transformationRuleTree.getSelectedElement().getParent().getValue().toString();
transformationRuleName = transformationRuleTree.getSelectedElement().getValue().toString();
transformationRule = TransformationRule.findByEventTypeAndTitle(selectedEventTypeName, transformationRuleName).getQuery();
target.add(transformationRuleNameTextField);
target.add(eventTypeDropDownChoice);
target.add(transformationRuleTextArea);
updateOnChangeOfDropDownChoice(target);
}
}
};
layoutForm.add(editButton);
AjaxButton deleteButton = new AjaxButton("deleteButton") {
private static final long serialVersionUID = 1L;
@Override
public void onSubmit(AjaxRequestTarget target, Form form) {
if (transformationRuleTree.getSelectedElement() != null) {
String eventTypeNameFromTree = transformationRuleTree.getSelectedElement().getParent().getValue().toString();
String transformationRuleNameFromTree = transformationRuleTree.getSelectedElement().getValue().toString();
removeTransformationRule(eventTypeNameFromTree, transformationRuleNameFromTree);
renderOrUpdateTransformationRuleTree();
target.add(transformationRuleTree);
clearFields(target);
}
}
};
layoutForm.add(deleteButton);
AjaxButton saveButton = new AjaxButton("saveButton", layoutForm) {
private static final long serialVersionUID = 1L;
@Override
public void onSubmit(AjaxRequestTarget target, Form form) {
try {
if (transformationRuleName == null || transformationRuleName.isEmpty()) {
transformationPage.getFeedbackPanel().error("Please enter an transformation rule name!");
target.add(transformationPage.getFeedbackPanel());
} else if (selectedEventType == null) {
transformationPage.getFeedbackPanel().error("Please select an event type!");
target.add(transformationPage.getFeedbackPanel());
} else if (transformationRule == null || transformationRule.isEmpty()) {
transformationPage.getFeedbackPanel().error("Please enter an transformation rule!");
target.add(transformationPage.getFeedbackPanel());
} else {
saveTransformationRule(target, selectedEventType, transformationRuleName, transformationRule);
}
} catch (EPException e) {
transformationPage.getFeedbackPanel().error(e.getMessage());
target.add(transformationPage.getFeedbackPanel());
}
}
};
layoutForm.add(saveButton);
}
private void clearFields(AjaxRequestTarget target) {
transformationRuleName = "";
target.add(transformationRuleNameTextField);
selectedEventTypeName = null;
target.add(eventTypeDropDownChoice);
transformationRule = "";
target.add(transformationRuleTextArea);
}
private void saveTransformationRule(AjaxRequestTarget target, SushiEventType selectedEventType, String transformationRuleName, String transformationRule) {
if (TransformationRule.findByEventTypeAndTitle(selectedEventTypeName, transformationRuleName) != null) {
removeTransformationRule(selectedEventTypeName, transformationRuleName);
}
addTransformationRule(selectedEventType, transformationRuleName, transformationRule);
renderOrUpdateTransformationRuleTree();
target.add(transformationRuleTree);
transformationPage.getFeedbackPanel().success("Saved transformation rule '" + transformationRuleName + "' for event type '" + selectedEventTypeName + "'.");
target.add(transformationPage.getFeedbackPanel());
}
protected void addTransformationRule(SushiEventType selectedEventType, String transformationRuleName, String transformationQuery) throws EPException {
TransformationRule transformationRule = new TransformationRule(selectedEventType, transformationRuleName, transformationQuery);
transformationManager.register(transformationRule);
transformationRule.save();
String eventTypeName = selectedEventType.getTypeName();
addTransformationRuleToTreeStructure(eventTypeName, transformationRuleName);
}
protected void removeTransformationRule(String eventTypeName, String title) {
transformationRuleTreeStructure.removeChild(eventTypeName, title);
TransformationRule transformationRule = TransformationRule.findByEventTypeAndTitle(eventTypeName, title);
transformationManager.removeFromEsper(transformationRule);
transformationRule.remove();
}
private void addTransformationRuleToTreeStructure(String eventTypeName, String transformationRuleName) {
if (!transformationRuleTreeStructure.containsRootElement(eventTypeName)) {
transformationRuleTreeStructure.addRootElement(eventTypeName);
}
transformationRuleTreeStructure.addChild(eventTypeName, transformationRuleName);
}
private void buildTransformationRuleTree() {
transformationRuleTreeStructure = new SushiTree<String>();
List<TransformationRule> transformationRules = TransformationRule.findAll();
for (TransformationRule transformationRule : transformationRules) {
addTransformationRuleToTreeStructure(transformationRule.getEventType().getTypeName(), transformationRule.getTitle());
}
renderOrUpdateTransformationRuleTree();
}
private void renderOrUpdateTransformationRuleTree() {
transformationRuleTree = new SushiSelectTree<SushiTreeElement<String>>("transformationRuleTree", new TreeProvider<String>(generateNodesOfTransformationRuleTree()), new TreeExpansionModel<String>()) {
private static final long serialVersionUID = 1L;
@Override
protected void select(SushiTreeElement<String> element, AbstractTree<SushiTreeElement<String>> tree, final AjaxRequestTarget target) {
// only the transformation rules are selectable
if (element.hasParent()) {
super.select(element, tree, target);
}
}
};
TreeExpansion.get().expandAll();
transformationRuleTree.setOutputMarkupId(true);
layoutForm.addOrReplace(transformationRuleTree);
}
private ArrayList<SushiTreeElement<String>> generateNodesOfTransformationRuleTree() {
ArrayList<SushiTreeElement<String>> treeElements = new ArrayList<SushiTreeElement<String>>();
List<String> eventTypes = transformationRuleTreeStructure.getRootElements();
for (String eventType : eventTypes) {
SushiTreeElement<String> rootElement = new SushiTreeElement<String>(eventType);
treeElements.add(rootElement);
if (transformationRuleTreeStructure.hasChildren(eventType)) {
fillTreeLevel(rootElement, transformationRuleTreeStructure.getChildren(eventType), transformationRuleTreeStructure);
}
}
return treeElements;
}
private void fillTreeLevel(SushiTreeElement<String> parent, List<String> children, SushiTree<String> transformationRuleTreeStructure) {
for (String newValue : children) {
SushiTreeElement<String> newElement = new SushiTreeElement<String>(parent, newValue.toString());
if (transformationRuleTreeStructure.hasChildren(newValue)) {
fillTreeLevel(newElement, transformationRuleTreeStructure.getChildren(newValue), transformationRuleTreeStructure);
}
}
}
}