WorkflowDesigner.java :  » Workflow-Engines » OSWorkflow » com » opensymphony » workflow » designer » Java Open Source

Java Open Source » Workflow Engines » OSWorkflow 
OSWorkflow » com » opensymphony » workflow » designer » WorkflowDesigner.java
package com.opensymphony.workflow.designer;

import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import com.opensymphony.workflow.FactoryException;
import com.opensymphony.workflow.InvalidWorkflowDescriptorException;
import com.opensymphony.workflow.config.WorkspaceManager;
import com.opensymphony.workflow.designer.dialogs.NewWorkspaceDialog;
import com.opensymphony.workflow.designer.editor.*;
import com.opensymphony.workflow.designer.swing.*;
import com.opensymphony.workflow.designer.swing.status.StatusBar;
import com.opensymphony.workflow.loader.*;
import org.jgraph.event.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * @author Hani Suleiman (hani@formicary.net) Date: May 15, 2003 Time: 8:36:20 PM
 */
public class WorkflowDesigner extends JFrame implements GraphSelectionListener, GraphModelListener
{
  public static final String WORKSPACE_SUFFIX = ".wsf";

  private WorkspaceNavigator navigator;
  private WorkspaceManager manager = new WorkspaceManager();
  private GraphTabbedPane graphTabs = new GraphTabbedPane();
  private DesignerService service = null;
  private JSplitPane mainSplitPane;
  private EmptyBorderSplitPane leftSplitPane;
  private CardPanel detailPanel = new CardPanel();
  private FramePanel detailFramePanel;
  private Object currentDetailObject = null;
  public static WorkflowDesigner INSTANCE = null;
  private PaletteDescriptor palette = null;
  public StatusBar statusBar;

