package org.aperteworkflow.editor.actioneditor; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.terminal.ParameterHandler; import com.vaadin.ui.*; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import org.apache.commons.lang.StringUtils; import org.aperteworkflow.editor.stepeditor.JavaScriptHelper; import org.aperteworkflow.editor.stepeditor.user.Property; import org.aperteworkflow.editor.ui.property.PropertiesPanel; import org.aperteworkflow.editor.vaadin.GenericEditorApplication; import org.aperteworkflow.util.vaadin.VaadinUtility; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.map.JsonMappingException; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.type.TypeReference; import pl.net.bluesoft.rnd.processtool.ui.widgets.ProcessToolActionButton; import pl.net.bluesoft.rnd.processtool.ui.widgets.annotations.AliasName; import pl.net.bluesoft.rnd.util.i18n.I18NSource; import pl.net.bluesoft.util.lang.Classes; import java.io.IOException; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import static pl.net.bluesoft.rnd.processtool.model.config.ProcessStateAction.getAutowiredPropertyNames; public class ActionEditorApplication extends GenericEditorApplication implements ParameterHandler, ClickListener { private static final long serialVersionUID = 2136349126207525109L; private static final Logger logger = Logger.getLogger(ActionEditorApplication.class.getName()); private PropertiesPanel propertiesPanel = new PropertiesPanel(); private Button saveButton; private Select buttonList; private static final ObjectMapper mapper = new ObjectMapper(); private Window mainWindow; private JavaScriptHelper jsHelper; private String url; private Map<String,Object> oldActionParameters = new HashMap<String,Object>(); private Map<String,Object> oldActionAttributes = new HashMap<String,Object>(); @Override public void handleParameters(Map<String, String[]> parameters) { if (parameters == null || parameters.size() == 0) { // No parameters to handle, we are not interested in such a request // it may be a request for static resource e.g. // <servlet>/APP/323/root.gif return; } url = getStringParameterByName("callbackUrl", parameters); String buttonType = getStringParameterByName("buttonType", parameters); String buttonName = getStringParameterByName("buttonName", parameters); String actionParameters = getStringParameterByName("actionParameters", parameters); String actionAttributes = getStringParameterByName("actionAttributes", parameters); try { if (!StringUtils.isEmpty(actionParameters)) { oldActionParameters=mapper.readValue(actionParameters, new TypeReference<HashMap<String,Object>>(){}); } if (!StringUtils.isEmpty(actionAttributes)) { oldActionAttributes=mapper.readValue(actionAttributes, new TypeReference<HashMap<String,Object>>(){}); if(!oldActionParameters.isEmpty()){ oldActionParameters.putAll(oldActionAttributes); } } } catch (JsonParseException e) { logger.log(Level.SEVERE, "Error reading action parameters", e); } catch (JsonMappingException e) { logger.log(Level.SEVERE, "Error reading action parameters", e); } catch (IOException e) { logger.log(Level.SEVERE, "Error reading action parameters", e); } refreshWindow(buttonType, buttonName); } private void refreshWindow(String buttonType, String buttonName) { mainWindow.removeAllComponents(); VerticalLayout main = new VerticalLayout(); main.setMargin(true); Label header = new Label(); if (StringUtils.isEmpty(buttonName)) header.setCaption("[No button name]"); else header.setCaption("Button name: " + buttonName); main.addComponent(header); buttonList = prepareButtonList(buttonType); main.addComponent(buttonList); if (!StringUtils.isEmpty(buttonType)) { Class<? extends ProcessToolActionButton> buttonClass = getRegistry().getAvailableButtons().get(buttonType); propertiesPanel.init(buttonClass); propertiesPanel.refreshForm(true, oldActionParameters); main.addComponent(propertiesPanel); } saveButton = new Button("save", this); saveButton.setImmediate(true); main.addComponent(saveButton); mainWindow.setContent(main); } @Override public void init() { super.init(); mainWindow = new Window(I18NSource.ThreadUtil.getThreadI18nSource().getMessage("application.title")); jsHelper = new JavaScriptHelper(mainWindow); jsHelper.preventWindowClosing(); mainWindow.addParameterHandler(this); setMainWindow(mainWindow); } private Select prepareButtonList(String buttonType) { final Select buttonList = new Select(); buttonList.setNullSelectionAllowed(false); buttonList.setImmediate(true); // method-level class used for sorting class Item implements Comparable<Item> { public Class<? extends ProcessToolActionButton> stepClass; public String caption; public Item(Class<? extends ProcessToolActionButton> stepClass, String caption) { this.stepClass = stepClass; this.caption = caption; } @Override public int compareTo(Item o) { return caption.compareTo(o.caption); } } List<Item> items = new LinkedList<Item>(); Class<? extends ProcessToolActionButton> active = null; Map<String, Class<? extends ProcessToolActionButton>> availableButtons = getRegistry().getAvailableButtons(); for (Class<? extends ProcessToolActionButton> stepClass : availableButtons.values()) { AliasName a = Classes.getClassAnnotation(stepClass, AliasName.class); items.add(new Item(stepClass,a.name())); if (a.name().equals(buttonType)) active=stepClass; } Collections.sort(items); for (Item item:items){ buttonList.addItem(item.stepClass); buttonList.setItemCaption(item.stepClass, item.caption); } buttonList.setValue(active); buttonList.addListener(new Property.ValueChangeListener() { @Override public void valueChange(ValueChangeEvent event) { Class<?> buttonClass = (Class<?>) buttonList.getValue(); propertiesPanel.init(buttonClass); propertiesPanel.refreshForm(true, oldActionParameters); } }); return buttonList; } @Override public void buttonClick(ClickEvent event) { if (event.getComponent() == saveButton) { if (!propertiesPanel.getPropertiesForm().isValid()) { getCurrent().getMainWindow().showNotification(VaadinUtility.validationNotification("Validation error", "Correct data")); return; } ActionDef actionDef = new ActionDef(); actionDef.setButtonType(buttonList.getItemCaption(buttonList.getValue())); //Map<String, Object> codedPropertiesValue = codePropertiesValue(propertiesPanel.getPropertiesMap()); actionDef.setItems(getProperties()); actionDef.setAttributes(getAttributes()); try { String s = mapper.writeValueAsString(actionDef); jsHelper.postAndRedirectAction(url, s); } catch (JsonMappingException e) { logger.log(Level.SEVERE, "Error saving action", e); } catch (JsonGenerationException e) { logger.log(Level.SEVERE, "Error saving action", e); } catch (IOException e) { logger.log(Level.SEVERE, "Error saving action", e); } } } private Map<String, Object> getProperties() { return getStringObjectMap(true); } private Map<String, Object> getAttributes() { return getStringObjectMap(false); } private Map<String, Object> getStringObjectMap(boolean copyAutowiredProperties) { Map<String, Object> result = new HashMap<String, Object>(); for (Map.Entry<String, Object> entry : propertiesPanel.getPropertiesMap().entrySet()) { if (isAutowiredProperty(entry.getKey()) == copyAutowiredProperties) { result.put(entry.getKey(), entry.getValue()); } } return result; } private boolean isAutowiredProperty(String key) { return getAutowiredPropertyNames().contains(key); } }