/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 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.trans.step;
import java.util.List;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettlePluginException;
import org.pentaho.di.core.plugins.PartitionerPluginType;
import org.pentaho.di.core.plugins.PluginInterface;
import org.pentaho.di.core.plugins.PluginRegistry;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.core.xml.XMLInterface;
import org.pentaho.di.partition.PartitionSchema;
import org.pentaho.di.trans.Partitioner;
import org.w3c.dom.Node;
public class StepPartitioningMeta implements XMLInterface, Cloneable {
public static final int PARTITIONING_METHOD_NONE = 0;
public static final int PARTITIONING_METHOD_MIRROR = 1;
public static final int PARTITIONING_METHOD_SPECIAL = 2;
public static final String[] methodCodes = new String[] { "none", "Mirror", };
public static final String[] methodDescriptions = new String[] { "None", "Mirror to all partitions" };
private int methodType;
private String method;
private String partitionSchemaName; // to allow delayed binding...
private PartitionSchema partitionSchema;
private Partitioner partitioner;
private boolean hasChanged = false;
public StepPartitioningMeta() {
method = "none";
methodType = PARTITIONING_METHOD_NONE;
partitionSchema = new PartitionSchema();
hasChanged = false;
}
/**
* @param method
* @param partitionSchema
*/
public StepPartitioningMeta( String method, PartitionSchema partitionSchema ) throws KettlePluginException {
setMethod( method );
this.partitionSchema = partitionSchema;
hasChanged = false;
}
public StepPartitioningMeta clone() {
try {
StepPartitioningMeta stepPartitioningMeta =
new StepPartitioningMeta( method, partitionSchema != null
? (PartitionSchema) partitionSchema.clone() : null );
stepPartitioningMeta.partitionSchemaName = partitionSchemaName;
stepPartitioningMeta.setMethodType( methodType );
stepPartitioningMeta.setPartitioner( partitioner == null ? null : partitioner.clone() );
return stepPartitioningMeta;
} catch ( KettlePluginException e ) {
throw new RuntimeException( "Unable to load partitioning plugin", e );
}
}
/**
* @return true if the partition schema names are the same.
*/
@Override
public boolean equals( Object obj ) {
if ( obj == null ) {
return false;
}
if ( partitionSchemaName == null ) {
return false;
}
StepPartitioningMeta meta = (StepPartitioningMeta) obj;
if ( meta.partitionSchemaName == null ) {
return false;
}
return partitionSchemaName.equalsIgnoreCase( meta.partitionSchemaName );
}
@Override
public String toString() {
String description;
if ( partitioner != null ) {
description = partitioner.getDescription();
} else {
description = getMethodDescription();
}
if ( partitionSchema != null ) {
description += " / " + partitionSchema.toString();
}
return description;
}
/**
* @return the partitioningMethod
*/
public int getMethodType() {
return methodType;
}
/**
* @param method
* the partitioning method to set
*/
public void setMethod( String method ) throws KettlePluginException {
if ( !method.equals( this.method ) ) {
this.method = method;
createPartitioner( method );
hasChanged = true;
}
}
public String getXML() {
StringBuilder xml = new StringBuilder( 150 );
xml.append( " " ).append( XMLHandler.openTag( "partitioning" ) ).append( Const.CR );
xml.append( " " ).append( XMLHandler.addTagValue( "method", getMethodCode() ) );
xml.append( " " ).append(
XMLHandler.addTagValue( "schema_name", partitionSchema != null ? partitionSchema.getName() : "" ) );
if ( partitioner != null ) {
xml.append( partitioner.getXML() );
}
xml.append( " " ).append( XMLHandler.closeTag( "partitioning" ) ).append( Const.CR );
return xml.toString();
}
public StepPartitioningMeta( Node partitioningMethodNode ) throws KettleException {
this();
setMethod( getMethod( XMLHandler.getTagValue( partitioningMethodNode, "method" ) ) );
partitionSchemaName = XMLHandler.getTagValue( partitioningMethodNode, "schema_name" );
hasChanged = false;
if ( partitioner != null ) {
partitioner.loadXML( partitioningMethodNode );
}
}
public String getMethodCode() {
if ( methodType == PARTITIONING_METHOD_SPECIAL ) {
if ( partitioner != null ) {
return partitioner.getId();
} else {
return methodCodes[PARTITIONING_METHOD_NONE];
}
}
return methodCodes[methodType];
}
public String getMethodDescription() {
if ( methodType != PARTITIONING_METHOD_SPECIAL ) {
return methodDescriptions[methodType];
} else {
return partitioner.getDescription();
}
}
public String getMethod() {
return method;
}
public static final String getMethod( String name ) {
if ( Utils.isEmpty( name ) ) {
return methodCodes[PARTITIONING_METHOD_NONE];
}
for ( int i = 0; i < methodDescriptions.length; i++ ) {
if ( methodDescriptions[i].equalsIgnoreCase( name ) ) {
return methodCodes[i];
}
}
for ( int i = 0; i < methodCodes.length; i++ ) {
if ( methodCodes[i].equalsIgnoreCase( name ) ) {
return methodCodes[i];
}
}
PluginRegistry registry = PluginRegistry.getInstance();
PluginInterface plugin = registry.findPluginWithName( PartitionerPluginType.class, name );
if ( plugin != null ) {
return name;
}
plugin = registry.findPluginWithId( PartitionerPluginType.class, name );
if ( plugin != null ) {
return name;
}
return methodCodes[PARTITIONING_METHOD_NONE];
}
public static final int getMethodType( String description ) {
for ( int i = 0; i < methodDescriptions.length; i++ ) {
if ( methodDescriptions[i].equalsIgnoreCase( description ) ) {
return i;
}
}
for ( int i = 0; i < methodCodes.length; i++ ) {
if ( methodCodes[i].equalsIgnoreCase( description ) ) {
return i;
}
}
PluginInterface plugin =
PluginRegistry.getInstance().findPluginWithId( PartitionerPluginType.class, description );
if ( plugin != null ) {
return PARTITIONING_METHOD_SPECIAL;
}
return PARTITIONING_METHOD_NONE;
}
public boolean isPartitioned() {
return methodType != PARTITIONING_METHOD_NONE;
}
public void setPartitionSchemaName( String partitionSchemaName ) {
this.partitionSchemaName = partitionSchemaName;
}
/**
* @return the partitionSchema
*/
public PartitionSchema getPartitionSchema() {
return partitionSchema;
}
/**
* @param partitionSchema
* the partitionSchema to set
*/
public void setPartitionSchema( PartitionSchema partitionSchema ) {
this.partitionSchema = partitionSchema;
hasChanged = true;
}
/**
* Set the partitioning schema after loading from XML or repository
*
* @param partitionSchemas
* the list of partitioning schemas
*/
public void setPartitionSchemaAfterLoading( List<PartitionSchema> partitionSchemas ) throws KettleException {
partitionSchema = null; // sorry, not found!
for ( int i = 0; i < partitionSchemas.size() && partitionSchema == null; i++ ) {
PartitionSchema schema = partitionSchemas.get( i );
if ( schema.getName().equalsIgnoreCase( partitionSchemaName ) ) {
partitionSchema = schema; // found!
}
}
/*
* if (methodType!=PARTITIONING_METHOD_NONE && partitionSchema==null) { String message =
* "Unable to set partition schema for name ["+partitionSchemaName+"], method: "+getMethodDescription()+Const.CR;
* message += "This is the list of available partition schema:"+Const.CR; for (int i=0;i<partitionSchemas.size() &&
* partitionSchema==null;i++) { PartitionSchema schema = partitionSchemas.get(i);
* message+=" --> "+schema.getName()+Const.CR; } throw new KettleException(message); }
*/
}
public void createPartitioner( String method ) throws KettlePluginException {
methodType = getMethodType( method );
switch ( methodType ) {
case PARTITIONING_METHOD_SPECIAL: {
PluginRegistry registry = PluginRegistry.getInstance();
PluginInterface plugin = registry.findPluginWithId( PartitionerPluginType.class, method );
partitioner = (Partitioner) registry.loadClass( plugin );
partitioner.setId( plugin.getIds()[0] );
break;
}
case PARTITIONING_METHOD_NONE:
default:
partitioner = null;
}
if ( partitioner != null ) {
partitioner.setMeta( this );
}
}
public boolean isMethodMirror() {
return methodType == PARTITIONING_METHOD_MIRROR;
}
public int getPartition( RowMetaInterface rowMeta, Object[] row ) throws KettleException {
if ( partitioner != null ) {
return partitioner.getPartition( rowMeta, row );
}
return 0;
}
public Partitioner getPartitioner() {
return partitioner;
}
public void setPartitioner( Partitioner partitioner ) {
this.partitioner = partitioner;
}
public boolean hasChanged() {
return hasChanged;
}
public void hasChanged( boolean hasChanged ) {
this.hasChanged = hasChanged;
}
public void setMethodType( int methodType ) {
this.methodType = methodType;
}
}