private static PDEFormEditor getOpenEditor(ModelModification modification) {
   IProject project = modification.getFile().getProject();
   String name = modification.getFile().getName();
   if (name.equals(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR)
       || name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)
       || name.equals(ICoreConstants.MANIFEST_FILENAME)) {
     return getOpenManifestEditor(project);
   } else if (name.equals(ICoreConstants.BUILD_FILENAME_DESCRIPTOR)) {
     PDEFormEditor openEditor = getOpenBuildPropertiesEditor(project);
     if (openEditor == null) openEditor = getOpenManifestEditor(project);
     return openEditor;
   }
   return null;
 }
 private static IBaseModel getModelFromEditor(
     PDEFormEditor openEditor, ModelModification modification) {
   if (openEditor == null) return null;
   String name = modification.getFile().getName();
   IBaseModel model = null;
   if (name.equals(ICoreConstants.PLUGIN_FILENAME_DESCRIPTOR)
       || name.equals(ICoreConstants.FRAGMENT_FILENAME_DESCRIPTOR)) {
     model = openEditor.getAggregateModel();
     if (model instanceof IBundlePluginModelBase)
       model = ((IBundlePluginModelBase) model).getExtensionsModel();
   } else if (name.equals(ICoreConstants.BUILD_FILENAME_DESCRIPTOR)) {
     if (openEditor instanceof BuildEditor) {
       model = openEditor.getAggregateModel();
     } else if (openEditor instanceof ManifestEditor) {
       IFormPage page = openEditor.findPage(BuildInputContext.CONTEXT_ID);
       if (page instanceof BuildSourcePage)
         model = ((BuildSourcePage) page).getInputContext().getModel();
     }
   } else if (name.equals(ICoreConstants.MANIFEST_FILENAME)) {
     model = openEditor.getAggregateModel();
     if (model instanceof IBundlePluginModelBase) return model;
   }
   if (model instanceof AbstractEditingModel) return model;
   return null;
 }
  /**
   * Modify a model based on the specifications provided by the ModelModification parameter.
   *
   * <p>A model will be searched for in the open editors, if it is found changes will be applied and
   * the editor will be saved. If no model is found one will be created and text edit operations
   * will be generated / applied.
   *
   * <p>NOTE: If a MANIFEST.MF file is specified in the ModelModification a BundlePluginModel will
   * be searched for / created and passed to ModelModification#modifyModel(IBaseModel). (not a
   * BundleModel - which can be retreived from the BundlePluginModel)
   *
   * @param modification
   * @param monitor
   * @throws CoreException
   */
  public static void modifyModel(
      final ModelModification modification, final IProgressMonitor monitor) {
    // ModelModification was not supplied with the right files
    // TODO should we just fail silently?
    if (modification.getFile() == null) return;

    PDEFormEditor editor = getOpenEditor(modification);
    IBaseModel model = getModelFromEditor(editor, modification);

    if (model != null) {
      // open editor found, should have underlying text listeners -> apply modification
      modifyEditorModel(modification, editor, model, monitor);
    } else {
      generateModelEdits(modification, monitor, true);
    }
  }
  private static TextFileChange[] generateModelEdits(
      final ModelModification modification, final IProgressMonitor monitor, boolean performEdits) {
    ArrayList edits = new ArrayList();
    // create own model, attach listeners and grab text edits
    ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
    IFile[] files;
    if (modification.isFullBundleModification()) {
      files = new IFile[2];
      files[F_Bi] = modification.getManifestFile();
      files[F_Xi] = modification.getXMLFile();
    } else {
      files = new IFile[] {modification.getFile()};
    }
    // need to monitor number of successful buffer connections for disconnection purposes
    // @see } finally { statement
    int sc = 0;
    try {
      ITextFileBuffer[] buffers = new ITextFileBuffer[files.length];
      IDocument[] documents = new IDocument[files.length];
      for (int i = 0; i < files.length; i++) {
        if (files[i] == null || !files[i].exists()) continue;
        manager.connect(files[i].getFullPath(), LocationKind.NORMALIZE, monitor);
        sc++;
        buffers[i] = manager.getTextFileBuffer(files[i].getFullPath(), LocationKind.NORMALIZE);
        if (performEdits && buffers[i].isDirty()) buffers[i].commit(monitor, true);
        documents[i] = buffers[i].getDocument();
      }

      IBaseModel editModel;
      if (modification.isFullBundleModification())
        editModel = prepareBundlePluginModel(files, documents, !performEdits);
      else editModel = prepareAbstractEditingModel(files[0], documents[0], !performEdits);

      modification.modifyModel(editModel, monitor);

      IModelTextChangeListener[] listeners = gatherListeners(editModel);
      for (int i = 0; i < listeners.length; i++) {
        if (listeners[i] == null) continue;
        TextEdit[] currentEdits = listeners[i].getTextOperations();
        if (currentEdits.length > 0) {
          MultiTextEdit multi = new MultiTextEdit();
          multi.addChildren(currentEdits);
          if (performEdits) {
            multi.apply(documents[i]);
            buffers[i].commit(monitor, true);
          }
          TextFileChange change = new TextFileChange(files[i].getName(), files[i]);
          change.setEdit(multi);
          // If the edits were performed right away (performEdits == true) then
          // all the names are null and we don't need the granular detail anyway.
          if (!performEdits) {
            for (int j = 0; j < currentEdits.length; j++) {
              String name = listeners[i].getReadableName(currentEdits[j]);
              if (name != null) change.addTextEditGroup(new TextEditGroup(name, currentEdits[j]));
            }
          }
          // save the file after the change applied
          change.setSaveMode(TextFileChange.FORCE_SAVE);
          setChangeTextType(change, files[i]);
          edits.add(change);
        }
      }
    } catch (CoreException e) {
      PDEPlugin.log(e);
    } catch (MalformedTreeException e) {
      PDEPlugin.log(e);
    } catch (BadLocationException e) {
      PDEPlugin.log(e);
    } finally {
      // don't want to over-disconnect in case we ran into an exception during connections
      // dc <= sc stops this from happening
      int dc = 0;
      for (int i = 0; i < files.length && dc <= sc; i++) {
        if (files[i] == null || !files[i].exists()) continue;
        try {
          manager.disconnect(files[i].getFullPath(), LocationKind.NORMALIZE, monitor);
          dc++;
        } catch (CoreException e) {
          PDEPlugin.log(e);
        }
      }
    }
    return (TextFileChange[]) edits.toArray(new TextFileChange[edits.size()]);
  }