diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..57b6c2d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+.DS_Store
+.classpath
+.project
+.settings/
+target/
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
diff --git a/pentaho-plugin-base/build.xml b/pentaho-plugin-base/build.xml
new file mode 100644
index 0000000..4d6043d
--- /dev/null
+++ b/pentaho-plugin-base/build.xml
@@ -0,0 +1,102 @@
+
+
+
+ Build file for a PDI step plugin
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pentaho-plugin-base/pom.xml b/pentaho-plugin-base/pom.xml
new file mode 100644
index 0000000..462f3a6
--- /dev/null
+++ b/pentaho-plugin-base/pom.xml
@@ -0,0 +1,109 @@
+
+ 4.0.0
+
+ com.ucuenca
+ pentaho-plugin-base
+ 0.0.1-SNAPSHOT
+ jar
+
+ pentaho-plugin-base
+
+
+
+ UTF-8
+
+
+
+
+ default
+ http://repo1.maven.org/maven/
+
+ false
+
+
+
+
+ false
+
+ central
+ repo
+ http://repository.pentaho.org/artifactory/repo
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+ 1.7
+
+
+ deploy-plugin
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ src/main/resources
+
+ plugin/*.*
+
+
+
+ src/main/java
+
+ **/*.properties
+
+
+
+
+
+
+
+ junit
+ junit
+ 3.8.1
+ test
+
+
+
+ pentaho-kettle
+ kettle-core
+ 5.1.preview.506
+
+
+
+ pentaho-kettle
+ kettle-dbdialog
+ 5.1.preview.506
+
+
+
+ pentaho-kettle
+ kettle-engine
+ 5.1.preview.506
+
+
+
+ pentaho-kettle
+ kettle-ui-swt
+ 5.1.preview.506
+
+
+
diff --git a/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStep.java b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStep.java
new file mode 100644
index 0000000..0572602
--- /dev/null
+++ b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStep.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ *
+ * Pentaho Data Integration
+ *
+ * Copyright (C) 2002-2012 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 com.ucuenca.pentaho.plugin.step;
+
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.row.RowDataUtil;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.BaseStep;
+import org.pentaho.di.trans.step.StepDataInterface;
+import org.pentaho.di.trans.step.StepInterface;
+import org.pentaho.di.trans.step.StepMeta;
+import org.pentaho.di.trans.step.StepMetaInterface;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI.
+ *
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *
+ * This class is the implementation of StepInterface.
+ * Classes implementing this interface need to:
+ *
+ * - initialize the step
+ * - execute the row processing logic
+ * - dispose of the step
+ *
+ * Please do not create any local fields in a StepInterface class. Store any
+ * information related to the processing logic in the supplied step data interface
+ * instead.
+ *
+ */
+
+public class DemoStep extends BaseStep implements StepInterface {
+
+ /**
+ * The constructor should simply pass on its arguments to the parent class.
+ *
+ * @param s step description
+ * @param stepDataInterface step data class
+ * @param c step copy
+ * @param t transformation description
+ * @param dis transformation executing
+ */
+ public DemoStep(StepMeta s, StepDataInterface stepDataInterface, int c, TransMeta t, Trans dis) {
+ super(s, stepDataInterface, c, t, dis);
+ }
+
+ /**
+ * This method is called by PDI during transformation startup.
+ *
+ * It should initialize required for step execution.
+ *
+ * The meta and data implementations passed in can safely be cast
+ * to the step's respective implementations.
+ *
+ * It is mandatory that super.init() is called to ensure correct behavior.
+ *
+ * Typical tasks executed here are establishing the connection to a database,
+ * as wall as obtaining resources, like file handles.
+ *
+ * @param smi step meta interface implementation, containing the step settings
+ * @param sdi step data interface implementation, used to store runtime information
+ *
+ * @return true if initialization completed successfully, false if there was an error preventing the step from working.
+ *
+ */
+ public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
+ // Casting to step-specific implementation classes is safe
+ DemoStepMeta meta = (DemoStepMeta) smi;
+ DemoStepData data = (DemoStepData) sdi;
+
+ return super.init(meta, data);
+ }
+
+ /**
+ * Once the transformation starts executing, the processRow() method is called repeatedly
+ * by PDI for as long as it returns true. To indicate that a step has finished processing rows
+ * this method must call setOutputDone() and return false;
+ *
+ * Steps which process incoming rows typically call getRow() to read a single row from the
+ * input stream, change or add row content, call putRow() to pass the changed row on
+ * and return true. If getRow() returns null, no more rows are expected to come in,
+ * and the processRow() implementation calls setOutputDone() and returns false to
+ * indicate that it is done too.
+ *
+ * Steps which generate rows typically construct a new row Object[] using a call to
+ * RowDataUtil.allocateRowData(numberOfFields), add row content, and call putRow() to
+ * pass the new row on. Above process may happen in a loop to generate multiple rows,
+ * at the end of which processRow() would call setOutputDone() and return false;
+ *
+ * @param smi the step meta interface containing the step settings
+ * @param sdi the step data interface that should be used to store
+ *
+ * @return true to indicate that the function should be called again, false if the step is done
+ */
+ public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
+
+ // safely cast the step settings (meta) and runtime info (data) to specific implementations
+ DemoStepMeta meta = (DemoStepMeta) smi;
+ DemoStepData data = (DemoStepData) sdi;
+
+ // get incoming row, getRow() potentially blocks waiting for more rows, returns null if no more rows expected
+ Object[] r = getRow();
+
+ // if no more rows are expected, indicate step is finished and processRow() should not be called again
+ if (r == null){
+ setOutputDone();
+ return false;
+ }
+
+ // the "first" flag is inherited from the base step implementation
+ // it is used to guard some processing tasks, like figuring out field indexes
+ // in the row structure that only need to be done once
+ if (first) {
+ first = false;
+ // clone the input row structure and place it in our data object
+ data.outputRowMeta = (RowMetaInterface) getInputRowMeta().clone();
+ // use meta.getFields() to change it, so it reflects the output row structure
+ meta.getFields(data.outputRowMeta, getStepname(), null, null, this);
+ }
+
+ // safely add the string "Hello World!" at the end of the output row
+ // the row array will be resized if necessary
+ Object[] outputRow = RowDataUtil.addValueData(r, data.outputRowMeta.size() - 1, "Hello World!");
+
+ // put the row to the output row stream
+ putRow(data.outputRowMeta, outputRow);
+
+ // log progress if it is time to to so
+ if (checkFeedback(getLinesRead())) {
+ logBasic("Linenr " + getLinesRead()); // Some basic logging
+ }
+
+ // indicate that processRow() should be called again
+ return true;
+ }
+
+ /**
+ * This method is called by PDI once the step is done processing.
+ *
+ * The dispose() method is the counterpart to init() and should release any resources
+ * acquired for step execution like file handles or database connections.
+ *
+ * The meta and data implementations passed in can safely be cast
+ * to the step's respective implementations.
+ *
+ * It is mandatory that super.dispose() is called to ensure correct behavior.
+ *
+ * @param smi step meta interface implementation, containing the step settings
+ * @param sdi step data interface implementation, used to store runtime information
+ */
+ public void dispose(StepMetaInterface smi, StepDataInterface sdi) {
+
+ // Casting to step-specific implementation classes is safe
+ DemoStepMeta meta = (DemoStepMeta) smi;
+ DemoStepData data = (DemoStepData) sdi;
+
+ super.dispose(meta, data);
+ }
+
+}
diff --git a/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepData.java b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepData.java
new file mode 100644
index 0000000..6f9b930
--- /dev/null
+++ b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepData.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ *
+ * Pentaho Data Integration
+ *
+ * Copyright (C) 2002-2012 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 com.ucuenca.pentaho.plugin.step;
+
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.trans.step.BaseStepData;
+import org.pentaho.di.trans.step.StepDataInterface;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI.
+ *
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *
+ * This class is the implementation of StepDataInterface.
+ *
+ * Implementing classes inherit from BaseStepData, which implements the entire
+ * interface completely.
+ *
+ * In addition classes implementing this interface usually keep track of
+ * per-thread resources during step execution. Typical examples are:
+ * result sets, temporary data, caching indexes, etc.
+ *
+ * The implementation for the demo step stores the output row structure in
+ * the data class.
+ *
+ */
+public class DemoStepData extends BaseStepData implements StepDataInterface {
+
+ public RowMetaInterface outputRowMeta;
+
+ public DemoStepData()
+ {
+ super();
+ }
+}
+
diff --git a/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepDialog.java b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepDialog.java
new file mode 100644
index 0000000..7b83b1b
--- /dev/null
+++ b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepDialog.java
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ *
+ * Pentaho Data Integration
+ *
+ * Copyright (C) 2002-2012 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 com.ucuenca.pentaho.plugin.step;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.ShellAdapter;
+import org.eclipse.swt.events.ShellEvent;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.pentaho.di.core.Const;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.ui.trans.step.BaseStepDialog;
+import org.pentaho.di.trans.step.BaseStepMeta;
+import org.pentaho.di.trans.step.StepDialogInterface;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI.
+ *
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *
+ * This class is the implementation of StepDialogInterface.
+ * Classes implementing this interface need to:
+ *
+ * - build and open a SWT dialog displaying the step's settings (stored in the step's meta object)
+ * - write back any changes the user makes to the step's meta object
+ * - report whether the user changed any settings when confirming the dialog
+ *
+ */
+public class DemoStepDialog extends BaseStepDialog implements StepDialogInterface {
+
+ /**
+ * The PKG member is used when looking up internationalized strings.
+ * The properties file with localized keys is expected to reside in
+ * {the package of the class specified}/messages/messages_{locale}.properties
+ */
+ private static Class> PKG = DemoStepMeta.class; // for i18n purposes
+
+ // this is the object the stores the step's settings
+ // the dialog reads the settings from it when opening
+ // the dialog writes the settings to it when confirmed
+ private DemoStepMeta meta;
+
+ // text field holding the name of the field to add to the row stream
+ private Text wHelloFieldName;
+
+ /**
+ * The constructor should simply invoke super() and save the incoming meta
+ * object to a local variable, so it can conveniently read and write settings
+ * from/to it.
+ *
+ * @param parent the SWT shell to open the dialog in
+ * @param in the meta object holding the step's settings
+ * @param transMeta transformation description
+ * @param sname the step name
+ */
+ public DemoStepDialog(Shell parent, Object in, TransMeta transMeta, String sname) {
+ super(parent, (BaseStepMeta) in, transMeta, sname);
+ meta = (DemoStepMeta) in;
+ }
+
+ /**
+ * This method is called by Spoon when the user opens the settings dialog of the step.
+ * It should open the dialog and return only once the dialog has been closed by the user.
+ *
+ * If the user confirms the dialog, the meta object (passed in the constructor) must
+ * be updated to reflect the new step settings. The changed flag of the meta object must
+ * reflect whether the step configuration was changed by the dialog.
+ *
+ * If the user cancels the dialog, the meta object must not be updated, and its changed flag
+ * must remain unaltered.
+ *
+ * The open() method must return the name of the step after the user has confirmed the dialog,
+ * or null if the user cancelled the dialog.
+ */
+ public String open() {
+
+ // store some convenient SWT variables
+ Shell parent = getParent();
+ Display display = parent.getDisplay();
+
+ // SWT code for preparing the dialog
+ shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
+ props.setLook(shell);
+ setShellImage(shell, meta);
+
+ // Save the value of the changed flag on the meta object. If the user cancels
+ // the dialog, it will be restored to this saved value.
+ // The "changed" variable is inherited from BaseStepDialog
+ changed = meta.hasChanged();
+
+ // The ModifyListener used on all controls. It will update the meta object to
+ // indicate that changes are being made.
+ ModifyListener lsMod = new ModifyListener() {
+ public void modifyText(ModifyEvent e) {
+ meta.setChanged();
+ }
+ };
+
+ // ------------------------------------------------------- //
+ // SWT code for building the actual settings dialog //
+ // ------------------------------------------------------- //
+ FormLayout formLayout = new FormLayout();
+ formLayout.marginWidth = Const.FORM_MARGIN;
+ formLayout.marginHeight = Const.FORM_MARGIN;
+
+ shell.setLayout(formLayout);
+ shell.setText(BaseMessages.getString(PKG, "Demo.Shell.Title"));
+
+ int middle = props.getMiddlePct();
+ int margin = Const.MARGIN;
+
+ // Stepname line
+ wlStepname = new Label(shell, SWT.RIGHT);
+ wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName"));
+ props.setLook(wlStepname);
+ fdlStepname = new FormData();
+ fdlStepname.left = new FormAttachment(0, 0);
+ fdlStepname.right = new FormAttachment(middle, -margin);
+ fdlStepname.top = new FormAttachment(0, margin);
+ wlStepname.setLayoutData(fdlStepname);
+
+ wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ wStepname.setText(stepname);
+ props.setLook(wStepname);
+ wStepname.addModifyListener(lsMod);
+ fdStepname = new FormData();
+ fdStepname.left = new FormAttachment(middle, 0);
+ fdStepname.top = new FormAttachment(0, margin);
+ fdStepname.right = new FormAttachment(100, 0);
+ wStepname.setLayoutData(fdStepname);
+
+ // output field value
+ Label wlValName = new Label(shell, SWT.RIGHT);
+ wlValName.setText(BaseMessages.getString(PKG, "Demo.FieldName.Label"));
+ props.setLook(wlValName);
+ FormData fdlValName = new FormData();
+ fdlValName.left = new FormAttachment(0, 0);
+ fdlValName.right = new FormAttachment(middle, -margin);
+ fdlValName.top = new FormAttachment(wStepname, margin);
+ wlValName.setLayoutData(fdlValName);
+
+ wHelloFieldName = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
+ props.setLook(wHelloFieldName);
+ wHelloFieldName.addModifyListener(lsMod);
+ FormData fdValName = new FormData();
+ fdValName.left = new FormAttachment(middle, 0);
+ fdValName.right = new FormAttachment(100, 0);
+ fdValName.top = new FormAttachment(wStepname, margin);
+ wHelloFieldName.setLayoutData(fdValName);
+
+ // OK and cancel buttons
+ wOK = new Button(shell, SWT.PUSH);
+ wOK.setText(BaseMessages.getString(PKG, "System.Button.OK"));
+ wCancel = new Button(shell, SWT.PUSH);
+ wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));
+
+ BaseStepDialog.positionBottomButtons(shell, new Button[] { wOK, wCancel }, margin, wHelloFieldName);
+
+ // Add listeners for cancel and OK
+ lsCancel = new Listener() {
+ public void handleEvent(Event e) {cancel();}
+ };
+ lsOK = new Listener() {
+ public void handleEvent(Event e) {ok();}
+ };
+
+ wCancel.addListener(SWT.Selection, lsCancel);
+ wOK.addListener(SWT.Selection, lsOK);
+
+ // default listener (for hitting "enter")
+ lsDef = new SelectionAdapter() {
+ public void widgetDefaultSelected(SelectionEvent e) {ok();}
+ };
+ wStepname.addSelectionListener(lsDef);
+ wHelloFieldName.addSelectionListener(lsDef);
+
+ // Detect X or ALT-F4 or something that kills this window and cancel the dialog properly
+ shell.addShellListener(new ShellAdapter() {
+ public void shellClosed(ShellEvent e) {cancel();}
+ });
+
+ // Set/Restore the dialog size based on last position on screen
+ // The setSize() method is inherited from BaseStepDialog
+ setSize();
+
+ // populate the dialog with the values from the meta object
+ populateDialog();
+
+ // restore the changed flag to original value, as the modify listeners fire during dialog population
+ meta.setChanged(changed);
+
+ // open dialog and enter event loop
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+
+ // at this point the dialog has closed, so either ok() or cancel() have been executed
+ // The "stepname" variable is inherited from BaseStepDialog
+ return stepname;
+ }
+
+ /**
+ * This helper method puts the step configuration stored in the meta object
+ * and puts it into the dialog controls.
+ */
+ private void populateDialog() {
+ wStepname.selectAll();
+ wHelloFieldName.setText(meta.getOutputField());
+ }
+
+ /**
+ * Called when the user cancels the dialog.
+ */
+ private void cancel() {
+ // The "stepname" variable will be the return value for the open() method.
+ // Setting to null to indicate that dialog was cancelled.
+ stepname = null;
+ // Restoring original "changed" flag on the met aobject
+ meta.setChanged(changed);
+ // close the SWT dialog window
+ dispose();
+ }
+
+ /**
+ * Called when the user confirms the dialog
+ */
+ private void ok() {
+ // The "stepname" variable will be the return value for the open() method.
+ // Setting to step name from the dialog control
+ stepname = wStepname.getText();
+ // Setting the settings to the meta object
+ meta.setOutputField(wHelloFieldName.getText());
+ // close the SWT dialog window
+ dispose();
+ }
+}
diff --git a/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepMeta.java b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepMeta.java
new file mode 100644
index 0000000..1192701
--- /dev/null
+++ b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/DemoStepMeta.java
@@ -0,0 +1,310 @@
+/*******************************************************************************
+ *
+ * Pentaho Data Integration
+ *
+ * Copyright (C) 2002-2012 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 com.ucuenca.pentaho.plugin.step;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.widgets.Shell;
+import org.pentaho.di.core.CheckResult;
+import org.pentaho.di.core.CheckResultInterface;
+import org.pentaho.di.core.Counter;
+import org.pentaho.di.core.database.DatabaseMeta;
+import org.pentaho.di.core.exception.KettleException;
+import org.pentaho.di.core.exception.KettleValueException;
+import org.pentaho.di.core.exception.KettleXMLException;
+import org.pentaho.di.core.row.RowMetaInterface;
+import org.pentaho.di.core.row.ValueMeta;
+import org.pentaho.di.core.row.ValueMetaInterface;
+import org.pentaho.di.core.variables.VariableSpace;
+import org.pentaho.di.core.xml.XMLHandler;
+import org.pentaho.di.i18n.BaseMessages;
+import org.pentaho.di.repository.ObjectId;
+import org.pentaho.di.repository.Repository;
+import org.pentaho.di.trans.Trans;
+import org.pentaho.di.trans.TransMeta;
+import org.pentaho.di.trans.step.BaseStepMeta;
+import org.pentaho.di.trans.step.StepDataInterface;
+import org.pentaho.di.trans.step.StepDialogInterface;
+import org.pentaho.di.trans.step.StepInterface;
+import org.pentaho.di.trans.step.StepMeta;
+import org.pentaho.di.trans.step.StepMetaInterface;
+import org.w3c.dom.Node;
+
+/**
+ * This class is part of the demo step plug-in implementation.
+ * It demonstrates the basics of developing a plug-in step for PDI.
+ *
+ * The demo step adds a new string field to the row stream and sets its
+ * value to "Hello World!". The user may select the name of the new field.
+ *
+ * This class is the implementation of StepMetaInterface.
+ * Classes implementing this interface need to:
+ *
+ * - keep track of the step settings
+ * - serialize step settings both to xml and a repository
+ * - provide new instances of objects implementing StepDialogInterface, StepInterface and StepDataInterface
+ * - report on how the step modifies the meta-data of the row-stream (row structure and field types)
+ * - perform a sanity-check on the settings provided by the user
+ *
+ */
+public class DemoStepMeta extends BaseStepMeta implements StepMetaInterface {
+
+ /**
+ * The PKG member is used when looking up internationalized strings.
+ * The properties file with localized keys is expected to reside in
+ * {the package of the class specified}/messages/messages_{locale}.properties
+ */
+ private static Class> PKG = DemoStepMeta.class; // for i18n purposes
+
+ /**
+ * Stores the name of the field added to the row-stream.
+ */
+ private String outputField;
+
+ /**
+ * Constructor should call super() to make sure the base class has a chance to initialize properly.
+ */
+ public DemoStepMeta() {
+ super();
+ }
+
+ /**
+ * Called by Spoon to get a new instance of the SWT dialog for the step.
+ * A standard implementation passing the arguments to the constructor of the step dialog is recommended.
+ *
+ * @param shell an SWT Shell
+ * @param meta description of the step
+ * @param transMeta description of the the transformation
+ * @param name the name of the step
+ * @return new instance of a dialog for this step
+ */
+ public StepDialogInterface getDialog(Shell shell, StepMetaInterface meta, TransMeta transMeta, String name) {
+ return new DemoStepDialog(shell, meta, transMeta, name);
+ }
+
+ /**
+ * Called by PDI to get a new instance of the step implementation.
+ * A standard implementation passing the arguments to the constructor of the step class is recommended.
+ *
+ * @param stepMeta description of the step
+ * @param stepDataInterface instance of a step data class
+ * @param cnr copy number
+ * @param transMeta description of the transformation
+ * @param disp runtime implementation of the transformation
+ * @return the new instance of a step implementation
+ */
+ public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta, Trans disp) {
+ return new DemoStep(stepMeta, stepDataInterface, cnr, transMeta, disp);
+ }
+
+ /**
+ * Called by PDI to get a new instance of the step data class.
+ */
+ public StepDataInterface getStepData() {
+ return new DemoStepData();
+ }
+
+ /**
+ * This method is called every time a new step is created and should allocate/set the step configuration
+ * to sensible defaults. The values set here will be used by Spoon when a new step is created.
+ */
+ public void setDefault() {
+ outputField = "demo_field";
+ }
+
+ /**
+ * Getter for the name of the field added by this step
+ * @return the name of the field added
+ */
+ public String getOutputField() {
+ return outputField;
+ }
+
+ /**
+ * Setter for the name of the field added by this step
+ * @param outputField the name of the field added
+ */
+ public void setOutputField(String outputField) {
+ this.outputField = outputField;
+ }
+
+ /**
+ * This method is used when a step is duplicated in Spoon. It needs to return a deep copy of this
+ * step meta object. Be sure to create proper deep copies if the step configuration is stored in
+ * modifiable objects.
+ *
+ * See org.pentaho.di.trans.steps.rowgenerator.RowGeneratorMeta.clone() for an example on creating
+ * a deep copy.
+ *
+ * @return a deep copy of this
+ */
+ public Object clone() {
+ Object retval = super.clone();
+ return retval;
+ }
+
+ /**
+ * This method is called by Spoon when a step needs to serialize its configuration to XML. The expected
+ * return value is an XML fragment consisting of one or more XML tags.
+ *
+ * Please use org.pentaho.di.core.xml.XMLHandler to conveniently generate the XML.
+ *
+ * @return a string containing the XML serialization of this step
+ */
+ public String getXML() throws KettleValueException {
+
+ // only one field to serialize
+ String xml = XMLHandler.addTagValue("outputfield", outputField);
+ return xml;
+ }
+
+ /**
+ * This method is called by PDI when a step needs to load its configuration from XML.
+ *
+ * Please use org.pentaho.di.core.xml.XMLHandler to conveniently read from the
+ * XML node passed in.
+ *
+ * @param stepnode the XML node containing the configuration
+ * @param databases the databases available in the transformation
+ * @param counters the counters available in the transformation
+ */
+ public void loadXML(Node stepnode, List databases, Map counters) throws KettleXMLException {
+
+ try {
+ setOutputField(XMLHandler.getNodeValue(XMLHandler.getSubNode(stepnode, "outputfield")));
+ } catch (Exception e) {
+ throw new KettleXMLException("Demo plugin unable to read step info from XML node", e);
+ }
+
+ }
+ /**
+ * This method is called by Spoon when a step needs to serialize its configuration to a repository.
+ * The repository implementation provides the necessary methods to save the step attributes.
+ *
+ * @param rep the repository to save to
+ * @param id_transformation the id to use for the transformation when saving
+ * @param id_step the id to use for the step when saving
+ */
+ public void saveRep(Repository rep, ObjectId id_transformation, ObjectId id_step) throws KettleException
+ {
+ try{
+ rep.saveStepAttribute(id_transformation, id_step, "outputfield", outputField); //$NON-NLS-1$
+ }
+ catch(Exception e){
+ throw new KettleException("Unable to save step into repository: "+id_step, e);
+ }
+ }
+
+ /**
+ * This method is called by PDI when a step needs to read its configuration from a repository.
+ * The repository implementation provides the necessary methods to read the step attributes.
+ *
+ * @param rep the repository to read from
+ * @param id_step the id of the step being read
+ * @param databases the databases available in the transformation
+ * @param counters the counters available in the transformation
+ */
+ public void readRep(Repository rep, ObjectId id_step, List databases, Map counters) throws KettleException {
+ try{
+ outputField = rep.getStepAttributeString(id_step, "outputfield"); //$NON-NLS-1$
+ }
+ catch(Exception e){
+ throw new KettleException("Unable to load step from repository", e);
+ }
+ }
+
+ /**
+ * This method is called to determine the changes the step is making to the row-stream.
+ * To that end a RowMetaInterface object is passed in, containing the row-stream structure as it is when entering
+ * the step. This method must apply any changes the step makes to the row stream. Usually a step adds fields to the
+ * row-stream.
+ *
+ * @param r the row structure coming in to the step
+ * @param origin the name of the step making the changes
+ * @param info row structures of any info steps coming in
+ * @param nextStep the description of a step this step is passing rows to
+ * @param space the variable space for resolving variables
+ */
+ public void getFields(RowMetaInterface r, String origin, RowMetaInterface[] info, StepMeta nextStep, VariableSpace space) {
+
+ /*
+ * This implementation appends the outputField to the row-stream
+ */
+
+ // a value meta object contains the meta data for a field
+ ValueMetaInterface v = new ValueMeta();
+
+ // set the name of the new field
+ v.setName(outputField);
+
+ // type is going to be string
+ v.setType(ValueMeta.TYPE_STRING);
+
+ // setting trim type to "both"
+ v.setTrimType(ValueMeta.TRIM_TYPE_BOTH);
+
+ // the name of the step that adds this field
+ v.setOrigin(origin);
+
+ // modify the row structure and add the field this step generates
+ r.addValueMeta(v);
+
+ }
+
+ /**
+ * This method is called when the user selects the "Verify Transformation" option in Spoon.
+ * A list of remarks is passed in that this method should add to. Each remark is a comment, warning, error, or ok.
+ * The method should perform as many checks as necessary to catch design-time errors.
+ *
+ * Typical checks include:
+ * - verify that all mandatory configuration is given
+ * - verify that the step receives any input, unless it's a row generating step
+ * - verify that the step does not receive any input if it does not take them into account
+ * - verify that the step finds fields it relies on in the row-stream
+ *
+ * @param remarks the list of remarks to append to
+ * @param transmeta the description of the transformation
+ * @param stepMeta the description of the step
+ * @param prev the structure of the incoming row-stream
+ * @param input names of steps sending input to the step
+ * @param output names of steps this step is sending output to
+ * @param info fields coming in from info steps
+ */
+ public void check(List remarks, TransMeta transmeta, StepMeta stepMeta, RowMetaInterface prev, String input[], String output[], RowMetaInterface info) {
+
+ CheckResult cr;
+
+ // See if there are input streams leading to this step!
+ if (input.length > 0) {
+ cr = new CheckResult(CheckResult.TYPE_RESULT_OK, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.OK"), stepMeta);
+ remarks.add(cr);
+ } else {
+ cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString(PKG, "Demo.CheckResult.ReceivingRows.ERROR"), stepMeta);
+ remarks.add(cr);
+ }
+
+ }
+
+
+}
diff --git a/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/messages/messages_en_US.properties b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/messages/messages_en_US.properties
new file mode 100644
index 0000000..71b0584
--- /dev/null
+++ b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/messages/messages_en_US.properties
@@ -0,0 +1,4 @@
+Demo.Shell.Title=Demo step
+Demo.FieldName.Label=Output field name
+Demo.CheckResult.ReceivingRows.OK=Step is receiving input from other steps.
+Demo.CheckResult.ReceivingRows.ERROR=No input received from other steps!
diff --git a/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/messages/messages_es_ES.properties b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/messages/messages_es_ES.properties
new file mode 100644
index 0000000..71b0584
--- /dev/null
+++ b/pentaho-plugin-base/src/main/java/com/ucuenca/pentaho/plugin/step/messages/messages_es_ES.properties
@@ -0,0 +1,4 @@
+Demo.Shell.Title=Demo step
+Demo.FieldName.Label=Output field name
+Demo.CheckResult.ReceivingRows.OK=Step is receiving input from other steps.
+Demo.CheckResult.ReceivingRows.ERROR=No input received from other steps!
diff --git a/pentaho-plugin-base/src/main/resources/plugin/icon.png b/pentaho-plugin-base/src/main/resources/plugin/icon.png
new file mode 100644
index 0000000..2c6bce1
Binary files /dev/null and b/pentaho-plugin-base/src/main/resources/plugin/icon.png differ
diff --git a/pentaho-plugin-base/src/main/resources/plugin/plugin.xml b/pentaho-plugin-base/src/main/resources/plugin/plugin.xml
new file mode 100644
index 0000000..6ad9188
--- /dev/null
+++ b/pentaho-plugin-base/src/main/resources/plugin/plugin.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+