/** {@inheritDoc} */
  public void doSave(IProgressMonitor monitor) {
    monitor.beginTask(Messages.EditorsSaveEditors, IProgressMonitor.UNKNOWN);
    try {
      EditSupport editSupport = getEditorHelper().getEditSupport();
      final IPersistentObject perObj = editSupport.getWorkVersion();
      TimestampBP.refreshTimestamp((ITimestampPO) perObj);
      editSupport.saveWorkVersion();

      getEditorHelper().resetEditableState();
      getEditorHelper().setDirty(false);
    } catch (IncompatibleTypeException pmce) {
      handlePMCompNameException(pmce);
    } catch (PMException e) {
      PMExceptionHandler.handlePMExceptionForMasterSession(e);
      try {
        reOpenEditor(((NodeEditorInput) getEditorInput()).getNode());
      } catch (PMException e1) {
        PMExceptionHandler.handlePMExceptionForEditor(e, this);
      }
    } catch (ProjectDeletedException e) {
      PMExceptionHandler.handleProjectDeletedException();
    } finally {
      monitor.done();
    }
  }
  /**
   * Deletes all selected items unless an error occurs.
   *
   * @param selection The selected items to delete.
   */
  private void deleteSelection(IStructuredSelection selection) {
    // cleanup set for entries, that are children of other contained nodes
    Set<INodePO> set = new HashSet<INodePO>(selection.toList());
    Set<INodePO> topNodesToDelete = new HashSet<INodePO>();
    for (INodePO node : set) {
      if (!containsParent(set, node)) {
        topNodesToDelete.add(node);
      }
    }

    // determine all nodes, which have to be deleted
    // (children of selected nodes which are CategoryPO or SpecTestCasePO
    List<INodePO> nodesToDelete = new ArrayList<INodePO>();
    for (INodePO node : topNodesToDelete) {
      MultipleNodePM.collectAffectedNodes(nodesToDelete, node);
    }

    // reverse List, to get the right order of deletion (child first)
    Collections.reverse(nodesToDelete);

    List<AbstractCmdHandle> cmds = getDeleteCommands(nodesToDelete);
    if (!cmds.isEmpty()) {
      try {
        MultipleNodePM.getInstance().executeCommands(cmds);

        List<DataChangedEvent> eventList = new ArrayList<DataChangedEvent>();
        for (INodePO node : topNodesToDelete) {
          eventList.add(new DataChangedEvent(node, DataState.Deleted, UpdateState.all));
        }
        DataEventDispatcher.getInstance()
            .fireDataChangedListener(eventList.toArray(new DataChangedEvent[0]));
      } catch (PMException e) {
        PMExceptionHandler.handlePMExceptionForMasterSession(e);
      } catch (ProjectDeletedException e) {
        PMExceptionHandler.handleProjectDeletedException();
      }
    }
  }
  /**
   * Creates a new project, stops a started AUT, closes all opened editors.
   *
   * @param newProjectName the name for this project
   * @param monitor The progress monitor for this potentially long-running operation.
   * @throws InterruptedException if the operation is canceled.
   */
  private void createNewProject(final String newProjectName, IProgressMonitor monitor)
      throws InterruptedException {

    Plugin.closeAllOpenedJubulaEditors(false);
    m_newProject.setIsReusable(m_projectSettingWizardPage.isProjectReusable());
    m_newProject.setIsProtected(m_projectSettingWizardPage.isProjectProtected());
    if (m_autMain.getName() == null || StringConstants.EMPTY.equals(m_autMain.getName())) {
      m_newProject.removeAUTMain(m_autMain);
    }
    if (m_autConfig.getName() == null || StringConstants.EMPTY.equals(m_autConfig.getName())) {

      m_autMain.removeAutConfig(m_autConfig);
    }
    ParamNameBPDecorator paramNameMapper = new ParamNameBPDecorator(ParamNameBP.getInstance());
    final IWritableComponentNameMapper compNamesMapper =
        new ProjectComponentNameMapper(new ComponentNamesDecorator(null), m_newProject);
    List<INameMapper> mapperList = new ArrayList<INameMapper>();
    List<IWritableComponentNameMapper> compNameCacheList =
        new ArrayList<IWritableComponentNameMapper>();
    addUnboundModules(m_newProject);
    mapperList.add(paramNameMapper);
    compNameCacheList.add(compNamesMapper);
    try {
      GeneralStorage.getInstance().reset();
      ProjectPM.attachProjectToROSession(
          m_newProject, newProjectName, mapperList, compNameCacheList, monitor);
    } catch (PMSaveException e) {
      PMExceptionHandler.handlePMExceptionForMasterSession(
          new PMSaveException(e.getMessage(), MessageIDs.E_CREATE_NEW_PROJECT_FAILED));
    } catch (PMException e) {
      PMExceptionHandler.handlePMExceptionForMasterSession(e);
    } catch (ProjectDeletedException e) {
      PMExceptionHandler.handleProjectDeletedException();
    } catch (InterruptedException ie) {
      throw ie;
    }
  }
  /** {@inheritDoc} */
  public boolean performOk() {
    try {
      if (!m_oldProjectName.equals(m_newProjectName)) {
        if (ProjectPM.doesProjectNameExist(m_newProjectName)) {

          ErrorHandlingUtil.createMessageDialog(
              MessageIDs.E_PROJECTNAME_ALREADY_EXISTS, new Object[] {m_newProjectName}, null);
          return false;
        }
      }
      if (m_isReusableCheckbox != null) {
        getProject().setIsReusable(m_isReusableCheckbox.getSelection());
      }
      if (m_isProtectedCheckbox != null) {
        getProject().setIsProtected(m_isProtectedCheckbox.getSelection());
      }
      storeAutoTestResultCleanup();

      if (!m_oldProjectName.equals(m_newProjectName)) {
        ProjectNameBP.getInstance()
            .setName(getEditSupport().getSession(), getProject().getGuid(), m_newProjectName);
      }
      fireOkPressed();
      Set<IReusedProjectPO> origReused =
          ((IProjectPropertiesPO) getEditSupport().getOriginal()).getUsedProjects();
      Set<IReusedProjectPO> newReused =
          new HashSet<IReusedProjectPO>(
              ((IProjectPropertiesPO) getEditSupport().getWorkVersion()).getUsedProjects());
      newReused.removeAll(origReused);
      getEditSupport().saveWorkVersion();
      refreshAutMainList();
      DataEventDispatcher.getInstance().fireProjectStateChanged(ProjectState.prop_modified);
      for (IReusedProjectPO reused : newReused) {
        try {
          IProjectPO reusedProject = ProjectPM.loadReusedProject(reused);
          if (reusedProject != null) {
            // incomplete database, see https://bxapps.bredex.de/bugzilla/show_bug.cgi?id=854
            ComponentNamesBP.getInstance().refreshNames(reusedProject.getId());
          }
        } catch (JBException e) {
          // Could not refresh Component Name information for
          // reused project. Log the exception.
          log.error(Messages.ErrorWhileRetrievingReusedProjectInformation, e);
        }
      }
      // FIXME zeb This updates the Test Case Browser. Once we have separate
      //           EditSupports for each property page, then we can use
      //           "real" ReusedProjectPOs instead of a placeholder.
      DataEventDispatcher.getInstance()
          .fireDataChangedListener(
              PoMaker.createReusedProjectPO("1", 1, 1), // $NON-NLS-1$
              DataState.ReuseChanged,
              UpdateState.notInEditor);
      DataEventDispatcher.getInstance()
          .fireDataChangedListener(
              GeneralStorage.getInstance().getProject(),
              DataState.Renamed,
              UpdateState.notInEditor);
      CompletenessBP.getInstance().completeProjectCheck();
    } catch (PMException e) {
      ErrorHandlingUtil.createMessageDialog(e, null, null);
    } catch (ProjectDeletedException e) {
      PMExceptionHandler.handleProjectDeletedException();
    } catch (IncompatibleTypeException ite) {
      ErrorHandlingUtil.createMessageDialog(ite, ite.getErrorMessageParams(), null);
    }

    return true;
  }