/*
* 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, _resourceFilename //$NON-NLS-1$
.lastIndexOf( ResourceConstants.RRC_SUFFIX ) );
} else {
currentLocaleName = _resourceFilename.substring( _resourceFilename.indexOf( "_" ) + 1, _resourceFilename //$NON-NLS-1$
.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;
}
}