/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * 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.kie.workbench.common.screens.datasource.management.client.dbexplorer.dbobjects; import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; import javax.enterprise.context.Dependent; import javax.inject.Inject; import com.google.gwt.view.client.AsyncDataProvider; import com.google.gwt.view.client.HasData; import org.jboss.errai.bus.client.api.messaging.Message; import org.jboss.errai.common.client.api.Caller; import org.jboss.errai.common.client.api.IsElement; import org.jboss.errai.common.client.api.RemoteCallback; import org.jboss.errai.common.client.dom.HTMLElement; import org.jboss.errai.ui.client.local.spi.TranslationService; import org.kie.workbench.common.screens.datasource.management.client.resources.i18n.DataSourceManagementConstants; import org.kie.workbench.common.screens.datasource.management.client.util.InitializeCallback; import org.kie.workbench.common.screens.datasource.management.metadata.DatabaseMetadata; import org.kie.workbench.common.screens.datasource.management.metadata.SchemaMetadata; import org.kie.workbench.common.screens.datasource.management.metadata.TableMetadata; import org.kie.workbench.common.screens.datasource.management.service.DatabaseMetadataService; import org.uberfire.commons.data.Pair; import org.uberfire.ext.widgets.common.client.callbacks.HasBusyIndicatorDefaultErrorCallback; @Dependent public class DatabaseObjectExplorer implements DatabaseObjectExplorerView.Presenter, IsElement { private DatabaseObjectExplorerView view; private Caller< DatabaseMetadataService > metadataService; private AsyncDataProvider< DatabaseObjectRow > dataProvider; private TranslationService translationService; private List< DatabaseObjectRow > rows = new ArrayList<>( ); private Settings settings; private DatabaseObjectExplorerView.Handler handler; protected static final DatabaseMetadata.TableType[] availableSearchTypes = new DatabaseMetadata.TableType[] { DatabaseMetadata.TableType.VIEW, DatabaseMetadata.TableType.TABLE }; public DatabaseObjectExplorer( ) { } @Inject public DatabaseObjectExplorer( DatabaseObjectExplorerView view, Caller< DatabaseMetadataService > metadataService, TranslationService translationService ) { this.view = view; view.init( this ); this.metadataService = metadataService; this.translationService = translationService; } @Override public HTMLElement getElement( ) { return view.getElement( ); } @PostConstruct protected void init( ) { setObjectOptions( ); dataProvider = new AsyncDataProvider< DatabaseObjectRow >( ) { @Override protected void onRangeChanged( HasData< DatabaseObjectRow > display ) { updateRowCount( rows.size( ), true ); updateRowData( 0, rows ); } }; view.setDataProvider( dataProvider ); } public void initialize( Settings settings ) { initialize( settings, null ); } public void initialize( Settings settings, InitializeCallback initializeCallback ) { this.settings = settings; view.showSchemaSelector( settings.isShowSchemaSelection( ) ); view.showObjectTypeFilter( settings.isShowObjectTypeFilter( ) ); view.showObjectNameFilter( settings.isShowObjectNameFilter( ) ); boolean hasFilter = settings.isShowSchemaSelection( ) || settings.isShowObjectTypeFilter( ) || settings.isShowObjectNameFilter( ); view.showFilterButton( hasFilter ); view.showHeaderPanel( hasFilter ); if ( settings.isShowSchemaSelection( ) ) { loadSchemas( settings.dataSourceUuid( ), settings.schemaName( ), initializeCallback ); } else { search( settings.dataSourceUuid( ), settings.schemaName( ), DatabaseMetadata.TableType.ALL.name( ), "%", initializeCallback ); } } public void addHandler( DatabaseObjectExplorerView.Handler handler ) { this.handler = handler; } @Override public void onSearch( ) { search( settings.dataSourceUuid( ), getSchema( ), view.getObjectType( ), view.getFilterTerm( ) ); } @Override public void onOpen( DatabaseObjectRow row ) { handler.onOpen( getSchema( ), row.getName( ) ); } /** * Intended for helping testing. */ protected List< DatabaseObjectRow > getItems() { return rows; } private String getSchema( ) { if ( settings.isShowSchemaSelection( ) ) { return view.getSchema( ); } else { return settings.schemaName( ); } } private void clear( ) { rows.clear( ); refreshRows( ); } private void refreshRows( ) { dataProvider.updateRowCount( rows.size( ), true ); dataProvider.updateRowData( 0, rows ); view.redraw( ); } private void loadSchemas( String dataSourceUuid, String selectedSchema, InitializeCallback initializeCallback ) { view.showBusyIndicator( translationService.getTranslation( DataSourceManagementConstants.DatabaseObjectExplorerViewImpl_loadingDbSchemas ) ); metadataService.call( getLoadSchemasSuccessCallback( selectedSchema, initializeCallback ), new HasBusyIndicatorDefaultErrorCallback( view ) { @Override public boolean error( Message message, Throwable throwable ) { boolean result = super.error( message, throwable ); if ( initializeCallback != null ) { initializeCallback.onInitializeError( throwable ); } return result; } } ).getMetadata( dataSourceUuid, false, true ); } private RemoteCallback< DatabaseMetadata > getLoadSchemasSuccessCallback( String selectedSchema, InitializeCallback initializeCallback ) { return new RemoteCallback< DatabaseMetadata >( ) { @Override public void callback( DatabaseMetadata metadata ) { view.hideBusyIndicator( ); String currentSchema = selectedSchema; if ( currentSchema == null && !metadata.getSchemas( ).isEmpty( ) ) { currentSchema = metadata.getSchemas( ).get( 0 ).getSchemaName( ); } loadSchemas( metadata, currentSchema ); search( settings.dataSourceUuid( ), currentSchema, DatabaseMetadata.TableType.ALL.name( ), "%", initializeCallback ); } }; } private void loadSchemas( DatabaseMetadata metadata, String selectedSchema ) { String currentSchema = null; List< Pair< String, String > > options = new ArrayList<>( ); for ( SchemaMetadata schemaMetadata : metadata.getSchemas( ) ) { if ( schemaMetadata.getSchemaName( ).equals( selectedSchema ) ) { currentSchema = selectedSchema; } options.add( new Pair<>( schemaMetadata.getSchemaName( ), schemaMetadata.getSchemaName( ) ) ); } if ( currentSchema == null && !metadata.getSchemas( ).isEmpty( ) ) { currentSchema = metadata.getSchemas( ).get( 0 ).getSchemaName( ); } view.loadSchemaOptions( options, currentSchema ); } private void search( String dataSource, String schema, String databaseObjectType, String searchTerm ) { search( dataSource, schema, databaseObjectType, searchTerm, null ); } private void search( String dataSource, String schema, String databaseObjectType, String searchTerm, InitializeCallback initializeCallback ) { clear( ); view.showBusyIndicator( translationService.getTranslation( DataSourceManagementConstants.DatabaseObjectExplorerViewImpl_loadingDbObjects ) ); metadataService.call( getSearchSuccessCallback( initializeCallback ), new HasBusyIndicatorDefaultErrorCallback( view ) { @Override public boolean error( Message message, Throwable throwable ) { boolean result = super.error( message, throwable ); if ( initializeCallback != null ) { initializeCallback.onInitializeError( throwable ); } return result; } } ).findTables( dataSource, schema, buildSearchTerm( searchTerm ), buildSearchType( view.getObjectType() ) ); } private RemoteCallback< List< TableMetadata > > getSearchSuccessCallback( InitializeCallback initializeCallback ) { return new RemoteCallback< List< TableMetadata > >( ) { @Override public void callback( List< TableMetadata > response ) { view.hideBusyIndicator( ); loadTables( response ); if ( initializeCallback != null ) { initializeCallback.onInitializeSuccess( ); } } }; } private void loadTables( List< TableMetadata > response ) { rows.clear( ); for ( TableMetadata metadata : response ) { rows.add( new DatabaseObjectRow( metadata.getTableName( ), metadata.getTableType( ) ) ); } refreshRows( ); } private void setObjectOptions( ) { List< Pair< String, String > > options = new ArrayList<>( ); options.add( new Pair<>( DatabaseMetadata.TableType.ALL.name( ), DatabaseMetadata.TableType.ALL.name( ) ) ); options.add( new Pair<>( DatabaseMetadata.TableType.TABLE.name( ), DatabaseMetadata.TableType.TABLE.name( ) ) ); options.add( new Pair<>( DatabaseMetadata.TableType.VIEW.name( ), DatabaseMetadata.TableType.VIEW.name( ) ) ); view.loadDatabaseObjectTypeOptions( options ); } private String buildSearchTerm( String searchTerm ) { if ( searchTerm == null || searchTerm.trim( ).isEmpty( ) ) { return "%"; } else { return "%" + searchTerm.trim( ) + "%"; } } private DatabaseMetadata.TableType[] buildSearchType( String searchType ) { if ( searchType == null || DatabaseMetadata.TableType.ALL.name().equals( searchType ) ) { return availableSearchTypes; } else { return new DatabaseMetadata.TableType[] { DatabaseMetadata.TableType.valueOf( searchType ) }; } } public static class Settings { /** * Configures the data source that will be explored. */ private String dataSourceUuid; /** * When set it's the pre-configured database schema, otherwise the first available schema will be set. */ private String schemaName; /** * Indicates if the schema selector should be visible. */ private boolean showSchemaSelection; /** * When true the filtering of data objects by type is available. */ private boolean showObjectTypeFilter; /** * When true the filtering of data objects by name is available. */ private boolean showObjectNameFilter; public Settings( ) { } public String dataSourceUuid( ) { return dataSourceUuid; } public Settings dataSourceUuid( String selectedDataSourceUuid ) { this.dataSourceUuid = selectedDataSourceUuid; return this; } public String schemaName( ) { return schemaName; } public Settings schemaName( String schemaName ) { this.schemaName = schemaName; return this; } public boolean isShowSchemaSelection( ) { return showSchemaSelection; } public Settings showSchemaSelection( boolean showSchemaSelection ) { this.showSchemaSelection = showSchemaSelection; return this; } public boolean isShowObjectTypeFilter( ) { return showObjectTypeFilter; } public Settings showObjectTypeFilter( boolean showObjectTypeFilter ) { this.showObjectTypeFilter = showObjectTypeFilter; return this; } public boolean isShowObjectNameFilter( ) { return showObjectNameFilter; } public Settings showObjectNameFilter( boolean showObjectNameFilter ) { this.showObjectNameFilter = showObjectNameFilter; return this; } @Override public boolean equals( Object o ) { if ( this == o ) return true; if ( o == null || getClass( ) != o.getClass( ) ) return false; Settings settings = ( Settings ) o; if ( showSchemaSelection != settings.showSchemaSelection ) return false; if ( showObjectTypeFilter != settings.showObjectTypeFilter ) return false; if ( showObjectNameFilter != settings.showObjectNameFilter ) return false; if ( dataSourceUuid != null ? !dataSourceUuid.equals( settings.dataSourceUuid ) : settings.dataSourceUuid != null ) return false; return schemaName != null ? schemaName.equals( settings.schemaName ) : settings.schemaName == null; } @Override public int hashCode( ) { int result = dataSourceUuid != null ? dataSourceUuid.hashCode( ) : 0; result = ~~result; result = 31 * result + ( schemaName != null ? schemaName.hashCode( ) : 0 ); result = ~~result; result = 31 * result + ( showSchemaSelection ? 1 : 0 ); result = ~~result; result = 31 * result + ( showObjectTypeFilter ? 1 : 0 ); result = ~~result; result = 31 * result + ( showObjectNameFilter ? 1 : 0 ); result = ~~result; return result; } } }