Skip to content

Commit

Permalink
[PDI-6567] - Transformation entry in kettle job broken in Spoon if tr…
Browse files Browse the repository at this point in the history
…ansformation is specified by reference and the target is later deleted

- set "deleted" flag correctly
- display nothing, if element is absent or deleted
  • Loading branch information
Andrey Khayrutdinov committed Aug 13, 2015
1 parent ebc71e1 commit 9bdf735
Show file tree
Hide file tree
Showing 12 changed files with 408 additions and 79 deletions.
Expand Up @@ -1925,38 +1925,41 @@ public RepositoryDirectory getUserHomeDirectory() throws KettleException {
public RepositoryObject getObjectInformation( ObjectId objectId, RepositoryObjectType objectType ) throws KettleException { public RepositoryObject getObjectInformation( ObjectId objectId, RepositoryObjectType objectType ) throws KettleException {
try { try {


String name, description, modifiedUser;
Date modifiedDate;
RepositoryDirectoryInterface directory;
long dirId;
switch ( objectType ) { switch ( objectType ) {
case TRANSFORMATION: { case TRANSFORMATION: {
RowMetaAndData row = transDelegate.getTransformation( objectId ); RowMetaAndData row = transDelegate.getTransformation( objectId );
String name = row.getString( KettleDatabaseRepository.FIELD_TRANSFORMATION_NAME, null ); name = row.getString( KettleDatabaseRepository.FIELD_TRANSFORMATION_NAME, null );
String description = row.getString( KettleDatabaseRepository.FIELD_TRANSFORMATION_DESCRIPTION, null ); description = row.getString( KettleDatabaseRepository.FIELD_TRANSFORMATION_DESCRIPTION, null );
String modifiedUser = row.getString( KettleDatabaseRepository.FIELD_TRANSFORMATION_MODIFIED_USER, "-" ); modifiedUser = row.getString( KettleDatabaseRepository.FIELD_TRANSFORMATION_MODIFIED_USER, "-" );
Date modifiedDate = row.getDate( KettleDatabaseRepository.FIELD_TRANSFORMATION_MODIFIED_DATE, null ); modifiedDate = row.getDate( KettleDatabaseRepository.FIELD_TRANSFORMATION_MODIFIED_DATE, null );
long dirId = row.getInteger( KettleDatabaseRepository.FIELD_TRANSFORMATION_ID_DIRECTORY, 0 ); dirId = row.getInteger( KettleDatabaseRepository.FIELD_TRANSFORMATION_ID_DIRECTORY, 0 );
RepositoryDirectoryInterface directory = break;
loadRepositoryDirectoryTree().findDirectory( new LongObjectId( dirId ) );
return new RepositoryObject(
objectId, name, directory, modifiedUser, modifiedDate, objectType, description, false );
} }


case JOB: { case JOB: {
RowMetaAndData row = jobDelegate.getJob( objectId ); RowMetaAndData row = jobDelegate.getJob( objectId );
String name = row.getString( KettleDatabaseRepository.FIELD_JOB_NAME, null ); name = row.getString( KettleDatabaseRepository.FIELD_JOB_NAME, null );
String description = row.getString( KettleDatabaseRepository.FIELD_JOB_DESCRIPTION, null ); description = row.getString( KettleDatabaseRepository.FIELD_JOB_DESCRIPTION, null );
String modifiedUser = row.getString( KettleDatabaseRepository.FIELD_JOB_MODIFIED_USER, "-" ); modifiedUser = row.getString( KettleDatabaseRepository.FIELD_JOB_MODIFIED_USER, "-" );
Date modifiedDate = row.getDate( KettleDatabaseRepository.FIELD_JOB_MODIFIED_DATE, null ); modifiedDate = row.getDate( KettleDatabaseRepository.FIELD_JOB_MODIFIED_DATE, null );
long dirId = row.getInteger( KettleDatabaseRepository.FIELD_JOB_ID_DIRECTORY, 0 ); dirId = row.getInteger( KettleDatabaseRepository.FIELD_JOB_ID_DIRECTORY, 0 );
RepositoryDirectoryInterface directory = break;
loadRepositoryDirectoryTree().findDirectory( new LongObjectId( dirId ) );
return new RepositoryObject(
objectId, name, directory, modifiedUser, modifiedDate, objectType, description, false );
} }
default: default:
throw new KettleException( "Object type " throw new KettleException( "Object type "
+ objectType.getTypeDescription() + objectType.getTypeDescription()
+ " was specified. Only information from transformations and jobs can be retrieved at this time." ); + " was specified. Only information from transformations and jobs can be retrieved at this time." );
// Nothing matches, return null // Nothing matches, return null
} }

boolean isDeleted = ( name == null );
directory = loadRepositoryDirectoryTree().findDirectory( new LongObjectId( dirId ) );
return new RepositoryObject(
objectId, name, directory, modifiedUser, modifiedDate, objectType, description, isDeleted );
} catch ( Exception e ) { } catch ( Exception e ) {
throw new KettleException( "Unable to get object information for object with id=" + objectId, e ); throw new KettleException( "Unable to get object information for object with id=" + objectId, e );
} }
Expand Down
@@ -0,0 +1,193 @@
/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2015 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.repository.kdr;

import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.RowMetaAndData;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.value.ValueMetaFactory;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.RepositoryDirectoryInterface;
import org.pentaho.di.repository.RepositoryObject;
import org.pentaho.di.repository.RepositoryObjectType;
import org.pentaho.di.repository.StringObjectId;
import org.pentaho.di.repository.kdr.delegates.KettleDatabaseRepositoryJobDelegate;
import org.pentaho.di.repository.kdr.delegates.KettleDatabaseRepositoryTransDelegate;

import java.util.LinkedHashMap;
import java.util.Map;

import static java.util.Arrays.asList;
import static org.junit.Assert.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.*;
import static org.pentaho.di.core.row.ValueMetaInterface.TYPE_DATE;
import static org.pentaho.di.core.row.ValueMetaInterface.TYPE_INTEGER;
import static org.pentaho.di.core.row.ValueMetaInterface.TYPE_STRING;
import static org.pentaho.di.repository.RepositoryObjectType.JOB;
import static org.pentaho.di.repository.RepositoryObjectType.TRANSFORMATION;
import static org.pentaho.di.repository.kdr.KettleDatabaseRepositoryBase.*;

/**
* @author Andrey Khayrutdinov
*/
public class KettleDatabaseRepositoryUnitTest {
private static final String ABSENT_ID = "non-existing object";
private static final String EXISTING_ID = "existing object";

@BeforeClass
public static void initKettle() throws Exception {
KettleEnvironment.init();
}


private KettleDatabaseRepository repository;
private RepositoryDirectoryInterface directoryInterface;

@Before
public void setUp() throws Exception {
directoryInterface = mock( RepositoryDirectoryInterface.class );

repository = spy( new KettleDatabaseRepository() );
doReturn( directoryInterface ).when( repository ).loadRepositoryDirectoryTree();
doReturn( directoryInterface )
.when( repository )
.loadRepositoryDirectoryTree( any( RepositoryDirectoryInterface.class ) );
}


@Test
public void getObjectInformation_AbsentJob_IsDeletedFlagSet() throws Exception {
KettleDatabaseRepositoryJobDelegate jobDelegate =
spy( new KettleDatabaseRepositoryJobDelegate( repository ) );

RowMeta meta = createMetaForJob();
doReturn( new RowMetaAndData( meta, new Object[ meta.size() ] ) )
.when( jobDelegate )
.getJob( new StringObjectId( ABSENT_ID ) );

assertIsDeletedSet_ForAbsentObject( null, jobDelegate, JOB );
}

@Test
public void getObjectInformation_AbsentTrans_IsDeletedFlagSet() throws Exception {
KettleDatabaseRepositoryTransDelegate transDelegate =
spy( new KettleDatabaseRepositoryTransDelegate( repository ) );

RowMeta meta = createMetaForTrans();
doReturn( new RowMetaAndData( meta, new Object[ meta.size() ] ) )
.when( transDelegate )
.getTransformation( new StringObjectId( ABSENT_ID ) );

assertIsDeletedSet_ForAbsentObject( transDelegate, null, TRANSFORMATION );
}

private void assertIsDeletedSet_ForAbsentObject( KettleDatabaseRepositoryTransDelegate transDelegate,
KettleDatabaseRepositoryJobDelegate jobDelegate,
RepositoryObjectType objectType )
throws Exception {
repository.transDelegate = transDelegate;
repository.jobDelegate = jobDelegate;

when( directoryInterface.findDirectory( any( ObjectId.class ) ) ).thenReturn( null );

RepositoryObject object = repository.getObjectInformation( new StringObjectId( ABSENT_ID ), objectType );
assertTrue( object.isDeleted() );
}


@Test
public void getObjectInformation_ExistingJob_IsDeletedFlagNotSet() throws Exception {
KettleDatabaseRepositoryJobDelegate jobDelegate =
spy( new KettleDatabaseRepositoryJobDelegate( repository ) );

RowMeta meta = createMetaForJob();
Object[] values = new Object[ meta.size() ];
values[ asList( meta.getFieldNames() ).indexOf( FIELD_JOB_NAME ) ] = EXISTING_ID;
doReturn( new RowMetaAndData( meta, values ) )
.when( jobDelegate )
.getJob( new StringObjectId( EXISTING_ID ) );

assertIsDeletedNotSet_ForExistingObject( null, jobDelegate, JOB );
}

@Test
public void getObjectInformation_ExistingTrans_IsDeletedFlagNotSet() throws Exception {
KettleDatabaseRepositoryTransDelegate transDelegate =
spy( new KettleDatabaseRepositoryTransDelegate( repository ) );

RowMeta meta = createMetaForJob();
Object[] values = new Object[ meta.size() ];
values[ asList( meta.getFieldNames() ).indexOf( FIELD_TRANSFORMATION_NAME ) ] = EXISTING_ID;
doReturn( new RowMetaAndData( meta, values ) )
.when( transDelegate )
.getTransformation( new StringObjectId( EXISTING_ID ) );

assertIsDeletedNotSet_ForExistingObject( transDelegate, null, TRANSFORMATION );
}

private void assertIsDeletedNotSet_ForExistingObject( KettleDatabaseRepositoryTransDelegate transDelegate,
KettleDatabaseRepositoryJobDelegate jobDelegate,
RepositoryObjectType objectType )
throws Exception {
repository.transDelegate = transDelegate;
repository.jobDelegate = jobDelegate;

when( directoryInterface.findDirectory( any( ObjectId.class ) ) ).thenReturn( null );

RepositoryObject object = repository.getObjectInformation( new StringObjectId( EXISTING_ID ), objectType );
assertFalse( object.isDeleted() );
}


private static RowMeta createMetaForJob() throws Exception {
LinkedHashMap<String, Integer> fields = new LinkedHashMap<String, Integer>();
fields.put( FIELD_JOB_NAME, TYPE_STRING );
fields.put( FIELD_JOB_DESCRIPTION, TYPE_STRING );
fields.put( FIELD_JOB_MODIFIED_USER, TYPE_STRING );
fields.put( FIELD_JOB_MODIFIED_DATE, TYPE_DATE );
fields.put( FIELD_JOB_ID_DIRECTORY, TYPE_INTEGER );
return createMeta( fields );
}

private static RowMeta createMetaForTrans() throws Exception {
LinkedHashMap<String, Integer> fields = new LinkedHashMap<String, Integer>();
fields.put( FIELD_TRANSFORMATION_NAME, TYPE_STRING );
fields.put( FIELD_TRANSFORMATION_DESCRIPTION, TYPE_STRING );
fields.put( FIELD_TRANSFORMATION_MODIFIED_USER, TYPE_STRING );
fields.put( FIELD_TRANSFORMATION_MODIFIED_DATE, TYPE_DATE );
fields.put( FIELD_TRANSFORMATION_ID_DIRECTORY, TYPE_INTEGER );
return createMeta( fields );
}

private static RowMeta createMeta( LinkedHashMap<String, Integer> fields ) throws Exception {
RowMeta meta = new RowMeta();
for ( Map.Entry<String, Integer> entry : fields.entrySet() ) {
meta.addValueMeta( ValueMetaFactory.createValueMeta( entry.getKey(), entry.getValue() ) );
}
return meta;
}
}
17 changes: 7 additions & 10 deletions ui/src/org/pentaho/di/ui/job/entries/job/JobEntryJobDialog.java
Expand Up @@ -1238,13 +1238,12 @@ protected void setRadioButtons() {
setActive(); setActive();
} }


private void getByReferenceData( RepositoryElementMetaInterface jobInf ) { private void updateByReferenceField( RepositoryElementMetaInterface element ) {
String path = jobInf.getRepositoryDirectory().getPath(); String path = getPathOf( element );
if ( !path.endsWith( "/" ) ) { if ( path == null ) {
path += "/"; path = "";
} }
path += jobInf.getName(); wbByReference.setText( path );
wByReference.setText( path );
} }


protected void selectJobByReference() { protected void selectJobByReference() {
Expand All @@ -1253,7 +1252,7 @@ protected void selectJobByReference() {
sod.open(); sod.open();
RepositoryElementMetaInterface repositoryObject = sod.getRepositoryObject(); RepositoryElementMetaInterface repositoryObject = sod.getRepositoryObject();
if ( repositoryObject != null ) { if ( repositoryObject != null ) {
getByReferenceData( repositoryObject ); updateByReferenceField( repositoryObject );
referenceObjectId = repositoryObject.getObjectId(); referenceObjectId = repositoryObject.getObjectId();
specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE; specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE;
setRadioButtons(); setRadioButtons();
Expand Down Expand Up @@ -1480,9 +1479,7 @@ public void getData() {
private void getByReferenceData( ObjectId referenceObjectId ) { private void getByReferenceData( ObjectId referenceObjectId ) {
try { try {
RepositoryObject jobInf = rep.getObjectInformation( referenceObjectId, RepositoryObjectType.JOB ); RepositoryObject jobInf = rep.getObjectInformation( referenceObjectId, RepositoryObjectType.JOB );
if ( jobInf != null ) { updateByReferenceField( jobInf );
getByReferenceData( jobInf );
}
} catch ( KettleException e ) { } catch ( KettleException e ) {
new ErrorDialog( shell, new ErrorDialog( shell,
BaseMessages.getString( PKG, "JobEntryJobDialog.Exception.UnableToReferenceObjectId.Title" ), BaseMessages.getString( PKG, "JobEntryJobDialog.Exception.UnableToReferenceObjectId.Title" ),
Expand Down
Expand Up @@ -1264,7 +1264,7 @@ protected void selectTransformationByReference() {
RepositoryElementMetaInterface repositoryObject = sod.getRepositoryObject(); RepositoryElementMetaInterface repositoryObject = sod.getRepositoryObject();
if ( repositoryObject != null ) { if ( repositoryObject != null ) {
specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE; specificationMethod = ObjectLocationSpecificationMethod.REPOSITORY_BY_REFERENCE;
getByReferenceData( repositoryObject ); updateByReferenceField( repositoryObject );
referenceObjectId = repositoryObject.getObjectId(); referenceObjectId = repositoryObject.getObjectId();
setRadioButtons(); setRadioButtons();
} }
Expand Down Expand Up @@ -1490,23 +1490,20 @@ public void getData() {
private void getByReferenceData( ObjectId transObjectId ) { private void getByReferenceData( ObjectId transObjectId ) {
try { try {
RepositoryObject transInf = rep.getObjectInformation( transObjectId, RepositoryObjectType.TRANSFORMATION ); RepositoryObject transInf = rep.getObjectInformation( transObjectId, RepositoryObjectType.TRANSFORMATION );
if ( transInf != null ) { updateByReferenceField( transInf );
getByReferenceData( transInf );
}
} catch ( KettleException e ) { } catch ( KettleException e ) {
new ErrorDialog( shell, new ErrorDialog( shell,
BaseMessages.getString( PKG, "JobEntryTransDialog.Exception.UnableToReferenceObjectId.Title" ), BaseMessages.getString( PKG, "JobEntryTransDialog.Exception.UnableToReferenceObjectId.Title" ),
BaseMessages.getString( PKG, "JobEntryTransDialog.Exception.UnableToReferenceObjectId.Message" ), e ); BaseMessages.getString( PKG, "JobEntryTransDialog.Exception.UnableToReferenceObjectId.Message" ), e );
} }
} }


private void getByReferenceData( RepositoryElementMetaInterface transInf ) { private void updateByReferenceField( RepositoryElementMetaInterface element ) {
String path = transInf.getRepositoryDirectory().getPath(); String path = getPathOf( element );
if ( !path.endsWith( "/" ) ) { if ( path == null ) {
path += "/"; path = "";
} }
path += transInf.getName(); wbByReference.setText( path );
wByReference.setText( path );
} }


private void cancel() { private void cancel() {
Expand Down
5 changes: 5 additions & 0 deletions ui/src/org/pentaho/di/ui/job/entry/JobEntryDialog.java
Expand Up @@ -42,10 +42,12 @@
import org.pentaho.di.job.JobMeta; import org.pentaho.di.job.JobMeta;
import org.pentaho.di.job.entry.JobEntryInterface; import org.pentaho.di.job.entry.JobEntryInterface;
import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.Repository;
import org.pentaho.di.repository.RepositoryElementMetaInterface;
import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.ui.core.PropsUI; import org.pentaho.di.ui.core.PropsUI;
import org.pentaho.di.ui.core.database.dialog.DatabaseDialog; import org.pentaho.di.ui.core.database.dialog.DatabaseDialog;
import org.pentaho.di.ui.core.database.wizard.CreateDatabaseWizard; import org.pentaho.di.ui.core.database.wizard.CreateDatabaseWizard;
import org.pentaho.di.ui.util.DialogUtils;
import org.pentaho.metastore.api.IMetaStore; import org.pentaho.metastore.api.IMetaStore;


/** /**
Expand Down Expand Up @@ -319,4 +321,7 @@ public void setMetaStore( IMetaStore metaStore ) {
this.metaStore = metaStore; this.metaStore = metaStore;
} }


protected String getPathOf( RepositoryElementMetaInterface object ) {
return DialogUtils.getPathOf( object );
}
} }
6 changes: 6 additions & 0 deletions ui/src/org/pentaho/di/ui/trans/step/BaseStepDialog.java
Expand Up @@ -67,6 +67,7 @@
import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.laf.BasePropertyHandler; import org.pentaho.di.laf.BasePropertyHandler;
import org.pentaho.di.repository.Repository; import org.pentaho.di.repository.Repository;
import org.pentaho.di.repository.RepositoryElementMetaInterface;
import org.pentaho.di.trans.TransMeta; import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStepMeta; import org.pentaho.di.trans.step.BaseStepMeta;
import org.pentaho.di.trans.step.StepInterface; import org.pentaho.di.trans.step.StepInterface;
Expand All @@ -82,6 +83,7 @@
import org.pentaho.di.ui.core.gui.WindowProperty; import org.pentaho.di.ui.core.gui.WindowProperty;
import org.pentaho.di.ui.core.widget.ComboVar; import org.pentaho.di.ui.core.widget.ComboVar;
import org.pentaho.di.ui.core.widget.TableView; import org.pentaho.di.ui.core.widget.TableView;
import org.pentaho.di.ui.util.DialogUtils;
import org.pentaho.di.ui.util.HelpUtils; import org.pentaho.di.ui.util.HelpUtils;
import org.pentaho.metastore.api.IMetaStore; import org.pentaho.metastore.api.IMetaStore;


Expand Down Expand Up @@ -1415,4 +1417,8 @@ public IMetaStore getMetaStore() {
public void setMetaStore( IMetaStore metaStore ) { public void setMetaStore( IMetaStore metaStore ) {
this.metaStore = metaStore; this.metaStore = metaStore;
} }

protected String getPathOf( RepositoryElementMetaInterface object ) {
return DialogUtils.getPathOf( object );
}
} }

0 comments on commit 9bdf735

Please sign in to comment.