/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package org.pentaho.di.ui.repository.repositoryexplorer.controllers;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import com.google.common.annotations.VisibleForTesting;
import org.eclipse.swt.widgets.Shell;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.repository.RepositoryDirectoryInterface;
import org.pentaho.di.repository.RepositoryExtended;
import org.pentaho.di.ui.core.dialog.ErrorDialog;
import org.pentaho.di.ui.repository.repositoryexplorer.ContextChangeVetoer;
import org.pentaho.di.ui.repository.repositoryexplorer.ContextChangeVetoer.TYPE;
import org.pentaho.di.ui.repository.repositoryexplorer.ContextChangeVetoerCollection;
import org.pentaho.di.ui.repository.repositoryexplorer.ControllerInitializationException;
import org.pentaho.di.ui.repository.repositoryexplorer.IUISupportController;
import org.pentaho.di.ui.repository.repositoryexplorer.RepositoryExplorer;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIObjectCreationException;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIObjectRegistry;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryContent;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryDirectory;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryObject;
import org.pentaho.di.ui.repository.repositoryexplorer.model.UIRepositoryObjects;
import org.pentaho.di.ui.spoon.Spoon;
import org.pentaho.ui.xul.XulComponent;
import org.pentaho.ui.xul.XulException;
import org.pentaho.ui.xul.binding.Binding;
import org.pentaho.ui.xul.binding.BindingConvertor;
import org.pentaho.ui.xul.binding.BindingFactory;
import org.pentaho.ui.xul.components.XulConfirmBox;
import org.pentaho.ui.xul.components.XulMessageBox;
import org.pentaho.ui.xul.components.XulPromptBox;
import org.pentaho.ui.xul.containers.XulTree;
import org.pentaho.ui.xul.dnd.DropEvent;
import org.pentaho.ui.xul.impl.AbstractXulEventHandler;
import org.pentaho.ui.xul.swt.SwtBindingFactory;
import org.pentaho.ui.xul.swt.custom.DialogConstant;
import org.pentaho.ui.xul.swt.tags.SwtDialog;
import org.pentaho.ui.xul.util.XulDialogCallback;
/**
*
* This is the XulEventHandler for the browse panel of the repository explorer. It sets up the bindings for browse
* functionality.
*
*/
public class BrowseController extends AbstractXulEventHandler implements IUISupportController, IBrowseController {
private static Class<?> PKG = RepositoryExplorer.class; // for i18n purposes, needed by Translator2!!
protected UIRepositoryDirectory repoDir;
protected XulTree folderTree;
protected XulTree fileTable;
protected UIRepositoryDirectory repositoryDirectory;
protected ContextChangeVetoerCollection contextChangeVetoers;
protected BindingFactory bf;
protected Binding directoryBinding, selectedItemsBinding;
protected List<UIRepositoryDirectory> selectedFolderItems;
protected List<UIRepositoryObject> selectedFileItems;
protected List<UIRepositoryDirectory> repositoryDirectories;
protected Repository repository;
List<UIRepositoryObject> repositoryObjects;
List<UIRepositoryObject> repositoryItems;
protected MainController mainController;
protected XulMessageBox messageBox;
protected XulConfirmBox confirmBox;
private Shell shell;
/**
* Allows for lookup of a UIRepositoryDirectory by ObjectId. This allows the reuse of instances that are inside a UI
* tree.
*/
protected Map<ObjectId, UIRepositoryDirectory> dirMap;
private PropertyChangeListener fileChildrenListener = new PropertyChangeListener() {
public void propertyChange( PropertyChangeEvent arg0 ) {
try {
firePropertyChange( "selectedRepoDirChildren", null, getSelectedRepoDirChildren() );
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
};
public BrowseController() {
}
// begin PDI-3326 hack
private void fireRepositoryDirectoryChange() {
firePropertyChange( "repositoryDirectory", null, repositoryDirectory );
}
private void fireFoldersAndItemsChange( List<UIRepositoryDirectory> previousValue,
UIRepositoryObjects previousRepoObjects ) {
firePropertyChange( "repositoryDirectories", previousValue, getRepositoryDirectories() );
firePropertyChange( "selectedRepoDirChildren", previousRepoObjects, getSelectedRepoDirChildren() );
}
// end PDI-3326 hack
@SuppressWarnings( "deprecation" )
public void init( Repository repository ) throws ControllerInitializationException {
try {
this.repository = repository;
mainController = (MainController) this.getXulDomContainer().getEventHandler( "mainController" );
RepositoryDirectoryInterface root;
try {
if ( repository instanceof RepositoryExtended ) {
root = ( (RepositoryExtended) repository ).loadRepositoryDirectoryTree( "/", "*.ktr|*.kjb", -1, true, true, true );
} else {
root = repository.loadRepositoryDirectoryTree();
}
this.repositoryDirectory =
UIObjectRegistry.getInstance().constructUIRepositoryDirectory( root,
null, repository );
} catch ( UIObjectCreationException uoe ) {
this.repositoryDirectory =
new UIRepositoryDirectory( repository.loadRepositoryDirectoryTree(), null, repository );
}
dirMap = new HashMap<ObjectId, UIRepositoryDirectory>();
populateDirMap( repositoryDirectory );
bf = new SwtBindingFactory();
bf.setDocument( this.getXulDomContainer().getDocumentRoot() );
messageBox = (XulMessageBox) document.createElement( "messagebox" );
createBindings();
} catch ( Exception e ) {
throw new ControllerInitializationException( e );
}
}
protected void createBindings() {
shell = ( (SwtDialog) document.getElementById( "repository-explorer-dialog" ) ).getShell();
folderTree = (XulTree) document.getElementById( "folder-tree" );
fileTable = (XulTree) document.getElementById( "file-table" );
if ( !repositoryDirectory.isVisible() ) {
folderTree.setHiddenrootnode( true );
} else {
folderTree.setHiddenrootnode( false );
}
BindingConvertor<List<?>, Boolean> checkIfMultipleItemsAreSelected = new BindingConvertor<List<?>, Boolean>() {
@Override
public Boolean sourceToTarget( List<?> value ) {
return value != null && value.size() == 1 && value.get( 0 ) != null;
}
@Override
public List<?> targetToSource( Boolean value ) {
return null;
}
};
bf.setBindingType( Binding.Type.ONE_WAY );
bf.createBinding( fileTable, "selectedItems", "file-context-rename", "!disabled", checkIfMultipleItemsAreSelected );
bf.createBinding( fileTable, "selectedItems", this, "selectedFileItems" );
// begin PDI-3326 hack
PropertyChangeListener childrenListener = new PropertyChangeListener() {
public void propertyChange( PropertyChangeEvent evt ) {
fireRepositoryDirectoryChange();
}
};
repositoryDirectory.addPropertyChangeListener( "children", childrenListener );
// end PDI-3326 hack
directoryBinding = createDirectoryBinding();
// Bind the selected index from the folder tree to the list of repository objects in the file table.
bf.setBindingType( Binding.Type.ONE_WAY );
bf.createBinding( folderTree, "selectedItems", this, "selectedFolderItems" );
bf.setBindingType( Binding.Type.ONE_WAY );
selectedItemsBinding = bf.createBinding( this, "selectedRepoDirChildren", fileTable, "elements" );
// bindings can be added here in subclasses
doCreateBindings();
try {
// Fires the population of the repository tree of folders.
directoryBinding.fireSourceChanged();
} catch ( Exception e ) {
// convert to runtime exception so it bubbles up through the UI
throw new RuntimeException( e );
}
try {
// Set the initial selected directory as the users home directory
RepositoryDirectoryInterface homeDir = repository.getUserHomeDirectory();
int currentDir = 0;
String[] homePath = homeDir == null ? null : homeDir.getPathArray();
if ( homePath != null ) {
UIRepositoryDirectory tempRoot = repositoryDirectory;
// Check to see if the first item in homePath is the root directory
if ( homePath.length > 0 && tempRoot.getName().equalsIgnoreCase( homePath[currentDir] ) ) {
if ( homePath.length == 1 ) {
// The home directory is home root
setSelectedFolderItems( Arrays.asList( tempRoot ) );
}
// We have used the first element. Increment to the next
currentDir++;
}
// Traverse the tree until we find our destination
for ( ; currentDir < homePath.length; currentDir++ ) {
for ( UIRepositoryObject uiObj : tempRoot ) {
if ( uiObj instanceof UIRepositoryDirectory ) {
if ( uiObj.getName().equalsIgnoreCase( homePath[currentDir] ) ) {
// We have a match. Let's move on to the next
tempRoot = (UIRepositoryDirectory) uiObj;
break;
}
}
}
}
// If we have traversed as many directories as there are in the path, we have found the directory
if ( homePath.length == currentDir ) {
setSelectedFolderItems( Arrays.asList( tempRoot ) );
folderTree.setSelectedItems( this.selectedFolderItems );
}
}
} catch ( Exception e ) {
throw new RuntimeException( e );
}
}
protected void doCreateBindings() {
}
protected Binding createDirectoryBinding() {
bf.setBindingType( Binding.Type.ONE_WAY );
return bf.createBinding( this, "repositoryDirectory", folderTree, "elements" );
}
public String getName() {
return "browseController";
}
public UIRepositoryDirectory getRepositoryDirectory() {
return repositoryDirectory;
}
protected void populateDirMap( UIRepositoryDirectory repDir ) {
dirMap.put( repDir.getObjectId(), repDir );
for ( UIRepositoryObject obj : repDir ) {
if ( obj instanceof UIRepositoryDirectory ) {
populateDirMap( (UIRepositoryDirectory) obj );
}
}
}
public void expandAllFolders() {
folderTree.expandAll();
}
public void collapseAllFolders() {
folderTree.collapseAll();
}
public void openContent() {
Collection<UIRepositoryObject> content = fileTable.getSelectedItems();
openContent( content.toArray() );
}
public void openContent( Object[] items ) {
if ( ( items != null ) && ( items.length > 0 ) ) {
for ( Object o : items ) {
if ( o instanceof UIRepositoryDirectory ) {
( (UIRepositoryDirectory) o ).toggleExpanded();
List<Object> selectedFolder = new ArrayList<Object>();
selectedFolder.add( o );
folderTree.setSelectedItems( selectedFolder );
} else if ( ( mainController != null && mainController.getCallback() != null )
&& ( o instanceof UIRepositoryContent ) ) {
try {
mainController.getCallback().open( (UIRepositoryContent) o, null );
} catch ( Exception e ) {
mainController.handleLostRepository( e );
}
// TODO: fire request to close dialog
}
}
}
}
public void renameContent() throws Exception {
try {
Collection<UIRepositoryContent> content = fileTable.getSelectedItems();
UIRepositoryObject contentToRename = content.iterator().next();
renameRepositoryObject( contentToRename );
if ( contentToRename instanceof UIRepositoryDirectory ) {
directoryBinding.fireSourceChanged();
}
selectedItemsBinding.fireSourceChanged();
} catch ( Throwable th ) {
if ( mainController == null || !mainController.handleLostRepository( th ) ) {
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage( BaseMessages.getString( PKG, th.getLocalizedMessage() ) );
messageBox.open();
}
}
}
protected void confirm( String title, String message, final Callable<Void> onAccept ) throws XulException {
confirmBox = (XulConfirmBox) document.createElement( "confirmbox" );
confirmBox.setTitle( BaseMessages.getString( PKG, title ) );
confirmBox.setMessage( BaseMessages.getString( PKG, message ) );
confirmBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
confirmBox.setCancelLabel( BaseMessages.getString( PKG, "Dialog.Cancel" ) );
confirmBox.addDialogCallback( new XulDialogCallback<Object>() {
public void onClose( XulComponent sender, Status returnCode, Object retVal ) {
if ( returnCode == Status.ACCEPT ) {
try {
onAccept.call();
} catch ( Exception e ) {
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage( BaseMessages.getString( PKG, e.getLocalizedMessage() ) );
messageBox.open();
}
}
}
}
public void onError( XulComponent sender, Throwable t ) {
throw new RuntimeException( t );
}
} );
confirmBox.open();
}
public void deleteContent() throws Exception {
for ( Object object : fileTable.getSelectedItems() ) {
if ( object instanceof UIRepositoryObject ) {
final UIRepositoryObject repoObject = (UIRepositoryObject) object;
Callable<Void> deleteCallable = new Callable<Void>() {
@Override
public Void call() throws Exception {
deleteContent( repoObject );
return null;
}
};
// If content to be deleted is a folder we will display a warning message
// notwithstanding the folder is empty or not. If you choose to delete this folder, all its
// item(s) will be lost. If the user accept this, then we will delete that folder
// otherwise we will end this method call
if ( repoObject instanceof UIRepositoryDirectory ) {
confirm( "BrowseController.DeleteNonEmptyFolderWarningTitle",
"BrowseController.DeleteFolderWarningMessage", deleteCallable );
} else {
confirm( "BrowseController.DeleteFileWarningTitle",
"BrowseController.DeleteFileWarningMessage", deleteCallable );
}
}
}
}
private String newName = null;
protected void deleteContent( UIRepositoryObject repoObject ) throws Exception {
repoObject.delete();
if ( repoObject instanceof UIRepositoryDirectory ) {
directoryBinding.fireSourceChanged();
if ( repoDir != null ) {
repoDir.refresh();
}
}
selectedItemsBinding.fireSourceChanged();
}
public void createFolder() throws Exception {
try {
Collection<UIRepositoryDirectory> directories = folderTree.getSelectedItems();
if ( directories == null || directories.size() == 0 ) {
return;
}
UIRepositoryDirectory selectedFolder = directories.iterator().next();
// First, ask for a name for the folder
XulPromptBox prompt = promptForName( null );
prompt.addDialogCallback( new XulDialogCallback<String>() {
public void onClose( XulComponent component, Status status, String value ) {
if ( status == Status.ACCEPT ) {
newName = value;
} else {
newName = null;
}
}
public void onError( XulComponent component, Throwable err ) {
throw new RuntimeException( err );
}
} );
prompt.open();
if ( newName != null ) {
if ( selectedFolder == null ) {
selectedFolder = repositoryDirectory;
}
//Do an explicit check here to see if the folder already exists in the ui
//This is to prevent a double message being sent in case the folder does
//not exist in the ui but does exist in the repo (PDI-5202)
boolean folderExistsInUI = selectedFolder.contains( newName );
if ( folderExistsInUI ) {
throw new Exception(
BaseMessages.getString(
PKG,
"BrowserController.DirAlreadyExistsInUI",
newName
)
);
}
//PDI-5202
String newNameInRepo = selectedFolder.checkDirNameExistsInRepo( newName );
if ( newNameInRepo != null ) {
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Warning" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage(
BaseMessages.getString(
PKG,
"BrowserController.DirAlreadyExistsInRepository",
newNameInRepo
)
);
messageBox.open();
newName = newNameInRepo;
}
UIRepositoryDirectory newDir = selectedFolder.createFolder( newName );
dirMap.put( newDir.getObjectId(), newDir );
directoryBinding.fireSourceChanged();
selectedItemsBinding.fireSourceChanged();
this.folderTree.setSelectedItems( Collections.singletonList( selectedFolder ) );
}
newName = null;
} catch ( Exception e ) {
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage( BaseMessages.getString( PKG, e.getLocalizedMessage() ) );
messageBox.open();
}
}
}
public void exportFolder() throws Exception {
for ( Object object : folderTree.getSelectedItems() ) {
if ( object instanceof UIRepositoryDirectory ) {
repoDir = (UIRepositoryDirectory) object;
// Export the directories one by one...
//
if ( Spoon.getInstance().exportRepositoryDirectory( repoDir.getDirectory() ) ) {
return;
}
}
}
}
public void deleteFolder() throws Exception {
UIRepositoryDirectory newSelectedItem = null;
for ( Object object : folderTree.getSelectedItems() ) {
if ( object instanceof UIRepositoryDirectory ) {
repoDir = (UIRepositoryDirectory) object;
newSelectedItem = repoDir.getParent();
// If content to be deleted is a folder we will display a warning message
// notwithstanding the folder is empty or not. If you choose to delete this folder, all its
// item(s) will be lost. If the user accept this, then we will delete that folder
// otherwise we will end this method call
confirmBox = (XulConfirmBox) document.createElement( "confirmbox" );
confirmBox.setTitle( BaseMessages.getString( PKG, "BrowseController.DeleteNonEmptyFolderWarningTitle" ) );
confirmBox.setMessage( BaseMessages
.getString( PKG, "BrowseController.DeleteFolderWarningMessage" ) );
confirmBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
confirmBox.setCancelLabel( BaseMessages.getString( PKG, "Dialog.Cancel" ) );
confirmBox.addDialogCallback( new XulDialogCallback<Object>() {
public void onClose( XulComponent sender, Status returnCode, Object retVal ) {
if ( returnCode == Status.ACCEPT ) {
try {
deleteFolder( repoDir );
} catch ( Exception e ) {
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
new ErrorDialog( shell, BaseMessages.getString( PKG, "RepositoryExplorerDialog.ErrorDialog.Title" ),
BaseMessages.getString( PKG, "RepositoryExplorerDialog.ErrorDialog.Message" ), e );
}
}
}
}
public void onError( XulComponent sender, Throwable t ) {
throw new RuntimeException( t );
}
} );
confirmBox.open();
break;
} else {
deleteFolder( repoDir );
}
}
// since old selected item is the now deleted one, set the parent as the selected item
if ( newSelectedItem != null ) {
folderTree.setSelectedItems( Arrays.asList( newSelectedItem ) );
}
}
protected void deleteFolder( UIRepositoryDirectory repoDir ) throws Exception {
repoDir.delete();
directoryBinding.fireSourceChanged();
selectedItemsBinding.fireSourceChanged();
repoDir.refresh();
}
public void renameFolder() throws Exception {
try {
Collection<UIRepositoryDirectory> directory = folderTree.getSelectedItems();
final UIRepositoryDirectory toRename = directory.iterator().next();
renameRepositoryObject( toRename );
directoryBinding.fireSourceChanged();
selectedItemsBinding.fireSourceChanged();
} catch ( Throwable th ) {
if ( mainController == null || !mainController.handleLostRepository( th ) ) {
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage( BaseMessages.getString( PKG, th.getLocalizedMessage() ) );
messageBox.open();
}
}
}
protected void renameRepositoryObject( final UIRepositoryObject object ) throws XulException {
XulPromptBox prompt = promptForName( object );
prompt.addDialogCallback( new XulDialogCallback<String>() {
public void onClose( XulComponent component, Status status, String value ) {
if ( status == Status.ACCEPT ) {
try {
object.setName( value );
} catch ( Exception e ) {
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
throw new RuntimeException( e );
}
}
}
}
public void onError( XulComponent component, Throwable err ) {
throw new RuntimeException( err );
}
} );
prompt.open();
}
protected XulPromptBox promptForName( final UIRepositoryObject object ) throws XulException {
XulPromptBox prompt = (XulPromptBox) document.createElement( "promptbox" );
String currentName =
( object == null ) ? BaseMessages.getString( PKG, "BrowserController.NewFolder" ) : object.getName();
prompt.setTitle( BaseMessages.getString( PKG, "BrowserController.Name" ).concat( currentName ) );
prompt.setButtons( new DialogConstant[] { DialogConstant.OK, DialogConstant.CANCEL } );
prompt.setMessage( BaseMessages.getString( PKG, "BrowserController.NameLabel" ).concat( currentName ) );
prompt.setValue( currentName );
return prompt;
}
// Object being dragged from the hierarchical folder tree
public void onDragFromGlobalTree( DropEvent event ) {
event.setAccepted( true );
}
// Object being dragged from the file listing table
public void onDragFromLocalTable( DropEvent event ) {
event.setAccepted( true );
}
public void onDrop( DropEvent event ) {
boolean result = false;
try {
List<Object> dirList = new ArrayList<Object>();
List<UIRepositoryObject> moveList = new ArrayList<UIRepositoryObject>();
UIRepositoryDirectory targetDirectory = null;
if ( event.getDropParent() != null && event.getDropParent() instanceof UIRepositoryDirectory ) {
targetDirectory = (UIRepositoryDirectory) event.getDropParent();
if ( event.getDataTransfer().getData().size() > 0 ) {
for ( Object o : event.getDataTransfer().getData() ) {
if ( o instanceof UIRepositoryObject ) {
moveList.add( (UIRepositoryObject) o );
// Make sure only Folders are copied to the Directory Tree
if ( o instanceof UIRepositoryDirectory ) {
dirList.add( o );
}
result = true;
}
}
}
}
if ( result == true ) {
List<UIRepositoryObject> collisionObjects = new ArrayList<UIRepositoryObject>();
// Check for overwriting
for ( UIRepositoryObject newChild : moveList ) {
for ( UIRepositoryObject currChild : targetDirectory.getRepositoryObjects() ) {
if ( ( currChild instanceof UIRepositoryDirectory ) && ( newChild instanceof UIRepositoryDirectory )
&& ( currChild.getName().equalsIgnoreCase( newChild.getName() ) ) ) {
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage( BaseMessages.getString( PKG,
"BrowseController.UnableToMove.DirectoryAlreadyExists", currChild.getPath() ) );
messageBox.open();
result = false;
break;
} else if ( !( currChild instanceof UIRepositoryDirectory )
&& ( currChild.getType().equalsIgnoreCase( newChild.getType() ) )
&& ( currChild.getName().equalsIgnoreCase( newChild.getName() ) ) ) {
collisionObjects.add( currChild );
}
}
if ( !result ) {
break;
}
}
// Prompt to overwrite
if ( result && collisionObjects.size() > 0 ) {
FileOverwriteDialogController fileOverwriteDialog =
FileOverwriteDialogController.getInstance( getXulDomContainer().getOuterContext() instanceof Shell
? (Shell) getXulDomContainer().getOuterContext() : null, collisionObjects );
fileOverwriteDialog.show();
if ( fileOverwriteDialog.isOverwriteFiles() ) {
// Delete the files before moving
for ( UIRepositoryObject o : collisionObjects ) {
o.delete();
}
} else {
// We are not moving the files
result = false;
}
}
// Make sure we are still moving the files
if ( result ) {
moveFiles( moveList, targetDirectory );
// Set UI objects to appear in folder directory
event.getDataTransfer().setData( dirList );
}
}
} catch ( Exception e ) {
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
result = false;
event.setAccepted( false );
messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) );
messageBox.setMessage(
BaseMessages.getString( PKG, "BrowseController.UnableToMove", e.getLocalizedMessage() ) );
messageBox.open();
}
}
event.setAccepted( result );
}
protected void moveFiles( List<UIRepositoryObject> objects, UIRepositoryDirectory targetDirectory ) throws Exception {
// Perform move
for ( UIRepositoryObject o : objects ) {
o.move( targetDirectory );
}
}
private void messageBox( String message ) {
messageBox( "Dialog.Error", "Dialog.Ok", message );
}
private void messageBox( String title, String acceptLabel, String message ) {
messageBox.setTitle( BaseMessages.getString( PKG, title ) );
messageBox.setAcceptLabel( BaseMessages.getString( PKG, acceptLabel ) );
messageBox.setMessage( message );
messageBox.open();
}
public void onDoubleClick( Object[] selectedItems ) {
openContent( selectedItems );
}
public List<UIRepositoryDirectory> getSelectedFolderItems() {
return selectedFolderItems;
}
public void setSelectedFolderItems( List<UIRepositoryDirectory> selectedFolderItems ) {
if ( !compareFolderList( selectedFolderItems, this.selectedFolderItems ) ) {
List<TYPE> pollResults = pollContextChangeVetoResults();
if ( !contains( TYPE.CANCEL, pollResults ) ) {
this.selectedFolderItems = selectedFolderItems;
setRepositoryDirectories( selectedFolderItems );
} else if ( contains( TYPE.CANCEL, pollResults ) ) {
folderTree.setSelectedItems( this.selectedFolderItems );
fileTable.setSelectedItems( this.selectedFileItems );
}
} else {
setRepositoryDirectories( selectedFolderItems );
}
}
public List<UIRepositoryObject> getSelectedFileItems() {
return selectedFileItems;
}
public void setSelectedFileItems( List<UIRepositoryObject> selectedFileItems ) {
if ( !compareFileList( selectedFileItems, this.selectedFileItems ) ) {
List<TYPE> pollResults = pollContextChangeVetoResults();
if ( !contains( TYPE.CANCEL, pollResults ) ) {
this.selectedFileItems = selectedFileItems;
setRepositoryObjects( selectedFileItems );
setRepositoryItems( selectedFileItems );
} else if ( contains( TYPE.CANCEL, pollResults ) ) {
fileTable.setSelectedItems( this.selectedFileItems );
}
} else {
setRepositoryItems( selectedFileItems );
}
}
public Binding getSelectedItemsBinding() {
return selectedItemsBinding;
}
public void setSelectedItemsBinding( Binding selectedItemsBinding ) {
this.selectedItemsBinding = selectedItemsBinding;
}
public void setRepositoryObjects( List<UIRepositoryObject> selectedFileItems ) {
this.repositoryObjects = selectedFileItems;
firePropertyChange( "repositoryObjects", null, selectedFileItems );
}
public List<UIRepositoryObject> getRepositoryObjects() {
return repositoryObjects;
}
public void setRepositoryItems( List<UIRepositoryObject> selectedItems ) {
this.repositoryItems = selectedItems;
firePropertyChange( "repositoryItems", null, repositoryItems );
}
public List<UIRepositoryObject> getRepositoryItems() {
return repositoryItems;
}
public List<UIRepositoryDirectory> getRepositoryDirectories() {
if ( repositoryDirectories != null && repositoryDirectories.size() == 0 ) {
return null;
}
return repositoryDirectories;
}
public void setRepositoryDirectories( List<UIRepositoryDirectory> selectedFolderItems ) {
List<UIRepositoryDirectory> previousVal = null;
UIRepositoryObjects previousRepoObjects = null;
try {
if ( repositoryDirectories != null && repositoryDirectories.size() > 0 ) {
previousVal = new ArrayList<UIRepositoryDirectory>();
previousVal.addAll( repositoryDirectories );
previousRepoObjects = getSelectedRepoDirChildren();
}
// Remove children listener
if ( this.repositoryDirectories != null && this.repositoryDirectories.size() > 0 ) {
this.repositoryDirectories.get( 0 ).getRepositoryObjects().removePropertyChangeListener( fileChildrenListener );
}
this.repositoryDirectories = selectedFolderItems;
// Add children Listener
if ( this.repositoryDirectories != null && this.repositoryDirectories.size() > 0 ) {
this.repositoryDirectories.get( 0 ).getRepositoryObjects().addPropertyChangeListener( "children",
fileChildrenListener );
}
} catch ( KettleException e ) {
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
throw new RuntimeException( e );
}
}
fireFoldersAndItemsChange( previousVal, previousRepoObjects );
}
public UIRepositoryObjects getSelectedRepoDirChildren() {
UIRepositoryObjects repoObjects = null;
if ( selectedFolderItems != null && selectedFolderItems.size() > 0 ) {
try {
repoObjects = repositoryDirectories.get( 0 ).getRepositoryObjects();
} catch ( KettleException e ) {
// convert to runtime exception so it bubbles up through the UI
if ( mainController == null || !mainController.handleLostRepository( e ) ) {
throw new RuntimeException( e );
}
}
}
return repoObjects;
}
public void addContextChangeVetoer( ContextChangeVetoer listener ) {
if ( contextChangeVetoers == null ) {
contextChangeVetoers = new ContextChangeVetoerCollection();
}
contextChangeVetoers.add( listener );
}
public void removeContextChangeVetoer( ContextChangeVetoer listener ) {
if ( contextChangeVetoers != null ) {
contextChangeVetoers.remove( listener );
}
}
private boolean contains( TYPE type, List<TYPE> typeList ) {
for ( TYPE t : typeList ) {
if ( t.equals( type ) ) {
return true;
}
}
return false;
}
/**
* Fire all current {@link ContextChangeVetoer}. Every one who has added their self as a vetoer has a change to vote
* on what should happen.
*/
List<TYPE> pollContextChangeVetoResults() {
if ( contextChangeVetoers != null ) {
return contextChangeVetoers.fireContextChange();
} else {
List<TYPE> returnValue = new ArrayList<TYPE>();
returnValue.add( TYPE.NO_OP );
return returnValue;
}
}
boolean compareFolderList( List<UIRepositoryDirectory> rd1, List<UIRepositoryDirectory> rd2 ) {
if ( rd1 != null && rd2 != null ) {
if ( rd1.size() != rd2.size() ) {
return false;
}
for ( int i = 0; i < rd1.size(); i++ ) {
if ( rd1.get( i ) != null && rd2.get( i ) != null ) {
if ( !rd1.get( i ).getName().equals( rd2.get( i ).getName() ) ) {
return false;
}
}
}
} else {
return false;
}
return true;
}
boolean compareFileList( List<UIRepositoryObject> ro1, List<UIRepositoryObject> ro2 ) {
if ( ro1 != null && ro2 != null ) {
if ( ro1.size() != ro2.size() ) {
return false;
}
for ( int i = 0; i < ro1.size(); i++ ) {
if ( ro1.get( i ) != null && ro2.get( i ) != null ) {
if ( !ro1.get( i ).getName().equals( ro2.get( i ).getName() ) ) {
return false;
}
}
}
} else {
return false;
}
return true;
}
@VisibleForTesting
void setDirMap( Map<ObjectId, UIRepositoryDirectory> dirMap ) {
this.dirMap = dirMap;
}
@VisibleForTesting
void setFolderTree( XulTree folderTree ) {
this.folderTree = folderTree;
}
@VisibleForTesting
void setRepositoryDirectory( UIRepositoryDirectory repositoryDirectory ) {
this.repositoryDirectory = repositoryDirectory;
}
@VisibleForTesting
void setDirectoryBinding( Binding directoryBinding ) {
this.directoryBinding = directoryBinding;
}
}