/*! * Copyright 2010 - 2015 Pentaho Corporation. All rights reserved. * * 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.pur.repositoryexplorer.controller; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.List; import java.util.ResourceBundle; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.repository.Repository; import org.pentaho.di.ui.repository.pur.repositoryexplorer.ILockObject; import org.pentaho.di.ui.repository.pur.repositoryexplorer.IRevisionObject; import org.pentaho.di.ui.repository.pur.repositoryexplorer.IUIEEUser; import org.pentaho.di.ui.repository.pur.repositoryexplorer.model.UIRepositoryObjectRevision; import org.pentaho.di.ui.repository.pur.repositoryexplorer.model.UIRepositoryObjectRevisions; import org.pentaho.di.ui.repository.repositoryexplorer.ControllerInitializationException; import org.pentaho.di.ui.repository.repositoryexplorer.IUISupportController; import org.pentaho.di.ui.repository.repositoryexplorer.RepositoryExplorerCallback; import org.pentaho.di.ui.repository.repositoryexplorer.controllers.BrowseController; import org.pentaho.di.ui.repository.repositoryexplorer.controllers.MainController; 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.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.binding.DefaultBindingFactory; import org.pentaho.ui.xul.components.XulMessageBox; import org.pentaho.ui.xul.components.XulPromptBox; import org.pentaho.ui.xul.components.XulTab; import org.pentaho.ui.xul.containers.XulTabbox; import org.pentaho.ui.xul.containers.XulTree; import org.pentaho.ui.xul.impl.AbstractXulEventHandler; import org.pentaho.ui.xul.swt.custom.DialogConstant; import org.pentaho.ui.xul.util.XulDialogCallback; public class RevisionController extends AbstractXulEventHandler implements IUISupportController, java.io.Serializable { private static final long serialVersionUID = 4072800373062217146L; /* EESOURCE: UPDATE SERIALVERUID */ private static final Class<?> PKG = IUIEEUser.class; private static final String OPEN_REVISION_BUTTON = "revision-open"; private static final String RESTORE_REVISION_BUTTON = "revision-restore"; protected XulTree folderTree; protected XulTree fileTable; protected XulTab historyTab; protected Repository repository; protected XulTree revisionTable; protected MainController mainController; protected BrowseController browseController; protected BindingFactory bf; protected XulTabbox filePropertiesTabbox; protected RepositoryExplorerCallback callback; protected UIRepositoryObjectRevisions revisions; protected Binding revisionBinding; protected boolean masterVersioningEnabled = true; protected boolean masterCommentsEnabled = true; private XulMessageBox messageBox; protected ResourceBundle messages = new ResourceBundle() { @Override public Enumeration<String> getKeys() { return null; } @Override protected Object handleGetObject( String key ) { return BaseMessages.getString( PKG, key ); } }; public RevisionController() { super(); // TODO Auto-generated constructor stub } public void init( Repository repository ) throws ControllerInitializationException { try { this.repository = repository; mainController = (MainController) this.getXulDomContainer().getEventHandler( "mainController" ); //$NON-NLS-1$ browseController = (BrowseController) this.getXulDomContainer().getEventHandler( "browseController" ); //$NON-NLS-1$ bf = new DefaultBindingFactory(); bf.setDocument( this.getXulDomContainer().getDocumentRoot() ); messageBox = (XulMessageBox) document.createElement( "messagebox" ); //$NON-NLS-1$ createBindings(); } catch ( Exception e ) { if ( mainController == null || !mainController.handleLostRepository( e ) ) { throw new ControllerInitializationException( e ); } } } private void createBindings() { filePropertiesTabbox = (XulTabbox) document.getElementById( "file-properties-tabs" ); //$NON-NLS-1$ historyTab = (XulTab) document.getElementById( "history" ); //$NON-NLS-1$ revisionTable = (XulTree) document.getElementById( "revision-table" ); //$NON-NLS-1$ folderTree = (XulTree) document.getElementById( "folder-tree" ); //$NON-NLS-1$ fileTable = (XulTree) document.getElementById( "file-table" ); //$NON-NLS-1$ // Hide the history tab if versioning is off historyTab.setVisible( false ); bf.setBindingType( Binding.Type.ONE_WAY ); BindingConvertor<int[], Boolean> forButtons = new BindingConvertor<int[], Boolean>() { @Override public Boolean sourceToTarget( int[] value ) { return value != null && !( value.length <= 0 ); } @Override public int[] targetToSource( Boolean value ) { return null; } }; Binding openButtonBinding = bf.createBinding( revisionTable, "selectedRows", OPEN_REVISION_BUTTON, "!disabled", forButtons ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Binding restoreButtonBinding = bf.createBinding( revisionTable, "selectedRows", RESTORE_REVISION_BUTTON, "!disabled", forButtons ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ bf.setBindingType( Binding.Type.ONE_WAY ); bf.createBinding( folderTree, "selectedItems", this, "historyTabVisibility" ); //$NON-NLS-1$ //$NON-NLS-2$ revisionBinding = bf.createBinding( this, "revisionObjects", revisionTable, "elements" ); //$NON-NLS-1$ //$NON-NLS-2$ revisionBinding = bf.createBinding( browseController, "repositoryItems", this, "revisionObjects", //$NON-NLS-1$ //$NON-NLS-2$ new BindingConvertor<List<UIRepositoryObject>, UIRepositoryObjectRevisions>() { private void disableButtons() { document.getElementById( OPEN_REVISION_BUTTON ).setDisabled( true ); document.getElementById( RESTORE_REVISION_BUTTON ).setDisabled( true ); } @Override public UIRepositoryObjectRevisions sourceToTarget( List<UIRepositoryObject> ro ) { if ( ro == null || ro.isEmpty() || !masterVersioningEnabled ) { return new UIRepositoryObjectRevisions(); } if ( ro.get( 0 ) instanceof UIRepositoryDirectory ) { historyTab.setVisible( false ); filePropertiesTabbox.setSelectedIndex( 0 ); disableButtons(); return null; } UIRepositoryObjectRevisions revisions = null; try { UIRepositoryContent rc = (UIRepositoryContent) ro.get( 0 ); if ( rc instanceof IRevisionObject ) { Boolean versioningEnabled = ( (IRevisionObject) rc ).getVersioningEnabled(); // Show/hide the Verison History tab historyTab.setVisible( versioningEnabled ); if ( !versioningEnabled ) { return new UIRepositoryObjectRevisions(); } Boolean versionCommentEnabled = ( (IRevisionObject) rc ).getVersionCommentEnabled(); // Show/Hide the version comment column setRevisionTableColumns( versionCommentEnabled ); revisions = ( (IRevisionObject) rc ).getRevisions(); } else { throw new IllegalStateException( BaseMessages.getString( PKG, "RevisionsController.RevisionsNotSupported" ) ); //$NON-NLS-1$ } } catch ( KettleException e ) { if ( mainController == null || !mainController.handleLostRepository( e ) ) { // convert to runtime exception so it bubbles up through the UI throw new RuntimeException( e ); } } return revisions; } @Override public List<UIRepositoryObject> targetToSource( UIRepositoryObjectRevisions elements ) { return null; } } ); try { openButtonBinding.fireSourceChanged(); restoreButtonBinding.fireSourceChanged(); revisionBinding.fireSourceChanged(); } catch ( Exception e ) { if ( mainController == null || !mainController.handleLostRepository( e ) ) { // convert to runtime exception so it bubbles up through the UI throw new RuntimeException( e ); } } } public void setRevisionObjects( UIRepositoryObjectRevisions revisions ) { this.revisions = revisions; this.firePropertyChange( "revisionObjects", null, revisions ); } public UIRepositoryObjectRevisions getRevisionObjects() { return revisions; } public String getName() { return "revisionController"; //$NON-NLS-1$ } public <T> void setHistoryTabVisibility( Collection<T> items ) { historyTab.setVisible( false ); filePropertiesTabbox.setSelectedIndex( 0 ); } public RepositoryExplorerCallback getCallback() { return callback; } public void setCallback( RepositoryExplorerCallback callback ) { this.callback = callback; } public void openRevision() { Collection<UIRepositoryContent> content = fileTable.getSelectedItems(); UIRepositoryContent contentToOpen = content.iterator().next(); Collection<UIRepositoryObjectRevision> revision = revisionTable.getSelectedItems(); // TODO: Is it a requirement to allow opening multiple revisions? UIRepositoryObjectRevision revisionToOpen = revision.iterator().next(); if ( mainController != null && mainController.getCallback() != null ) { try { if ( mainController.getCallback().open( contentToOpen, revisionToOpen.getName() ) ) { // TODO: fire request to close dialog } } catch ( Exception e ) { if ( mainController != null ) { mainController.handleLostRepository( e ); } } } } public void restoreRevision() { try { final Collection<UIRepositoryContent> content = fileTable.getSelectedItems(); final UIRepositoryContent contentToRestore = content.iterator().next(); Collection<UIRepositoryObjectRevision> versions = revisionTable.getSelectedItems(); final UIRepositoryObjectRevision versionToRestore = versions.iterator().next(); XulPromptBox commitPrompt = promptCommitComment( document, messages, null ); if ( contentToRestore instanceof ILockObject && ( (ILockObject) contentToRestore ).isLocked() ) { // Cannot restore revision of locked content messageBox.setTitle( BaseMessages.getString( PKG, "Dialog.Error" ) ); //$NON-NLS-1$ messageBox.setAcceptLabel( BaseMessages.getString( PKG, "Dialog.Ok" ) ); //$NON-NLS-1$ messageBox.setMessage( BaseMessages.getString( PKG, "RevisionsController.RestoreLockedFileNotAllowed" ) ); //$NON-NLS-1$ messageBox.open(); return; } commitPrompt.addDialogCallback( new XulDialogCallback<String>() { public void onClose( XulComponent component, Status status, String value ) { if ( !status.equals( Status.CANCEL ) ) { try { if ( contentToRestore instanceof IRevisionObject ) { ( (IRevisionObject) contentToRestore ).restoreRevision( versionToRestore, value ); List<UIRepositoryObject> objects = new ArrayList<UIRepositoryObject>(); objects.add( contentToRestore ); browseController.setRepositoryObjects( objects ); } else { throw new IllegalStateException( BaseMessages.getString( PKG, "RevisionsController.RevisionsNotSupported" ) ); //$NON-NLS-1$ } } catch ( Exception e ) { if ( mainController == null || !mainController.handleLostRepository( e ) ) { // convert to runtime exception so it bubbles up through the UI throw new RuntimeException( e ); } } } } public void onError( XulComponent component, Throwable err ) { if ( mainController == null || !mainController.handleLostRepository( err ) ) { throw new RuntimeException( err ); } } } ); commitPrompt.open(); } catch ( Exception e ) { if ( mainController == null || !mainController.handleLostRepository( e ) ) { throw new RuntimeException( new KettleException( e ) ); } } } private XulPromptBox promptCommitComment( org.pentaho.ui.xul.dom.Document document, ResourceBundle messages, String defaultMessage ) throws XulException { XulPromptBox prompt = (XulPromptBox) document.createElement( "promptbox" ); //$NON-NLS-1$ prompt.setTitle( BaseMessages.getString( PKG, "RepositoryExplorer.CommitTitle" ) ); //$NON-NLS-1$ prompt.setButtons( new DialogConstant[] { DialogConstant.OK, DialogConstant.CANCEL } ); prompt.setMessage( BaseMessages.getString( PKG, "RepositoryExplorer.CommitLabel" ) ); //$NON-NLS-1$ prompt.setValue( defaultMessage == null ? BaseMessages.getString( PKG, "RepositoryExplorer.DefaultCommitMessage" ) : defaultMessage ); //$NON-NLS-1$ return prompt; } private void setRevisionTableColumns( Boolean versionCommentEnabled ) { if ( versionCommentEnabled ) { revisionTable.getColumns().getColumn( 2 ).setHidden( false ); } else { revisionTable.getColumns().getColumn( 2 ).setHidden( true ); } } }