  public WorkflowDesigner(Splash splash)
  {
    super(ResourceManager.getString("app.name"));
    INSTANCE = this;

    service = new DesignerService();

    setJMenuBar(BarFactory.createMenubar(manager, service.getVerb()));
    splash.setProgress(30);
    navigator = new WorkspaceNavigator(this);
    JScrollPane sp = new JScrollPane(detailPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
    detailFramePanel = new FramePanel(ResourceManager.getString("details"), false);
    detailFramePanel.setContent(sp);

    splash.setProgress(40);
    loadPalette();
    splash.setProgress(50);

    // create workspace view
    FramePanel flowsPanel = new FramePanel(ResourceManager.getString("workspace"), false);
    flowsPanel.setContent(new JScrollPane(navigator));

    // layout
    leftSplitPane = new EmptyBorderSplitPane(JSplitPane.VERTICAL_SPLIT, flowsPanel, detailFramePanel);
    mainSplitPane = new EmptyBorderSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftSplitPane, graphTabs);
    graphTabs.setVisible(false);

    splash.setProgress(60);
    //Provide a preferred size for the split pane
    String bounds = Prefs.INSTANCE.get(Prefs.DESIGNER_BOUNDS, "100, 100, 800, 600");
    StringTokenizer tok = new StringTokenizer(bounds, ",");
    int x = Integer.parseInt(tok.nextToken().trim());
    int y = Integer.parseInt(tok.nextToken().trim());
    int w = Integer.parseInt(tok.nextToken().trim());
    int h = Integer.parseInt(tok.nextToken().trim());
    setLocation(x, y);
    getContentPane().setLayout(new BorderLayout());
    getContentPane().add(BarFactory.createToolbar(), BorderLayout.NORTH);
    splash.setProgress(65);
    getContentPane().add(mainSplitPane, BorderLayout.CENTER);
    statusBar = BarFactory.createStatusBar();
    getContentPane().add(statusBar, BorderLayout.SOUTH);

    splash.setProgress(70);
    mainSplitPane.setPreferredSize(new Dimension(w, h));

    addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent evt)
      {
        quit();
      }
    });
    if("new".equals(service.getVerb()))
    {
      newRemoteWorkspace();
    }
    else if("modify".equals(service.getVerb()))
    {
      newRemoteWorkspace();
      openRemoteWorkspace();
    }
    else
    {
      String lastOpened = Prefs.INSTANCE.get(Prefs.LAST_WORKSPACE, null);
      if(lastOpened != null)
      {
        try
        {
          if(lastOpened.indexOf(":/") == -1)
          {
            openWorkspace(new File(lastOpened).toURL());
          }
          else
          {
            openWorkspace(new URL(lastOpened));
          }
        }
        catch(MalformedURLException e)
        {
          e.printStackTrace();
        }
        String workflow = Prefs.INSTANCE.get(Prefs.WORKFLOW_CURRENT, null);
        if(workflow != null)
        {
          navigator.selectWorkflow(workflow);
        }
      }
    }
    mainSplitPane.setDividerLocation(Prefs.INSTANCE.getInt(Prefs.MAIN_DIVIDER_LOCATION, 150));
    leftSplitPane.setDividerLocation(Prefs.INSTANCE.getInt(Prefs.DETAIL_DIVIDER_LOCATION, 50));
  }

  public void graphChanged(GraphModelEvent e)
  {
    if(detailPanel.getVisibleCard() == null)
    {
      return;
    }

    AbstractDescriptor desc = ((DetailPanel)detailPanel.getVisibleCard()).getDescriptor();
    showDetails(desc);
    //DefaultGraphCell  relationsCell = relationshipsNavigator.getCell();

    //Object[] cells = e.getChange().getChanged();
    //System.out.println("changed = " + java.util.Arrays.asList(cells));
    //for(int i = 0; i < cells.length; i++)
    //{
    //  if(cells[i] instanceof WorkflowCell)
    //  {
    //    if(cells[i] == detailCell)
    //    {
    //      showDetails(desc);
    //    }
    //  }
    //  else if(cells[i] instanceof WorkflowEdge)
    //  {
    //    if(cells[i] == detailEdge)
    //    {
    //      showDetails(desc);
    //    }
    //  }
    //  if(cells[i] instanceof DefaultGraphCell)
    //  {
    //    //showRelationships(relationsCell);
    //  }
    //}
  }

  public WorkflowGraph getCurrentGraph()
  {
    return graphTabs.getCurrentGraph();
  }

  /**
   * Delete a workflow from config
   */ 
  public void deleteWorkflow(String workflowName) throws FactoryException
  {
    graphTabs.removeGraph(workflowName);
    navigator.removeWorkflow(workflowName);
    manager.getCurrentWorkspace().removeWorkflow(workflowName);
  }

  /**
   * Delete a workflow from config
   */
  public void closeWorkflow(String workflowName) throws FactoryException
  {
    graphTabs.removeGraph(workflowName);
    navigator.removeWorkflow(workflowName);
    manager.getCurrentWorkspace().removeWorkflow(workflowName);
  }

  public void validateCurrentWorkflow()
  {
    WorkflowGraph graph = graphTabs.getCurrentGraph();
    if(graph != null)
    {
      validateWorkflow(graph.getName());
    }
  }

  public void validateSaveCurrentWorkflow()
  {
    WorkflowGraph graph = graphTabs.getCurrentGraph();
    if(graph != null)
    {
      save(graph, true);
    }
  }

  public void validateWorkflow(String workflowName)
  {
    WorkflowGraph graph = graphTabs.getGraph(workflowName);
    if(graph != null)
    {
      workflowName = graph.getName();
      WorkflowDescriptor d = graph.getDescriptor();
      if(d != null)
      {
        try
        {
          d.validate();
        }
        catch(InvalidWorkflowDescriptorException e)
        {
          System.out.println("Error validating workflow: " + e);
          JOptionPane.showMessageDialog(this,
                                        ResourceManager.getString("error.validate.workflow", new Object[]{e.getMessage()}),
                                        ResourceManager.getString("title.validate.workflow", new Object[]{workflowName}),
                                        JOptionPane.ERROR_MESSAGE);
          return;
        }

        JOptionPane.showMessageDialog(this,
                                      ResourceManager.getString("success.validate.workflow"),
                                      ResourceManager.getString("title.validate.workflow", new Object[]{workflowName}),
                                      JOptionPane.INFORMATION_MESSAGE);
      }
    }
  }

  public void closeCurrentWorkflow()
  {
    WorkflowGraph graph = graphTabs.getCurrentGraph();
    if(graph != null)
    {
      graphTabs.removeGraph(graph);
    }
    //graphTabs.removeGraph(graphTabs.getCurrentGraph());
  }

  public void createGraph(String workflowName)
  {
    //Workspace currentWorkspace = manager.getCurrentWorkspace();
    WorkflowFactory currentWorkspace = manager.getCurrentWorkspace();
    Layout layout = (Layout)currentWorkspace.getLayout(workflowName);
    WorkflowGraphModel model = new WorkflowGraphModel(layout);
    model.setPalette(palette);
    model.addGraphModelListener(this);
    boolean hasLayout = layout != null;
    if(layout == null) layout = new Layout();
    WorkflowDescriptor descriptor;
    try
    {
      descriptor = currentWorkspace.getWorkflow(workflowName, false);
    }
    catch(FactoryException e)
    {
      e.printStackTrace();
      return;
    }
    WorkflowGraph graph = new WorkflowGraph(model, descriptor, layout, !hasLayout);
    graph.addGraphSelectionListener(this);
    //graph.setName(workflowName);
    if(descriptor != null)
      graph.setName(descriptor.getName());
    else
      graph.setName(workflowName);
    graphTabs.addGraph(graph);
    graphTabs.setVisible(true);
  }

  public void quit()
  {
    Point location = getLocation();
    Prefs.INSTANCE.putInt(Prefs.MAIN_DIVIDER_LOCATION, mainSplitPane.getDividerLocation());
    Prefs.INSTANCE.putInt(Prefs.DETAIL_DIVIDER_LOCATION, leftSplitPane.getDividerLocation());
    Prefs.INSTANCE.put(Prefs.DESIGNER_BOUNDS, location.x + "," + location.y + ',' + mainSplitPane.getWidth() + ',' + mainSplitPane.getHeight());
    try
    {
      Prefs.INSTANCE.flush();
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
    System.exit(0);
  }

  public void renameWorkflow(String oldName, String newName)
  {
    graphTabs.renameGraph(oldName, newName);
    manager.getCurrentWorkspace().renameWorkflow(oldName, newName);
  }

  public void valueChanged(GraphSelectionEvent e)
  {
    Object lastAdded = null;
    for(int i = e.getCells().length - 1; i >= 0; i--)
    {
      if(e.isAddedCell(i))
      {
        lastAdded = e.getCells()[i];
        break;
      }
    }
    if(lastAdded instanceof WorkflowCell || lastAdded instanceof WorkflowEdge)
    {
      AbstractDescriptor desc = getCellDescriptor(lastAdded);
      showDetails(desc);
      navigator.selectTreeNode(graphTabs.getCurrentGraph().getDescriptor(), desc);
    }
  }

  public void showSelectedCellDetails()
  {
    WorkflowGraph graph = graphTabs.getCurrentGraph();
    if(graph != null)
    {
      Object cell = graph.getSelectionModel().getSelectionCell();
      if(cell != null)
      {
        if(cell instanceof WorkflowCell || cell instanceof WorkflowEdge)
        {
          AbstractDescriptor desc = getCellDescriptor(cell);
          showDetails(desc);
          navigator.selectTreeNode(graphTabs.getCurrentGraph().getDescriptor(), desc);
        }
      }
    }
  }

  public void refreshUI()
  {
    if(currentDetailObject != null)
    {
      showDetails(currentDetailObject);
    }
  }

  public void showDetails(Object node)
  {
    if(node == null) return;
    String title = getDescriptorTitle(node);
    AbstractDescriptor descriptor = null;
    currentDetailObject = node;
    String panelName = node.getClass().getName();
    DetailPanel current = (DetailPanel)detailPanel.getVisibleCard();
    if(current != null)
      current.closeView();
    DetailPanel panel = (DetailPanel)detailPanel.showCard(panelName);
    if(panel == null)
    {
      if(node instanceof StepDescriptor)
      {
        panel = new StepEditor();
      }
      else if(node instanceof SplitDescriptor)
      {
        panel = new SplitEditor();
      }
      else if(node instanceof JoinDescriptor)
      {
        panel = new JoinEditor();
      }
      else if(node instanceof ResultDescriptor)
      {
        panel = new ResultEditor();
      }
      else if(node instanceof ActionDescriptor)
      {
        panel = new ActionEditor();
      }
      else if(node instanceof WorkflowDescriptor)
      {
        panel = new WorkflowEditor();
      }
      else if(node instanceof String)
      {
        panel = new GenericEditor();
      }
    }

    if(panel != null)
    {
      if(node instanceof String)
      {
        ((GenericEditor)panel).setLabel((String)node);
        panel.setName(panelName);
        detailFramePanel.setTitle(ResourceManager.getString("details") + (title != null ? (" - " + title) : ""));
        detailPanel.showCard(panel);
        return;
      }
      descriptor = (AbstractDescriptor)node;
    }

    if(panel != null)
    {
      WorkflowGraph currentGraph = graphTabs.getCurrentGraph();
      if(currentGraph == null) return;
      panel.setModel(currentGraph.getWorkflowGraphModel());
      panel.setGraph(currentGraph);
      panel.setDescriptor(descriptor);

      detailFramePanel.setTitle(ResourceManager.getString("details") + (title != null ? (" - " + title) : ""));
      detailPanel.showCard(panel);
    }
    else
    {
      System.out.println("WARN: no detail panel for " + node.getClass());
    }
  }

  public void openWorkspace(URL file)
  {
    if(file != null)
    {
      String oldWorkspace = Prefs.INSTANCE.get(Prefs.LAST_WORKSPACE, null);
      try
      {
        graphTabs.removeAll();
        Prefs.INSTANCE.put(Prefs.LAST_WORKSPACE, file.toString());
        manager.loadWorkspace(file);
        WorkflowFactory workspace = manager.getCurrentWorkspace();
        navigator.setWorkspace(workspace);
        String[] workflows = workspace.getWorkflowNames();
        for(int i = 0; i < workflows.length; i++)
        {
          createGraph(workflows[i]);
        }
        Prefs.INSTANCE.put(Prefs.LAST_WORKSPACE, file.toString());
      }
      catch(Exception t)
      {
        if(!file.toString().equals(oldWorkspace))
          Prefs.INSTANCE.put(Prefs.LAST_WORKSPACE, oldWorkspace);
        else
          Prefs.INSTANCE.remove(Prefs.LAST_WORKSPACE);
        t.printStackTrace();
      }
    }
  }

  public void openRemoteWorkspace()
  {
    try
    {
      manager.loadServiceWorkspace(service);
      RemoteWorkspace workspace = (RemoteWorkspace)manager.getCurrentWorkspace();
      navigator.setWorkspace(workspace);
      String[] workflows = workspace.getWorkflowNames();
      for(int i = 0; i < workflows.length; i++)
      {
        createGraph(workflows[i]);
      }
    }
    catch(Exception t)
    {
      t.printStackTrace();
    }
  }

  public void checkWorkspaceExists()
  {
    if(manager.getCurrentWorkspace() == null)
    {
      NewWorkspaceDialog newSpace = new NewWorkspaceDialog(this, ResourceManager.getString("workspace.new"), true);
      newSpace.pack();
      newSpace.getBanner().setTitle("");
      newSpace.getBanner().setSubtitle(ResourceManager.getString("workspace.new.long"));
      Utils.centerComponent(this, newSpace);
      Dimension size = newSpace.getSize();
      newSpace.setSize(size.width + 10, size.height + 15);
      newSpace.setVisible(true);
    }
  }

  private boolean save(WorkflowGraph graph, boolean validate)
  {
    boolean saved = false;

    Layout layout = graph.getGraphLayout();
    WorkflowGraphModel model = (WorkflowGraphModel)graph.getModel();
    layout.setAllEntries(model.getActivitiesList());
    String workflowName = graph.getName();
    manager.getCurrentWorkspace().setLayout(workflowName, layout);
    WorkflowDescriptor descriptor = null;
    try
    {
      descriptor = manager.getCurrentWorkspace().getWorkflow(workflowName);
      if(validate)
      {
        descriptor.validate();
      }
      if(manager.getCurrentWorkspace() instanceof Workspace)
        saved = ((Workspace)manager.getCurrentWorkspace()).saveWorkflow(workflowName, descriptor, graph, true);
      else if(manager.getCurrentWorkspace() instanceof RemoteWorkspace)
        saved = ((RemoteWorkspace)manager.getCurrentWorkspace()).saveWorkflow(workflowName, descriptor, graph, true);
      if(!saved)
      {
        JOptionPane.showMessageDialog(this, "Error", ResourceManager.getString("error.save.workflow.long", new Object[]{workflowName}), JOptionPane.ERROR_MESSAGE);
      }
    }
    catch(InvalidWorkflowDescriptorException e)
    {
      System.out.println("Error saving workflow: " + e);
      PrintWriter out = new PrintWriter(System.out);
      descriptor.writeXML(out, 0);
      out.flush();
      JOptionPane.showMessageDialog(this,
                                    ResourceManager.getString("error.validate.workflow", new Object[]{e.getMessage()}),
                                    ResourceManager.getString("title.validate.workflow", new Object[]{workflowName}),
                                    JOptionPane.ERROR_MESSAGE);
    }
    catch(Exception e)
    {
      e.printStackTrace();
      JOptionPane.showMessageDialog(this, e.getMessage(), ResourceManager.getString("error.save.workflow.long", new Object[]{workflowName}), JOptionPane.ERROR_MESSAGE);
    }
    return saved;
  }

  public void saveOpenGraphs()
  {
    WorkflowGraph[] graphs = graphTabs.getGraphs();
    for(int i = 0; i < graphs.length; i++)
    {
      save(graphs[i], false);
    }
  }

  public void saveWorkspace()
  {
    manager.saveWorkspace();
  }

  public Workspace newLocalWorkspace()
  {
    closeWorkspace();
    Workspace workspace = new Workspace();
    manager.setCurrentWorkspace(workspace);
    navigator.setWorkspace(workspace);
    return workspace;
  }

  public RemoteWorkspace newRemoteWorkspace()
  {
    closeWorkspace();
    RemoteWorkspace workspace = new RemoteWorkspace(service);
    manager.setCurrentWorkspace(workspace);
    navigator.setWorkspace(workspace);
    return workspace;
  }

  public void closeWorkspace()
  {
    //don't bother doing anything if we have no workspace visible
    if(!graphTabs.isVisible()) return;
    graphTabs.removeAll();
    manager.setCurrentWorkspace(null);
    navigator.setWorkspace(null);
    Prefs.INSTANCE.remove(Prefs.LAST_WORKSPACE);
    graphTabs.setVisible(false);
  }

  public void newWorkflowCreated(String name)
  {
    navigator.addWorkflow(name);
    navigator.selectWorkflow(name);
  }

  public WorkspaceNavigator navigator()
  {
    return navigator;
  }

  public void selectWorkflow(String workflowName)
  {
    if(graphTabs.selectWorkflow(workflowName))
    {
      Prefs.INSTANCE.put(Prefs.WORKFLOW_CURRENT, workflowName);
      return;
    }
    createGraph(workflowName);
    Prefs.INSTANCE.put(Prefs.WORKFLOW_CURRENT, workflowName);
    graphTabs.setVisible(true);
  }

  public void selectCell(AbstractDescriptor descriptor)
  {
    WorkflowGraph graph = getCurrentGraph();
    graph.getSelectionModel().clearSelection();
    WorkflowGraphModel model = (WorkflowGraphModel)graph.getModel();
    if(descriptor instanceof StepDescriptor)
    {
      StepCell cell = model.getStepCell(descriptor.getId());
      if(cell != null)
      {
        graph.getSelectionModel().setSelectionCell(cell);
      }
    }
    else if(descriptor instanceof SplitDescriptor)
    {
      SplitCell cell = model.getSplitCell(descriptor.getId());
      if(cell != null)
      {
        graph.getSelectionModel().setSelectionCell(cell);
      }
    }
    else if(descriptor instanceof JoinDescriptor)
    {
      JoinCell cell = model.getJoinCell(descriptor.getId());
      if(cell != null)
      {
        graph.getSelectionModel().setSelectionCell(cell);
      }
    }
    else if(descriptor instanceof ResultDescriptor)
    {
      ResultEdge edge = model.getResultCell((ResultDescriptor)descriptor);
      if(edge != null)
      {
        graph.getSelectionModel().setSelectionCell(edge);
      }
    }
  }

  private void loadPalette()
  {
    try
    {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      dbf.setNamespaceAware(true);

      DocumentBuilder db = null;

      try
      {
        db = dbf.newDocumentBuilder();
      }
      catch(ParserConfigurationException e)
      {
        e.printStackTrace();
        System.exit(1);
      }

      InputStream is = WorkflowDesigner.class.getResourceAsStream("/META-INF/palette.xml");
      Document doc = db.parse(is);
      ResourceBundle bundle = ResourceBundle.getBundle("META-INF/palette", Locale.getDefault(), getClass().getClassLoader());
      Element root = (Element)doc.getElementsByTagName("plugin").item(0);

      palette = new PaletteDescriptor(root, new EnhancedResourceBundle(bundle));
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  private AbstractDescriptor getCellDescriptor(Object cell)
  {
    if(cell instanceof StepCell)
    {
      return ((StepCell)cell).getDescriptor();
    }
    else if(cell instanceof JoinCell)
    {
      return ((JoinCell)cell).getJoinDescriptor();
    }
    else if(cell instanceof SplitCell)
    {
      return ((SplitCell)cell).getSplitDescriptor();
    }
    else if(cell instanceof InitialActionCell)
    {
      return ((InitialActionCell)cell).getActionDescriptor();
    }
    else if(cell instanceof ResultEdge)
    {
      return ((ResultEdge)cell).getDescriptor();
    }
    return null;
  }

  private String getDescriptorTitle(Object desc)
  {
    String title = "";
    if(desc instanceof StepDescriptor)
    {
      title = ((StepDescriptor)desc).getName();
    }
    else if(desc instanceof SplitDescriptor)
    {
      title = "Split #" + ((SplitDescriptor)desc).getId();
    }
    else if(desc instanceof JoinDescriptor)
    {
      title = "Join #" + ((JoinDescriptor)desc).getId();
    }
    else if(desc instanceof ResultDescriptor)
    {
      title = ((ResultDescriptor)desc).getDisplayName();
    }
    else if(desc instanceof ActionDescriptor)
    {
      title = ((ActionDescriptor)desc).getName();
    }
    else if(desc instanceof WorkflowDescriptor)
    {
      title = ((WorkflowDescriptor)desc).getName();
    }
    return title;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.