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 @@ + + + + + + + + + + + + + +