net.rim.ejde.internal.ui.editors.locale.ResourceEditor.java Source code

Java tutorial

Introduction

Here is the source code for net.rim.ejde.internal.ui.editors.locale.ResourceEditor.java

Source

/*
* Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License, Version 1.0,
* which accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package net.rim.ejde.internal.ui.editors.locale;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Vector;

import net.rim.ejde.internal.core.ContextManager;
import net.rim.ejde.internal.util.ImportUtils;
import net.rim.ejde.internal.util.Messages;
import net.rim.ejde.internal.util.PackageUtils;
import net.rim.sdk.resourceutil.RIMResourceLocale;
import net.rim.sdk.resourceutil.ResourceCollection;
import net.rim.sdk.resourceutil.ResourceCollectionFactory;
import net.rim.sdk.resourceutil.ResourceCollectionListener;
import net.rim.sdk.resourceutil.ResourceConstants;
import net.rim.sdk.resourceutil.ResourceElement;
import net.rim.sdk.resourceutil.ResourceLocale;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceDescription;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;

/**
 * The multipage editor for blackberry resources
 *
 * @author jkeshavarzi
 *
 */
public class ResourceEditor extends MultiPageEditorPart {
    // vector to keep track of the open pages
    private Vector<ResourceEditorPage> _pages;

    // this variable keeps track of the resourceCollection. It is used to get locales of the file.
    private ResourceCollection _resources;

    private boolean _wasDirty;
    private ResourceEditorListener _resourceEditorListener;
    private static final String ROOT = "Root";

    // this variable keeps track if resourceChangeListener has already been added to the workspace. This variable was introduced
    // as a fix to SDR185428 to load pages dynamically in the resource Editor.
    private static boolean resourceChangeListenerAdded = false;

    private static final Logger _logger = Logger.getLogger(ResourceEditor.class);

    // array of references to open editors in this WorkbenchPage
    private static IEditorReference[] _openEditorReferences = null;

    // filename of .rrh/.rrc file that was opened (i.e. double-clicked) by user
    private String _resourceFilename;

    // The resource header file for the resource collection
    private File rrhFile;

    // The package of the resource when it was opened in the resource editor
    private String _originalPackage = null;

    // vector of resource IFiles to be potentially checked out (i.e. opened for edit in Perforce). all IFiles in this vector
    // correspond to all resource files from all resource bundles opened by user
    private static Vector<IFile> _checkoutFiles = new Vector<IFile>(0);

    // vector of ResourceEditorPage objects (used by ResourceEditorOptionsDialog class to activate versioning highlighting)
    private static Vector<ResourceEditorPage> _resourceEditorPages = new Vector<ResourceEditorPage>(0);

    private boolean _callByResourceListener = false;

    // return EditorReferences from all the pages in eclipse
    public IEditorReference[] getOpenEditorReferences() {
        Vector<IEditorReference> openEditorReferences = new Vector<IEditorReference>(0);
        IWorkbenchPage[] workbenchPage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getPages();
        int workbenchPageCount = workbenchPage.length;

        for (int i = 0; i < workbenchPageCount; i++) {
            Collection<IEditorReference> editorReferences = Arrays.asList(workbenchPage[i].getEditorReferences());
            openEditorReferences.addAll(editorReferences);
        }

        return openEditorReferences.toArray(new IEditorReference[1]);
    }

    private File getRRCFile(File s) {
        String[] splitFiles = s.getName().split("\\.");
        String extension = "";
        if (splitFiles[1].toLowerCase().equals("rrh")) {
            extension = ".rrc";
        } else {
            extension = ".rrh";
        }
        return new File((s.getPath().substring(0, s.getPath().lastIndexOf(File.separator)) + File.separator
                + splitFiles[0] + extension));
    }

    private class ResourceEditorListener implements IPartListener {
        private boolean _allowOpen = true;
        private boolean _openTextEditor = false;
        private IEditorSite _site;
        private IEditorInput _input;

        public ResourceEditorListener(IEditorSite site, IEditorInput input) {
            this._site = site;
            this._input = input;
        }

        public void setAllowOpen(boolean allowOpen) {
            this._allowOpen = allowOpen;
        }

        public void setOpenTextEditor(boolean openTextEditor) {
            this._openTextEditor = openTextEditor;
        }

        public void partActivated(IWorkbenchPart part) {
        }

        public void partBroughtToTop(IWorkbenchPart part) {
        }

        public void partClosed(IWorkbenchPart part) {
        }

        public void partDeactivated(IWorkbenchPart part) {
        }

        public void partOpened(IWorkbenchPart part) {
            if (!(part instanceof ResourceEditor)) {
                return;
            }
            if (!_allowOpen) {
                part.getSite().getWorkbenchWindow().getActivePage().closeEditor((IEditorPart) part, false);
                if (_openTextEditor) {
                    try {
                        IDE.openEditor(_site.getWorkbenchWindow().getActivePage(), _input,
                                EditorsUI.DEFAULT_TEXT_EDITOR_ID);
                    } catch (PartInitException e) {
                        _logger.error("Error occurred during Opening the Text Editor for" + _input.getName(), e); //$NON-NLS-1$
                    }
                }
            }
            IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
            window.getPartService().removePartListener(this);
        }
    }

    /**
     * This function adds resourceChangeListener to the workspace to detect the addition of new locales to the exisiting .rrc
     * files and dynamically add them in the .rrc file if the ResourceEditor is already open The addition of resourceEditor was a
     * fix to SDR185428.
     */
    public ResourceEditor() {
        // when ResourceEditor is first initialized _wasdirty is false. ResourceEditor is not dirty. Dirty bit is used in the
        // doSave function.
        _wasDirty = false;

        // if resource change listener is not already added to the workspace add it to the workspace.
        if (!resourceChangeListenerAdded) {
            // set the resourceChangeListener flag to true. when this flag is set to true the editor is not closed in the
            // createPages() method
            resourceChangeListenerAdded = true;

            // add Resource Change Listener to listen to addition of locales so that they can be added dynamically
            ResourcesPlugin.getWorkspace().addResourceChangeListener(new IResourceChangeListener() {
                // @Override
                public void resourceChanged(IResourceChangeEvent event) {
                    IResourceDelta delta = event.getDelta();

                    try {
                        delta.accept(new IResourceDeltaVisitor() {
                            // @Override

                            /**
                             * We are interested in checking if the file added was an RRH or a RRC file.
                             */
                            public boolean visit(IResourceDelta resourceDelta) throws CoreException {
                                IResource resource = resourceDelta.getResource();
                                int type = resource.getType();
                                int kind = resourceDelta.getKind();

                                // check to see if the resource added is a file
                                if (type == IResource.FILE) {
                                    // check to see if the resource is of the kind added
                                    if (kind == IResourceDelta.ADDED) {
                                        // check to see if the resource ends with .rrc or .rrh extension (these are resource file
                                        // extensions)
                                        if (resource.toString().endsWith(ResourceConstants.RRH_SUFFIX) || resource
                                                .getName().toString().endsWith(ResourceConstants.RRC_SUFFIX)) {
                                            // store the resource as final so that it can be used in the run method run method can
                                            // not refer to external non final variables
                                            final IResource runResource = resource;

                                            // Display thread was introduced as a 'blog' suggestion because changed to
                                            // ResourceEditor could not be done in the non-UI thread.
                                            Display.getDefault().asyncExec(new Runnable() {
                                                public void run() {
                                                    // your stuff here ...
                                                    try {
                                                        // get a reference to open editors.
                                                        // _openEditorReferences =
                                                        // PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences();
                                                        _openEditorReferences = getOpenEditorReferences();
                                                        // addPage(new EditorPart(), new FileEditorInput((IFile)resource));
                                                        // ResourceEditor.getInstance().createPages();
                                                        // createPages();
                                                        // System.out.println("Hello");

                                                        // check through all the open editors to see if any of the editors that we
                                                        // want to add the locale to is opened.
                                                        // Example : say if a.rrh and a.rrc already exist. Then if we add
                                                        // a_en.rrc ( english locale ) we want to browse through all the
                                                        // _openEditroReferences to see if a.rrh or a.rrc is opened.
                                                        for (int i = 0; i < _openEditorReferences.length; i++) {
                                                            // Check to see if the referenced editor is the instance of
                                                            // ResourceEditor
                                                            if (_openEditorReferences[i]
                                                                    .getEditor(true) instanceof ResourceEditor) {
                                                                ResourceEditor editor = (ResourceEditor) _openEditorReferences[i]
                                                                        .getEditor(true);
                                                                // get the name of the Input Editor name from the
                                                                // _openEditorReferences. Usually it is a.rrh file as set in the
                                                                // init function. However it can be a.rrc file in cases where the
                                                                // editor has no .rrh file.
                                                                String existingEditorFilename = _openEditorReferences[i]
                                                                        .getEditor(true).getEditorInput().getName();

                                                                // get the name of the .rrh file or .rrc file that we just added
                                                                String thisEditorFilename = runResource.getName();

                                                                // store the trimmed name for existing editor
                                                                String existingEditorFilenameTrim;

                                                                // store the name for the editor of the file that is added
                                                                String thisEditorFilenameTrim;

                                                                // store the path of the parent of the resource
                                                                String resourcePath = runResource.getParent()
                                                                        .getLocation().toOSString();

                                                                // store the path of the parent of the editor
                                                                String editorPath = ((FileEditorInput) (editor
                                                                        .getEditorInput())).getFile().getParent()
                                                                                .getLocation().toOSString();

                                                                // strip off both the existingEditor file name and thisEditor
                                                                // filename of its .rrc and .rrh extension and the locale name.
                                                                if (existingEditorFilename
                                                                        .endsWith(ResourceConstants.RRH_SUFFIX)
                                                                        || existingEditorFilename.endsWith(
                                                                                ResourceConstants.RRC_SUFFIX)) {
                                                                    if (existingEditorFilename.contains("_")) { //$NON-NLS-1$
                                                                        existingEditorFilenameTrim = existingEditorFilename
                                                                                .substring(0, existingEditorFilename
                                                                                        .indexOf("_")); //$NON-NLS-1$
                                                                    } else {
                                                                        existingEditorFilenameTrim = existingEditorFilename
                                                                                .substring(0, existingEditorFilename
                                                                                        .indexOf(".")); //$NON-NLS-1$
                                                                    }

                                                                    if (thisEditorFilename.contains("_")) { //$NON-NLS-1$
                                                                        thisEditorFilenameTrim = thisEditorFilename
                                                                                .substring(0, thisEditorFilename
                                                                                        .indexOf("_")); //$NON-NLS-1$
                                                                    } else {
                                                                        thisEditorFilenameTrim = thisEditorFilename
                                                                                .substring(0, thisEditorFilename
                                                                                        .indexOf(".")); //$NON-NLS-1$
                                                                    }

                                                                    // if the thisEditorFileNameTrim is equal to the
                                                                    // existingEditorFilenameTrim and the project of this editor
                                                                    // is equal to the project of the resource then only add the
                                                                    // dynamically added locale
                                                                    if (thisEditorFilenameTrim
                                                                            .equals(existingEditorFilenameTrim)
                                                                            && resourcePath.equals(editorPath)) {
                                                                        // existing editor on WorkbenchPage and this editor belong
                                                                        // to the same ResourceCollection

                                                                        // save previous changes in the editor
                                                                        editor.doSave(new NullProgressMonitor());

                                                                        String locale = thisEditorFilename
                                                                                .substring(
                                                                                        thisEditorFilename
                                                                                                .indexOf("_") + 1, //$NON-NLS-1$
                                                                                        thisEditorFilename
                                                                                                .indexOf(".")); //$NON-NLS-1$
                                                                        // editor . _wasDirty = false;

                                                                        // if the locale is already a part of the editor do not
                                                                        // add
                                                                        if (editor._resources
                                                                                .getLocale(locale) != null) {
                                                                            break;
                                                                        }

                                                                        // set callByResourceListener to true so that in
                                                                        // createPages function the editor. Close is not called
                                                                        editor._callByResourceListener = true;

                                                                        // dispose the existing pages of the editor
                                                                        editor.dispose();

                                                                        // reinitialize the editor again
                                                                        editor.init(_openEditorReferences[i]
                                                                                .getEditor(true).getEditorSite(),
                                                                                new FileEditorInput(
                                                                                        (IFile) runResource));

                                                                        // add Pages to editor
                                                                        editor.createPages();

                                                                        // set the callByResourceListener to false
                                                                        editor._callByResourceListener = false;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    } catch (Exception e) {
                                                    }
                                                }
                                            }); // new Runnable object ends here
                                        } // end of if
                                    } // end of if
                                } // end of if

                                // return true to continue visiting the Delta tree.
                                return true;
                            }// visit ends here
                        });// new ResourceDeltaVisitor ends here
                    } catch (CoreException e) {
                        // log.error(e.getMessage(), e);
                        e.printStackTrace();
                    }
                }
            }); // new IResourceChangeListener ends here
        }
    }

    public void doSave(IProgressMonitor monitor) {
        try {
            _resources.save();

            // Check if package was changed.
            String rrhPackage = PackageUtils.getRRHPackageID(rrhFile);
            if (!_originalPackage.equals(rrhPackage)) {
                // Attempt to find a non linked rrhIFile
                IFile files[] = ResourcesPlugin.getWorkspace().getRoot()
                        .findFilesForLocation(new Path(rrhFile.getAbsolutePath()));
                IFile rrhIFile = null;
                for (IFile file : files) {
                    if (!file.isLinked()) {
                        rrhIFile = file;
                        break;
                    }
                }
                if (files.length != 0 && rrhIFile == null) {
                    rrhIFile = files[0];
                }

                IJavaElement packageFolder = JavaCore.create(rrhIFile.getParent());
                IPackageFragmentRoot sourceFolder = (IPackageFragmentRoot) packageFolder.getParent();
                try {
                    moveResources(rrhIFile,
                            sourceFolder.createPackageFragment(rrhPackage, true, new NullProgressMonitor()));
                } catch (Exception e) {
                    _logger.error("doSave: error moving resources", e); //$NON-NLS-1$
                }
            }

            if (_wasDirty) {
                _wasDirty = false;
                firePropertyChange(IEditorPart.PROP_DIRTY);
            }

            // get eclipse workspace
            final IWorkspace workspace = ResourcesPlugin.getWorkspace();

            // get eclipse workspace description
            final IWorkspaceDescription workspaceDescription = workspace.getDescription();

            // get autoBuildFlag
            final boolean autoBuild = workspaceDescription.isAutoBuilding();
            IProject project = ((FileEditorInput) (this.getEditorInput())).getFile().getProject();

            // if autobuild is checked build eclipse project
            if (autoBuild) {
                try {
                    project.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
                } catch (CoreException e) {
                    e.printStackTrace();
                }
            }

            // We must refresh the project because we are using a JAR that uses File objects to save, instead of eclipse IFiles.
            project.refreshLocal(IProject.DEPTH_INFINITE, monitor);

        } catch (IOException e) {
            TableViewer viewer = getActiveResourceEditorPage().getTableViewer();
            Status status = new Status(IStatus.ERROR, ContextManager.PLUGIN_ID, IStatus.OK,
                    "Unable to open file for writing.", e);
            ErrorDialog.openError(viewer.getControl().getShell(), "Error - Resource Editor", "Error saving file.",
                    status);
            monitor.setCanceled(true);
        } catch (CoreException e) {
            _logger.error("doSave: error getting package", e); //$NON-NLS-1$
        }
    }

    public void doSaveAs() {
        // "Save As" not allowed
    }

    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
        if (!(input instanceof IFileEditorInput)) {
            throw new PartInitException(input.getName() + " is not part of the current project.");
        }

        String messagePrompt = ""; //$NON-NLS-1$
        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        _resourceEditorListener = new ResourceEditorListener(site, input);
        window.getPartService().addPartListener(_resourceEditorListener);

        FileEditorInput fileEditorInput = (FileEditorInput) input;
        // Check out file corresponding to the locale that is open in this ResourceEditor (Opened for Edit in Perforce)
        IFile[] checkOutFiles = new IFile[1];
        checkOutFiles[0] = ((IFileEditorInput) input).getFile();
        ResourcesPlugin.getWorkspace().validateEdit(checkOutFiles, null);

        _openEditorReferences = null;
        try {
            // _openEditorReferences = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getEditorReferences();
            _openEditorReferences = getOpenEditorReferences();
            // array of references to open editors in this WorkbenchPage this will be used to prevent multiple ResourceEditor
            // instances from being open for the same resource collection
        } catch (Exception e) {
            _logger.error("init:", e); //$NON-NLS-1$
        }

        // keeps track of the recently added _resourceFilename for this ResourceEditor.
        _resourceFilename = fileEditorInput.getName();

        // Fix for SDR169264 (eJDE: Resource Editor can show incorrect tab when switching between locales via double-click in
        // managing views) inputFileAbsolutePath = inputFileAbsolutePath.substring(0,
        // inputFileAbsolutePath.lastIndexOf(File.separator)); if selected file is .rrc file, we try to get corresponding .rrh
        // file
        String tempFilename = _resourceFilename;
        if (tempFilename.contains("_")) { //$NON-NLS-1$
            tempFilename = tempFilename.substring(0, tempFilename.indexOf("_")) + ResourceConstants.RRH_SUFFIX; //$NON-NLS-1$
        } else {
            tempFilename = tempFilename.replace(ResourceConstants.RRC_SUFFIX, ResourceConstants.RRH_SUFFIX);
        }

        rrhFile = new File(((Path) fileEditorInput.getPath()).toFile().getParentFile(), tempFilename);
        try {
            _originalPackage = PackageUtils.getRRHPackageID(rrhFile);
        } catch (Exception e) {
            _logger.error("init: error getting original package", e); //$NON-NLS-1$
        }

        // Check#1: Checks to see if the resource header file exists in the same location as the rrc file. This is a mandatory
        // check needed to create the resourceCollection in RIA.
        if (rrhFile.exists()) {
            try {
                _resources = ResourceCollectionFactory.newResourceCollection(rrhFile.getAbsolutePath());
                _resources.addListener(createCollectionListener());
            } catch (Exception e) {
                throw new PartInitException(e.getMessage());
            }

            // Check#2: Checks to see if the corresponding rrh file exists in the workspace. If createResourceFileEditorInput does
            // not return null, then the corresponding resource was found. We can then call super and return.
            FileEditorInput rrhFileEditorInput;
            if ((rrhFileEditorInput = createResourceFileEditorInput(rrhFile)) != null) {
                // Check#3: Checks to ensure that the resource collection has locale files. If no locale files exist, RE cannot be
                // opened.
                ResourceLocale[] resourceLocales = _resources.getLocales();
                IFile rrhIFile = ImportUtils.getProjectBasedFileFromOSBasedFile(rrhFile.getAbsolutePath());
                File rrcFile = getRRCFile(rrhFile);
                IFile rrcIFile = ImportUtils.getProjectBasedFileFromOSBasedFile(rrcFile.getAbsolutePath());

                if (resourceLocales.length != 0) {
                    // Check#4 Check to make sure at least 1 locale exists in workspace. This is required to create RE pages.
                    for (int i = 0; i < resourceLocales.length; i++) {
                        if (StringUtils.isEmpty(resourceLocales[i].getLocaleName())) {
                            if (rrcIFile != null && rrcIFile.exists()) {
                                super.init(site, rrhFileEditorInput);
                                return;
                            }
                        } else {
                            IFile resourceFile = ImportUtils.getProjectBasedFileFromOSBasedFile(
                                    ((RIMResourceLocale) resourceLocales[i]).getRrcFileAbsolutePath());
                            if (resourceFile != null && resourceFile.getName()
                                    .equals((((RIMResourceLocale) resourceLocales[i]).getRrcFilename()))) {
                                super.init(site, rrhFileEditorInput);
                                return;
                            }
                        }
                    }
                    MessageDialog.openError(site.getShell(), Messages.NO_LOCALE_ERROR_TITLE,
                            Messages.NO_LOCALE_ERROR_TEXT);
                } else {
                    // Prompt user to create root locale.
                    if (MessageDialog.openQuestion(site.getShell(), Messages.MISSING_LOCALE_ERROR_TITLE,
                            Messages.MISSING_LOCALE_ERROR_TEXT)) {
                        File rootRrcFile = getRRCFile(rrhFile);
                        try {
                            if (rootRrcFile.createNewFile()) {
                                if (rrhIFile.isLinked()) {
                                    IFile newRrcIFile = rrhIFile.getParent()
                                            .getFile(new Path(rootRrcFile.getName()));
                                    newRrcIFile.createLink(new Path(rootRrcFile.getAbsolutePath()), IResource.NONE,
                                            new NullProgressMonitor());
                                } else {
                                    rrhIFile.getProject().refreshLocal(IProject.DEPTH_INFINITE,
                                            new NullProgressMonitor());
                                }

                                // recreate the resource collection
                                _resources = ResourceCollectionFactory
                                        .newResourceCollection(rrhFile.getAbsolutePath());
                                super.init(site, rrhFileEditorInput);
                                return;
                            }
                        } catch (Exception e) {
                            _logger.error("init: error creating new root rrc file", e); //$NON-NLS-1$
                        }
                    }
                }
            } else {
                // The .rrh file does not exist in the workspace, prompt to load .rrh file.
                messagePrompt = NLS.bind(Messages.MESSAGE_BOX_RESOURCE_HEADER_DOES_NOT_EXIST_IN_WORKSPACE,
                        tempFilename, rrhFile.getAbsolutePath());

                if (MessageDialog.openQuestion(site.getShell(),
                        Messages.MESSAGE_BOX_RESOURCE_HEADER_DOES_NOT_EXIST_IN_WORKSPACE_TITLE, messagePrompt)) {
                    IFile fileOpened = fileEditorInput.getFile();
                    IFile newRrhIFile = fileOpened.getParent().getFile(new Path(rrhFile.getName()));
                    try {
                        if (!newRrhIFile.exists()) {
                            newRrhIFile.createLink(new Path(rrhFile.getAbsolutePath()), IResource.NONE,
                                    new NullProgressMonitor());
                        }
                    } catch (CoreException e) {
                        _logger.error("init: error creating linking rrh file", e); //$NON-NLS-1$
                    }

                    // Check#2: Checks to see if the corresponding rrh file exists in the workspace. If
                    // createResourceFileEditorInput does not return null, then the corresponding resource was found. We can
                    // then call super and return.
                    if ((rrhFileEditorInput = createResourceFileEditorInput(rrhFile)) != null) {
                        super.init(site, rrhFileEditorInput);
                        return;
                    }
                } else {
                    // User selected to not load the .rrh file. Prompt to load .rrc file in text editor.
                    messagePrompt = NLS.bind(Messages.MESSAGE_BOX_OPEN_TEXT_EDITOR_PROMPT, _resourceFilename);

                    if (MessageDialog.openQuestion(site.getShell(),
                            Messages.MESSAGE_BOX_OPEN_TEXT_EDITOR_PROMPT_TITLE, messagePrompt)) {
                        _resourceEditorListener.setOpenTextEditor(true);
                    }
                }
            }
        } else {
            // The corresponding .rrh file does not exist in the rrc directory. We cannot create a resourceCollection unless we
            // enforce this limitation.
            messagePrompt = NLS.bind(Messages.MESSAGE_BOX_RESOURCE_HEADER_DOES_NOT_EXIST_IN_DIRECTORY,
                    new String[] { tempFilename, rrhFile.getParent(), _resourceFilename });

            MessageDialog.openError(site.getShell(),
                    Messages.MESSAGE_BOX_RESOURCE_HEADER_DOES_NOT_EXIST_IN_DIRECTORY_TITLE, messagePrompt);
        }
        // Dummy call to avoid Part Init exception caused by the site not getting set properly.
        super.init(site, input);

        // Set flag to close editor when its opened. Eclipse requires the editor to open.
        _resourceEditorListener.setAllowOpen(false);
    }

    public FileEditorInput createResourceFileEditorInput(File rrhFile) throws PartInitException {
        // For SDR180459: We should get project based file for the local .rrh file that is represented by underlying OS file
        // system.
        IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
        IFile rrhIFile = null;
        for (IProject project : projects) {
            if (rrhIFile != null) {
                break;
            }
            rrhIFile = ImportUtils.getProjectBasedFileFromOSBasedFile(project.getName(), rrhFile.getAbsolutePath());
        }

        if (rrhIFile != null) {
            return new FileEditorInput(rrhIFile);
        } else {
            return null;
        }
    }

    /**
     * This method will move the given rrhIFile and any of its corresponding locales (if they exist in the workspace) to the
     * passed in package.
     *
     * @param rrhIFile
     *            - The resource header file being moved.
     * @param newPackage
     *            - The package to move the resources to.
     */
    private void moveResources(IFile rrhIFile, IPackageFragment newPackage) {
        IPath oldRrhLocation = rrhIFile.getLocation();
        RIMResourceLocale locales[] = (RIMResourceLocale[]) _resources.getLocales();

        if (!rrhIFile.isLinked()) {
            IPath newDestination = newPackage.getPath();
            IContainer sourceFolder = rrhIFile.getParent();

            // First we move the rrh file. Then we Check for links to the rrh file. If they exist, they must be recreated in the
            // proper package and pointing to the new location.
            IFile resourceFile = rrhIFile;
            IFile newIFile = moveCopiedFile(resourceFile, newDestination.append(resourceFile.getName()));
            updateLinksLocationAndPackage(oldRrhLocation, newIFile.getLocation(), newPackage.getElementName());

            // Second we move all the locales (if they exist in the workspace). Then we check for any/all links to the locale
            // files. If they exist, they must be recreated in the proper package and pointing to the new location.
            for (RIMResourceLocale locale : locales) {
                resourceFile = sourceFolder.getFile(new Path(locale.getRrcFilename()));
                newIFile = moveCopiedFile(resourceFile, newDestination.append(resourceFile.getName()));
                updateLinksLocationAndPackage(resourceFile.getLocation(), newIFile.getLocation(),
                        newPackage.getElementName());
            }
        } else {
            // First update all links pointing to rrh file.
            updateLinksLocationAndPackage(oldRrhLocation, null, newPackage.getElementName());

            // Second update all links pointing to any locales from this resource collection that exist in the workspace.
            IPath resourceLocation = null;
            for (RIMResourceLocale locale : locales) {
                resourceLocation = new Path(locale.getRrcFileAbsolutePath());
                updateLinksLocationAndPackage(resourceLocation, null, newPackage.getElementName());
            }
        }
    }

    private IFile moveCopiedFile(IFile resourceFile, IPath newDestination) {
        if (resourceFile == null || !resourceFile.exists() || resourceFile.isLinked()) {
            throw new IllegalArgumentException("Error: resourceFile must exist and cannot be null or linked."); //$NON-NLS-1$
        }
        if (newDestination == null) {
            throw new IllegalArgumentException("Error: newDestination cannot be null."); //$NON-NLS-1$
        }

        try {
            resourceFile.move(newDestination, true, new NullProgressMonitor());
        } catch (CoreException e) {
            _logger.error("Error moving resource", e); //$NON-NLS-1$
        }

        IProject project = resourceFile.getProject();
        IPath projectLocation = newDestination.removeFirstSegments(1);
        IFile newIFile = project.getFile(projectLocation);
        return newIFile;
    }

    /**
     * This method will find all links pointing to oldLinkLocation and will point them to the newLinkLocation. The method also
     * moves the links to a package specified by the passed in packageID.
     *
     * @param oldLinkLocation
     *            - The location existing links will be pointing to.
     * @param newLinkLocation
     *            - The location the new links will be pointing to, null if location doesn't change.
     * @param packageID
     *            - The package to place the new links.
     */
    private void updateLinksLocationAndPackage(IPath oldLinkLocation, IPath newLinkLocation, String packageID) {
        if (newLinkLocation == null) {
            // Link location will not change
            newLinkLocation = oldLinkLocation;
        }
        IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(oldLinkLocation);
        for (IFile file : files) {
            if (file.isLinked()) {
                IJavaElement packageFolder = JavaCore.create(file.getParent());
                IPackageFragmentRoot sourceFolder = (IPackageFragmentRoot) packageFolder.getParent();
                try {
                    IPackageFragment newPackage = sourceFolder.createPackageFragment(packageID, true,
                            new NullProgressMonitor());
                    if (newPackage.exists()) {
                        IContainer parentFolder = ((IFolder) newPackage.getResource());
                        IFile newLocation = parentFolder.getFile(new Path(file.getName()));
                        newLocation.createLink(newLinkLocation, IResource.NONE, new NullProgressMonitor());
                        file.delete(true, new NullProgressMonitor());
                    }
                } catch (Exception e) {
                    _logger.error("Error updating links", e); //$NON-NLS-1$
                }
            }
        }
    }

    public boolean isDirty() {
        if (_resources != null) {
            return _resources.isDirty();
        }
        return false;
    }

    public boolean isSaveAsAllowed() {
        return false;
    }

    public void setFocus() {
        getActiveResourceEditorPage().setFocus();
    }

    /**
     * This function was added as a fix to SDR185428.
     */
    public void dispose() {
        for (int i = this.getPageCount() - 1; i >= 0; i--) {

            removePage(i);
        }
    }

    protected void createPages() {
        // If _resource is null then the .rrh file was not found or if the _allowOpen flag is set to false we must not allow this
        // editor to open. In these cases we create a dummy page with no content in order to satisfy the page requirements. We
        // then simply return.
        if (_resources == null || !_resourceEditorListener._allowOpen) {
            addPage(new Composite(this.getContainer(), SWT.BORDER_SOLID));
            setActivePage(0);
            return;
        }

        // Fix for DPI221808. Only add pages for locales that exist in project
        ArrayList<ResourceLocale> localeList = new ArrayList<ResourceLocale>();
        ResourceLocale[] resourceLocales = _resources.getLocales();
        for (int i = 0; i < resourceLocales.length; i++) {
            // Special case for root locale file. The getProjectBasedFileFromOSBasedFile method can't find linked root locales.
            if (StringUtils.isEmpty(resourceLocales[i].getLocaleName())) {
                File rrcFile = getRRCFile(rrhFile);
                IFile rrcIFile = ImportUtils.getProjectBasedFileFromOSBasedFile(rrcFile.getAbsolutePath());

                if (rrcIFile != null && rrcIFile.exists()) {
                    localeList.add(resourceLocales[i]);
                }
            } else {
                IFile resourceFile = ImportUtils.getProjectBasedFileFromOSBasedFile(
                        ((RIMResourceLocale) resourceLocales[i]).getRrcFileAbsolutePath());
                if (resourceFile != null && resourceFile.getName()
                        .equals((((RIMResourceLocale) resourceLocales[i]).getRrcFilename()))) {
                    localeList.add(resourceLocales[i]);
                }
            }
        }
        ResourceLocale[] locales = localeList.toArray(new ResourceLocale[localeList.size()]);
        _pages = new Vector<ResourceEditorPage>(locales.length);
        // locale corresponding to .rrh/.rrc file that was opened from package explorer (i.e. "en", "fr")
        String currentLocaleName = ""; //$NON-NLS-1$

        // open first page (i.e. tab for root locale) of ResourceEditor by default
        int setActivePageIndex = 0;

        for (int i = 0; i < locales.length; ++i) {
            ResourceEditorPage page = new ResourceEditorPage(getContainer(), locales[i]);
            int index = addPage(page.getControl());
            String localeName = locales[i].getLocaleName();
            setPageText(index, localeName == ResourceConstants.ROOT_LOCALE ? ROOT : localeName);
            page.createContextMenu(getSite());
            _pages.add(i, page);

            if (_resourceFilename.endsWith(ResourceConstants.RRC_SUFFIX)) {
                currentLocaleName = _resourceFilename.substring(_resourceFilename.indexOf("_") + 1, //$NON-NLS-1$
                        _resourceFilename.lastIndexOf(ResourceConstants.RRC_SUFFIX));
            } else {
                currentLocaleName = _resourceFilename.substring(_resourceFilename.indexOf("_") + 1, //$NON-NLS-1$
                        _resourceFilename.lastIndexOf(ResourceConstants.RRH_SUFFIX));
            }

            if (currentLocaleName.equals(localeName)) {
                setActivePage(i);
                // keep track of which locale tab to open in ResourceEditor
                setActivePageIndex = i;
            } else {
                setActivePage(0);
            }
        }

        // flag used to determine if the resource collection is already open in an existing Resource Editor instance
        boolean resourceCollectionAlreadyOpen = false;
        try {
            if (_openEditorReferences.length > 1) {
                for (int i = 0; i < _openEditorReferences.length; i++) {

                    if (_openEditorReferences[i].getEditor(false) instanceof ResourceEditor) {

                        String existingEditorFilename = _openEditorReferences[i].getEditor(false).getEditorInput()
                                .getName();
                        String thisEditorFilename = this.getEditorInput().getName();

                        String existingEditorPath = ((FileEditorInput) (_openEditorReferences[i].getEditor(true)
                                .getEditorInput())).getFile().getParent().getLocation().toOSString();
                        String thisEditorPath = ((FileEditorInput) (this.getEditorInput())).getFile().getParent()
                                .getLocation().toOSString();

                        if (existingEditorFilename.endsWith(ResourceConstants.RRH_SUFFIX)
                                || existingEditorFilename.endsWith(ResourceConstants.RRC_SUFFIX)) {
                            if (existingEditorFilename.contains("_")) { //$NON-NLS-1$
                                existingEditorFilename = existingEditorFilename.substring(0,
                                        existingEditorFilename.indexOf("_")); //$NON-NLS-1$
                            } else {
                                existingEditorFilename = existingEditorFilename.substring(0,
                                        existingEditorFilename.indexOf(".")); //$NON-NLS-1$
                            }

                            if (thisEditorFilename.contains("_")) { //$NON-NLS-1$
                                thisEditorFilename = thisEditorFilename.substring(0,
                                        thisEditorFilename.indexOf("_")); //$NON-NLS-1$
                            } else {
                                thisEditorFilename = thisEditorFilename.substring(0,
                                        thisEditorFilename.indexOf(".")); //$NON-NLS-1$
                            }

                            // existing editor on WorkbenchPage and this editor belong to the same ResourceCollection
                            if (thisEditorFilename.equals(existingEditorFilename)
                                    && existingEditorPath.equals(thisEditorPath)) {
                                if (_callByResourceListener == false) {
                                    // do not open duplicate editor for resources under the same ResourceCollection
                                    PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                                            .closeEditor(this, false);
                                }

                                ((ResourceEditor) _openEditorReferences[i].getEditor(true))
                                        .setActivePage(setActivePageIndex);
                                // set focus to the editor containing resources for this
                                PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                                        .activate(_openEditorReferences[i].getEditor(true));
                                resourceCollectionAlreadyOpen = true;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
        }

        if (!resourceCollectionAlreadyOpen) {
            // Update _resourceEditorPages<ResourceEditorPage> vector with newly opened resource files (used by
            // ResourceEditorOptionsDialog class for versioning highlighting)
            for (int i = 0; i < _pages.size(); i++) {
                for (int j = 0; j < _resourceEditorPages.size(); j++) {
                    // remove old existing ResourceEditorPage objects
                    if (_resourceEditorPages.get(j).getRrcFile().getAbsolutePath()
                            .equals(_pages.get(i).getRrcFile().getAbsolutePath())) {
                        _resourceEditorPages.remove(j);
                        // System.out.println("removed: " + _pages.get(i).getRrcFile().getAbsolutePath());
                    }
                }
                _resourceEditorPages.add(_pages.get(i));
                super.setActivePage(setActivePageIndex);
            }

            // Activate Versioning Highlighting when resource file is opened in Resource Editor (if turned on)
            if (_pages.size() > 0) {
                String rrhPath = getRRCFile(_pages.get(0).getRrcFile()).getAbsolutePath();
                // first page (index 0) is always root locale
                File rrhFile = new File(rrhPath);
                String originalLocale = ResourceEditorOptionsDialog.getOriginalLocaleString(rrhFile);
                if (originalLocale != null) {
                    ResourceEditorOptionsDialog.updateVersioningForResourceEditor(true, _resources.getLocale("")); //$NON-NLS-1$
                }
            }
            _pages.get(setActivePageIndex).setFocus();
        }
    }

    protected void pageChange(int newPageIndex) {
        updateTitle(newPageIndex);
        super.pageChange(newPageIndex);
    }

    private ResourceCollectionListener createCollectionListener() {
        return new ResourceCollectionListener() {
            public void commentChanged(String key) {
                markDirty();
            }

            public void keyAdded(ResourceElement element) {
                if (localeExists(element.getLocale().getLocaleName())) {
                    getResourceEditorPage(element).refresh();
                }
                markDirty();
            }

            public void keyChanged(ResourceElement element) {
                if (localeExists(element.getLocale().getLocaleName())) {
                    getResourceEditorPage(element).update(element,
                            new String[] { ResourceEditorPage.KEY_COLUMN_ID });
                }
                markDirty();
            }

            public void keyDeleted(ResourceElement element) {
                if (localeExists(element.getLocale().getLocaleName())) {
                    getResourceEditorPage(element).refresh();
                }
                markDirty();
            }

            public void valueChanged(ResourceElement element) {
                getResourceEditorPage(element).update(element, new String[] { ResourceEditorPage.VALUE_COLUMN_ID });
                markDirty();
            }
        };
    }

    private ResourceEditorPage getActiveResourceEditorPage() {
        return _pages.elementAt(getActivePage());
    }

    private boolean localeExists(String localeName) {
        for (int i = 0; i < _pages.size(); ++i) {
            String currentPageLocale = _pages.elementAt(i).getLocale().getLocaleName();
            if (currentPageLocale.equals(localeName)) {
                return true;
            }
        }
        return false;
    }

    private ResourceEditorPage getResourceEditorPage(ResourceElement element) {
        String localeName = element.getLocale().getLocaleName();

        if (localeName == ResourceConstants.ROOT_LOCALE) {
            localeName = ROOT;
        }

        // TODO: make this a more efficient search
        for (int i = 0; i < _pages.size(); ++i) {
            String pageName = getPageText(i);
            if (pageName.equals(localeName)) {
                return _pages.elementAt(i);
            }
        }
        throw new IllegalArgumentException();
    }

    private void markDirty() {
        if (!_wasDirty && _resources.isDirty()) {
            _wasDirty = true;
            firePropertyChange(IEditorPart.PROP_DIRTY);
        }
    }

    private void updateTitle(int index) {
        String editorFileName = _resourceFilename;

        if (editorFileName.contains("_")) { //$NON-NLS-1$
            editorFileName = editorFileName.substring(0, editorFileName.indexOf("_")); //$NON-NLS-1$
        } else {
            editorFileName = editorFileName.substring(0, editorFileName.indexOf(".")); //$NON-NLS-1$
        }
        setPartName("Resource Editor - " + editorFileName + "-" + getPageText(index) + " locale");
    }

    /**
     * Helper method returns vector of IFile objects to be checked out
     *
     * @return
     */
    protected static Vector<IFile> getCheckoutFiles() {
        return _checkoutFiles;
    }

    /**
     * Helper method returns vector of all ResourceEditorPage objects belonging to all resource collections that were ever open in
     * the Resource Editor. (used for versioning highlighting)
     *
     * @return
     */
    protected static Vector<ResourceEditorPage> getResourceEditorPages() {
        return _resourceEditorPages;
    }
}