diff --git a/org.knime.base.filehandling.tests/files/node_settings/BinaryObjectsToPNGsNodeParameters.xml b/org.knime.base.filehandling.tests/files/node_settings/BinaryObjectsToPNGsNodeParameters.xml
new file mode 100644
index 00000000..6400bfa7
--- /dev/null
+++ b/org.knime.base.filehandling.tests/files/node_settings/BinaryObjectsToPNGsNodeParameters.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest.snap b/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest.snap
new file mode 100644
index 00000000..4a189e71
--- /dev/null
+++ b/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest.snap
@@ -0,0 +1,107 @@
+{
+ "data" : {
+ "model" : {
+ "columnSelection" : "",
+ "outputMode" : "REPLACE",
+ "newColumnName" : "PNG"
+ }
+ },
+ "schema" : {
+ "type" : "object",
+ "properties" : {
+ "model" : {
+ "type" : "object",
+ "properties" : {
+ "columnSelection" : {
+ "type" : "string",
+ "title" : "Column selection",
+ "description" : "Column containing the binary objects that will be converted to PNG images.",
+ "default" : ""
+ },
+ "newColumnName" : {
+ "type" : "string",
+ "title" : "New column name",
+ "description" : "Name of the appended column. Only applicable when \"Append\" is selected.",
+ "default" : "PNG"
+ },
+ "outputMode" : {
+ "oneOf" : [ {
+ "const" : "REPLACE",
+ "title" : "Replace"
+ }, {
+ "const" : "APPEND",
+ "title" : "Append"
+ } ],
+ "title" : "Output handling",
+ "description" : "Determines whether to append a new PNG column or to replace the selected binary object column.\n
\n- Replace: Replaces the selected binary object column with the PNG column.
\n- Append: Appends a new PNG column to the table.
\n
",
+ "default" : "REPLACE"
+ }
+ }
+ }
+ }
+ },
+ "ui_schema" : {
+ "elements" : [ {
+ "type" : "Control",
+ "scope" : "#/properties/model/properties/columnSelection",
+ "options" : {
+ "format" : "dropDown"
+ },
+ "providedOptions" : [ "possibleValues" ]
+ }, {
+ "type" : "Control",
+ "scope" : "#/properties/model/properties/outputMode",
+ "options" : {
+ "format" : "valueSwitch"
+ }
+ }, {
+ "type" : "Control",
+ "scope" : "#/properties/model/properties/newColumnName",
+ "rule" : {
+ "effect" : "SHOW",
+ "condition" : {
+ "scope" : "#/properties/model/properties/outputMode",
+ "schema" : {
+ "oneOf" : [ {
+ "const" : "APPEND"
+ } ]
+ }
+ }
+ }
+ } ]
+ },
+ "persist" : {
+ "type" : "object",
+ "properties" : {
+ "model" : {
+ "type" : "object",
+ "properties" : {
+ "columnSelection" : {
+ "configKey" : "columnselection"
+ },
+ "outputMode" : {
+ "configPaths" : [ [ "replace" ] ]
+ },
+ "newColumnName" : {
+ "configKey" : "columnname"
+ }
+ }
+ }
+ }
+ },
+ "initialUpdates" : [ {
+ "scope" : "#/properties/model/properties/columnSelection",
+ "providedOptionName" : "possibleValues",
+ "values" : [ {
+ "indices" : [ ],
+ "value" : [ {
+ "id" : "foo",
+ "text" : "foo",
+ "type" : {
+ "id" : "org.knime.core.data.blob.BinaryObjectDataValue",
+ "text" : "Binary Object"
+ }
+ } ]
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest0.settings.xml.snap b/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest0.settings.xml.snap
new file mode 100644
index 00000000..89d4084e
--- /dev/null
+++ b/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest0.settings.xml.snap
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest1.snap b/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest1.snap
new file mode 100644
index 00000000..3eed69d6
--- /dev/null
+++ b/org.knime.base.filehandling.tests/files/test_snapshots/org.knime.base.filehandling.binaryobjectstopngs.BinaryObjectsToPNGsNodeParametersTest1.snap
@@ -0,0 +1,107 @@
+{
+ "data" : {
+ "model" : {
+ "columnSelection" : "Image",
+ "outputMode" : "APPEND",
+ "newColumnName" : "PNG"
+ }
+ },
+ "schema" : {
+ "type" : "object",
+ "properties" : {
+ "model" : {
+ "type" : "object",
+ "properties" : {
+ "columnSelection" : {
+ "type" : "string",
+ "title" : "Column selection",
+ "description" : "Column containing the binary objects that will be converted to PNG images.",
+ "default" : ""
+ },
+ "newColumnName" : {
+ "type" : "string",
+ "title" : "New column name",
+ "description" : "Name of the appended column. Only applicable when \"Append\" is selected.",
+ "default" : "PNG"
+ },
+ "outputMode" : {
+ "oneOf" : [ {
+ "const" : "REPLACE",
+ "title" : "Replace"
+ }, {
+ "const" : "APPEND",
+ "title" : "Append"
+ } ],
+ "title" : "Output handling",
+ "description" : "Determines whether to append a new PNG column or to replace the selected binary object column.\n\n- Replace: Replaces the selected binary object column with the PNG column.
\n- Append: Appends a new PNG column to the table.
\n
",
+ "default" : "REPLACE"
+ }
+ }
+ }
+ }
+ },
+ "ui_schema" : {
+ "elements" : [ {
+ "type" : "Control",
+ "scope" : "#/properties/model/properties/columnSelection",
+ "options" : {
+ "format" : "dropDown"
+ },
+ "providedOptions" : [ "possibleValues" ]
+ }, {
+ "type" : "Control",
+ "scope" : "#/properties/model/properties/outputMode",
+ "options" : {
+ "format" : "valueSwitch"
+ }
+ }, {
+ "type" : "Control",
+ "scope" : "#/properties/model/properties/newColumnName",
+ "rule" : {
+ "effect" : "SHOW",
+ "condition" : {
+ "scope" : "#/properties/model/properties/outputMode",
+ "schema" : {
+ "oneOf" : [ {
+ "const" : "APPEND"
+ } ]
+ }
+ }
+ }
+ } ]
+ },
+ "persist" : {
+ "type" : "object",
+ "properties" : {
+ "model" : {
+ "type" : "object",
+ "properties" : {
+ "columnSelection" : {
+ "configKey" : "columnselection"
+ },
+ "outputMode" : {
+ "configPaths" : [ [ "replace" ] ]
+ },
+ "newColumnName" : {
+ "configKey" : "columnname"
+ }
+ }
+ }
+ }
+ },
+ "initialUpdates" : [ {
+ "scope" : "#/properties/model/properties/columnSelection",
+ "providedOptionName" : "possibleValues",
+ "values" : [ {
+ "indices" : [ ],
+ "value" : [ {
+ "id" : "foo",
+ "text" : "foo",
+ "type" : {
+ "id" : "org.knime.core.data.blob.BinaryObjectDataValue",
+ "text" : "Binary Object"
+ }
+ } ]
+ } ]
+ } ]
+}
\ No newline at end of file
diff --git a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeDialog.java b/org.knime.base.filehandling.tests/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeParametersTest.java
similarity index 51%
rename from org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeDialog.java
rename to org.knime.base.filehandling.tests/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeParametersTest.java
index d3e9235d..030d102c 100644
--- a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeDialog.java
+++ b/org.knime.base.filehandling.tests/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeParametersTest.java
@@ -1,5 +1,6 @@
/*
* ------------------------------------------------------------------------
+ *
* Copyright by KNIME AG, Zurich, Switzerland
* Website: http://www.knime.com; Email: contact@knime.com
*
@@ -41,61 +42,64 @@
* may freely choose the license terms applicable to such Node, including
* when such Node is propagated with or for interoperation with KNIME.
* ------------------------------------------------------------------------
- *
- * History
- * Oct 30, 2012 (Patrick Winter): created
*/
package org.knime.base.filehandling.binaryobjectstopngs;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
+import java.io.FileInputStream;
+import java.io.IOException;
-import org.knime.core.data.blob.BinaryObjectDataValue;
-import org.knime.core.node.defaultnodesettings.DefaultNodeSettingsPane;
-import org.knime.core.node.defaultnodesettings.DialogComponentButtonGroup;
-import org.knime.core.node.defaultnodesettings.DialogComponentColumnNameSelection;
-import org.knime.core.node.defaultnodesettings.DialogComponentString;
-import org.knime.core.node.defaultnodesettings.SettingsModelString;
+import org.knime.core.data.DataTableSpec;
+import org.knime.core.data.DataType;
+import org.knime.core.data.blob.BinaryObjectDataCell;
+import org.knime.core.node.InvalidSettingsException;
+import org.knime.core.node.NodeSettings;
+import org.knime.core.node.port.PortObjectSpec;
+import org.knime.core.webui.node.dialog.SettingsType;
+import org.knime.core.webui.node.dialog.defaultdialog.NodeParametersUtil;
+import org.knime.testing.node.dialog.DefaultNodeSettingsSnapshotTest;
+import org.knime.testing.node.dialog.SnapshotTestConfiguration;
/**
- * NodeDialog for the node.
- *
- *
- * @author Patrick Winter, KNIME AG, Zurich, Switzerland
+ * Snapshot test for {@link BinaryObjectsToPNGsNodeParameters}.
+ *
+ * @author Tim Crundall, TNG Technology Consulting GmbH
*/
-public class BinaryObjectsToPNGsNodeDialog extends DefaultNodeSettingsPane {
+@SuppressWarnings("restriction")
+final class BinaryObjectsToPNGsNodeParametersTest extends DefaultNodeSettingsSnapshotTest {
- private SettingsModelString m_columnselection;
-
- private SettingsModelString m_columnname;
+ BinaryObjectsToPNGsNodeParametersTest() {
+ super(getConfig());
+ }
- private SettingsModelString m_replace;
+ private static SnapshotTestConfiguration getConfig() {
+ return SnapshotTestConfiguration.builder() //
+ .withInputPortObjectSpecs(createInputPortSpecs()) //
+ .testJsonFormsForModel(BinaryObjectsToPNGsNodeParameters.class) //
+ .testJsonFormsWithInstance(SettingsType.MODEL, () -> readSettings()) //
+ .testNodeSettingsStructure(() -> readSettings()) //
+ .build();
+ }
- /**
- * New pane for configuring the node dialog.
- */
- @SuppressWarnings("unchecked")
- protected BinaryObjectsToPNGsNodeDialog() {
- super();
- m_columnselection = SettingsFactory.createColumnSelectionSettings();
- m_replace = SettingsFactory.createReplacePolicySettings();
- m_columnname = SettingsFactory.createColumnNameSettings(m_replace);
- m_replace.addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(final ChangeEvent e) {
- boolean append = m_replace.getStringValue().equals(ReplacePolicy.APPEND.getName());
- m_columnname.setEnabled(append);
+ private static BinaryObjectsToPNGsNodeParameters readSettings() {
+ try {
+ var path = getSnapshotPath(BinaryObjectsToPNGsNodeParameters.class).getParent().resolve("node_settings")
+ .resolve("BinaryObjectsToPNGsNodeParameters.xml");
+ try (var fis = new FileInputStream(path.toFile())) {
+ var nodeSettings = NodeSettings.loadFromXML(fis);
+ return NodeParametersUtil.loadSettings(nodeSettings.getNodeSettings(SettingsType.MODEL.getConfigKey()),
+ BinaryObjectsToPNGsNodeParameters.class);
}
- });
- // Column selection
- addDialogComponent(new DialogComponentColumnNameSelection(m_columnselection, "Column selection", 0,
- BinaryObjectDataValue.class));
- createNewGroup("New column...");
- // Replace
- addDialogComponent(new DialogComponentButtonGroup(m_replace, false, "", ReplacePolicy.getAllSettings()));
- // Column name
- addDialogComponent(new DialogComponentString(m_columnname, "Name", true, 20));
- closeCurrentGroup();
+ } catch (IOException | InvalidSettingsException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static PortObjectSpec[] createInputPortSpecs() {
+ return new PortObjectSpec[]{createDefaultTestTableSpec()};
}
+ private static DataTableSpec createDefaultTestTableSpec() {
+ return new DataTableSpec(new String[]{"foo"},
+ new DataType[]{DataType.getType(BinaryObjectDataCell.class), });
+ }
}
diff --git a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.java b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.java
index 85cf0994..159d2984 100644
--- a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.java
+++ b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.java
@@ -41,63 +41,114 @@
* may freely choose the license terms applicable to such Node, including
* when such Node is propagated with or for interoperation with KNIME.
* ------------------------------------------------------------------------
- *
+ *
* History
* Sep 5, 2012 (Patrick Winter): created
*/
package org.knime.base.filehandling.binaryobjectstopngs;
+import static org.knime.node.impl.description.PortDescription.fixedPort;
+
+import java.util.List;
+import java.util.Map;
+
+import org.knime.core.node.NodeDescription;
import org.knime.core.node.NodeDialogPane;
import org.knime.core.node.NodeFactory;
import org.knime.core.node.NodeView;
+import org.knime.core.webui.node.dialog.NodeDialog;
+import org.knime.core.webui.node.dialog.NodeDialogFactory;
+import org.knime.core.webui.node.dialog.NodeDialogManager;
+import org.knime.core.webui.node.dialog.SettingsType;
+import org.knime.core.webui.node.dialog.defaultdialog.DefaultKaiNodeInterface;
+import org.knime.core.webui.node.dialog.defaultdialog.DefaultNodeDialog;
+import org.knime.core.webui.node.dialog.kai.KaiNodeInterface;
+import org.knime.core.webui.node.dialog.kai.KaiNodeInterfaceFactory;
+import org.knime.node.impl.description.DefaultNodeDescriptionUtil;
+import org.knime.node.impl.description.PortDescription;
/**
* NodeFactory for node.
- *
- *
+ *
+ *
* @author Patrick Winter, KNIME AG, Zurich, Switzerland
+ *
+ * @author Tim Crundall, TNG Technology Consulting GmbH
+ *
+ * @author AI Migration Pipeline v1.2
*/
-public class BinaryObjectsToPNGsNodeFactory extends NodeFactory {
+@SuppressWarnings({"restriction", "removal"})
+public class BinaryObjectsToPNGsNodeFactory extends NodeFactory
+ implements NodeDialogFactory, KaiNodeInterfaceFactory {
- /**
- * {@inheritDoc}
- */
@Override
public BinaryObjectsToPNGsNodeModel createNodeModel() {
return new BinaryObjectsToPNGsNodeModel();
}
- /**
- * {@inheritDoc}
- */
@Override
public int getNrNodeViews() {
return 0;
}
- /**
- * {@inheritDoc}
- */
@Override
- public NodeView createNodeView(final int viewIndex,
- final BinaryObjectsToPNGsNodeModel nodeModel) {
+ public NodeView createNodeView( //
+ final int viewIndex, //
+ final BinaryObjectsToPNGsNodeModel nodeModel //
+ ) {
return null;
}
- /**
- * {@inheritDoc}
- */
@Override
public boolean hasDialog() {
return true;
}
- /**
- * {@inheritDoc}
- */
+ private static final String NODE_NAME = "Binary Objects to PNGs";
+
+ private static final String NODE_ICON = "./binaryobjectstopngs16x16.png";
+
+ private static final String SHORT_DESCRIPTION = "Converts the binary objects of a column to PNGs.";
+
+ private static final String FULL_DESCRIPTION = "This node converts the binary object cells to PNG cells.";
+
+ private static final List INPUT_PORTS =
+ List.of(fixedPort("Input table", "Table that contains the binary objects that will be converted."));
+
+ private static final List OUTPUT_PORTS = List
+ .of(fixedPort("Output table", "Input table with PNG column either appended or replacing the binary objects."));
+
@Override
public NodeDialogPane createNodeDialogPane() {
- return new BinaryObjectsToPNGsNodeDialog();
+ return NodeDialogManager.createLegacyFlowVariableNodeDialog(createNodeDialog());
+ }
+
+ @Override
+ public NodeDialog createNodeDialog() {
+ return new DefaultNodeDialog(SettingsType.MODEL, BinaryObjectsToPNGsNodeParameters.class);
+ }
+
+ @Override
+ public NodeDescription createNodeDescription() {
+ return DefaultNodeDescriptionUtil.createNodeDescription( //
+ NODE_NAME, //
+ NODE_ICON, //
+ INPUT_PORTS, //
+ OUTPUT_PORTS, //
+ SHORT_DESCRIPTION, //
+ FULL_DESCRIPTION, //
+ List.of(), //
+ BinaryObjectsToPNGsNodeParameters.class, //
+ null, //
+ NodeType.Manipulator, //
+ List.of(), //
+ null //
+ );
+ }
+
+ @Override
+ public KaiNodeInterface createKaiNodeInterface() {
+ return new DefaultKaiNodeInterface(Map.of(SettingsType.MODEL, BinaryObjectsToPNGsNodeParameters.class));
}
}
diff --git a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.xml b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.xml
deleted file mode 100644
index 0e8ea62b..00000000
--- a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeFactory.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
- Binary Objects to PNGs
-
-
- Converts the binary objects of a column to PNGs.
-
-
-
-
- This node converts the binary object cells to PNG cells.
-
-
-
-
-
-
-
-
-
-
- Table that contains the
- binary
- objects that will be converted.
-
-
- Input table with PNG
- column either appended or replacing the binary objects.
-
-
-
diff --git a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeModel.java b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeModel.java
index bcd6c960..58b22ee4 100644
--- a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeModel.java
+++ b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeModel.java
@@ -50,6 +50,7 @@
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Optional;
import org.knime.base.filehandling.NodeUtils;
import org.knime.core.data.DataCell;
@@ -214,6 +215,15 @@ protected void reset() {
*/
@Override
protected DataTableSpec[] configure(final DataTableSpec[] inSpecs) throws InvalidSettingsException {
+ // Auto-guess column selection (last BinaryObjectData-compatible column) if not set
+ if (m_columnselection.getStringValue() == null || m_columnselection.getStringValue().isEmpty()) {
+ Optional.ofNullable(inSpecs[0]).stream().flatMap(DataTableSpec::stream) //
+ .filter(col -> col.getType().isCompatible(BinaryObjectDataValue.class)) //
+ .reduce((first, second) -> second) //
+ .map(DataColumnSpec::getName) //
+ .ifPresent(m_columnselection::setStringValue); //
+ }
+
// createColumnRearranger will check the settings
DataTableSpec outSpec = createColumnRearranger(inSpecs[0]).createSpec();
return new DataTableSpec[]{outSpec};
diff --git a/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeParameters.java b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeParameters.java
new file mode 100644
index 00000000..83d6312e
--- /dev/null
+++ b/org.knime.base.filehandling/src/org/knime/base/filehandling/binaryobjectstopngs/BinaryObjectsToPNGsNodeParameters.java
@@ -0,0 +1,179 @@
+/*
+ * ------------------------------------------------------------------------
+ *
+ * Copyright by KNIME AG, Zurich, Switzerland
+ * Website: http://www.knime.com; Email: contact@knime.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see .
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * KNIME interoperates with ECLIPSE solely via ECLIPSE's plug-in APIs.
+ * Hence, KNIME and ECLIPSE are both independent programs and are not
+ * derived from each other. Should, however, the interpretation of the
+ * GNU GPL Version 3 ("License") under any applicable laws result in
+ * KNIME and ECLIPSE being a combined program, KNIME AG herewith grants
+ * you the additional permission to use and propagate KNIME together with
+ * ECLIPSE with only the license terms in place for ECLIPSE applying to
+ * ECLIPSE and the GNU GPL Version 3 applying for KNIME, provided the
+ * license terms of ECLIPSE themselves allow for the respective use and
+ * propagation of ECLIPSE together with KNIME.
+ *
+ * Additional permission relating to nodes for KNIME that extend the Node
+ * Extension (and in particular that are based on subclasses of NodeModel,
+ * NodeDialog, and NodeView) and that only interoperate with KNIME through
+ * standard APIs ("Nodes"):
+ * Nodes are deemed to be separate and independent programs and to not be
+ * covered works. Notwithstanding anything to the contrary in the
+ * License, the License does not apply to Nodes, you are not required to
+ * license Nodes under the License, and you are granted a license to
+ * prepare and propagate Nodes, in each case even if such Nodes are
+ * propagated with or for interoperation with KNIME. The owner of a Node
+ * may freely choose the license terms applicable to such Node, including
+ * when such Node is propagated with or for interoperation with KNIME.
+ * ------------------------------------------------------------------------
+ */
+
+package org.knime.base.filehandling.binaryobjectstopngs;
+
+import java.util.Optional;
+
+import org.knime.core.data.DataColumnSpec;
+import org.knime.core.data.blob.BinaryObjectDataValue;
+import org.knime.core.node.InvalidSettingsException;
+import org.knime.core.node.NodeSettingsRO;
+import org.knime.core.node.NodeSettingsWO;
+import org.knime.node.parameters.NodeParameters;
+import org.knime.node.parameters.NodeParametersInput;
+import org.knime.node.parameters.Widget;
+import org.knime.node.parameters.migration.LoadDefaultsForAbsentFields;
+import org.knime.node.parameters.migration.Migrate;
+import org.knime.node.parameters.persistence.NodeParametersPersistor;
+import org.knime.node.parameters.persistence.Persist;
+import org.knime.node.parameters.persistence.Persistor;
+import org.knime.node.parameters.updates.Effect;
+import org.knime.node.parameters.updates.Effect.EffectType;
+import org.knime.node.parameters.updates.EffectPredicate;
+import org.knime.node.parameters.updates.EffectPredicateProvider;
+import org.knime.node.parameters.updates.ParameterReference;
+import org.knime.node.parameters.updates.ValueProvider;
+import org.knime.node.parameters.updates.ValueReference;
+import org.knime.node.parameters.updates.legacy.ColumnNameAutoGuessValueProvider;
+import org.knime.node.parameters.widget.choices.ChoicesProvider;
+import org.knime.node.parameters.widget.choices.Label;
+import org.knime.node.parameters.widget.choices.ValueSwitchWidget;
+import org.knime.node.parameters.widget.choices.util.ColumnSelectionUtil;
+import org.knime.node.parameters.widget.choices.util.CompatibleColumnsProvider;
+
+/**
+ * Node parameters for Binary Objects to PNGs.
+ *
+ * @author Tim Crundall, TNG Technology Consulting GmbH
+ * @author AI Migration Pipeline v1.2
+ */
+@LoadDefaultsForAbsentFields
+@SuppressWarnings("restriction")
+final class BinaryObjectsToPNGsNodeParameters implements NodeParameters {
+
+ @Widget(title = "Column selection",
+ description = "Column containing the binary objects that will be converted to PNG images.")
+ @ChoicesProvider(BinaryObjectColumnsProvider.class)
+ @ValueProvider(InputColumnProvider.class)
+ @Persist(configKey = "columnselection")
+ @ValueReference(InputColumnRef.class)
+ String m_columnSelection = "";
+
+ private interface InputColumnRef extends ParameterReference {
+ }
+
+ private static final class BinaryObjectColumnsProvider extends CompatibleColumnsProvider {
+ protected BinaryObjectColumnsProvider() {
+ super(BinaryObjectDataValue.class);
+ }
+ }
+
+ private static final class InputColumnProvider extends ColumnNameAutoGuessValueProvider {
+ protected InputColumnProvider() {
+ super(InputColumnRef.class);
+ }
+
+ @Override
+ protected Optional autoGuessColumn(final NodeParametersInput parametersInput) {
+ final var compatibleColumns = ColumnSelectionUtil.getCompatibleColumnsOfFirstPort(
+ parametersInput, BinaryObjectDataValue.class);
+ return compatibleColumns.isEmpty() ? Optional.empty() :
+ Optional.of(compatibleColumns.get(compatibleColumns.size() - 1));
+ }
+ }
+
+ @Widget(title = "Output handling",
+ description = "Determines whether to append a new PNG column or to replace the selected binary object column.")
+ @ValueSwitchWidget
+ @ValueReference(OutputModeRef.class)
+ @Persistor(OutputModePersistor.class)
+ @Migrate(loadDefaultIfAbsent = true)
+ OutputMode m_outputMode = OutputMode.REPLACE;
+
+ private interface OutputModeRef extends ParameterReference {
+ }
+
+ private enum OutputMode {
+ @Label(value = "Replace", description = "Replaces the selected binary object column with the PNG column.")
+ REPLACE, //
+ @Label(value = "Append", description = "Appends a new PNG column to the table.")
+ APPEND;
+ }
+
+ /**
+ * Persists the OutputMode enum as the legacy string values "Append" / "Replace" under key "replace",
+ * matching via {@link ReplacePolicy#getName()}.
+ */
+ private static final class OutputModePersistor implements NodeParametersPersistor {
+
+ private static final String CFG_KEY = "replace";
+
+ @Override
+ public OutputMode load(final NodeSettingsRO settings) throws InvalidSettingsException {
+ final String value = settings.getString(CFG_KEY);
+ if (ReplacePolicy.APPEND.getName().equals(value)) {
+ return OutputMode.APPEND;
+ }
+ return OutputMode.REPLACE;
+ }
+
+ @Override
+ public void save(final OutputMode obj, final NodeSettingsWO settings) {
+ final ReplacePolicy policy = obj == OutputMode.APPEND ? ReplacePolicy.APPEND : ReplacePolicy.REPLACE;
+ settings.addString(CFG_KEY, policy.getName());
+ }
+
+ @Override
+ public String[][] getConfigPaths() {
+ return new String[][]{{CFG_KEY}};
+ }
+ }
+
+ @Widget(title = "New column name",
+ description = "Name of the appended column. Only applicable when \"Append\" is selected.")
+ @Effect(predicate = IsAppend.class, type = EffectType.SHOW)
+ @Persist(configKey = "columnname")
+ String m_newColumnName = "PNG";
+
+ private static final class IsAppend implements EffectPredicateProvider {
+ @Override
+ public EffectPredicate init(final PredicateInitializer i) {
+ return i.getEnum(OutputModeRef.class).isOneOf(OutputMode.APPEND);
+ }
+ }
+
+}
diff --git a/org.knime.ext.box.authenticator.tests/META-INF/MANIFEST.MF b/org.knime.ext.box.authenticator.tests/META-INF/MANIFEST.MF
index 076d8e50..d18728fd 100644
--- a/org.knime.ext.box.authenticator.tests/META-INF/MANIFEST.MF
+++ b/org.knime.ext.box.authenticator.tests/META-INF/MANIFEST.MF
@@ -2,10 +2,10 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Unit-Tests for org.knime.ext.box.authenticator
Bundle-SymbolicName: org.knime.ext.box.authenticator.tests;singleton:=true
-Bundle-Version: 5.9.0.qualifier
+Bundle-Version: 5.12.0.qualifier
Bundle-Vendor: KNIME AG, Zurich, Switzerland
Bundle-RequiredExecutionEnvironment: JavaSE-17
-Fragment-Host: org.knime.ext.box.authenticator;bundle-version="[5.6.0,6.0.0)"
+Fragment-Host: org.knime.ext.box.authenticator;bundle-version="[5.12.0,6.0.0)"
Eclipse-BundleShape: dir
Automatic-Module-Name: org.knime.ext.box.authenticator.tests
Require-Bundle: org.knime.core.ui.testing;bundle-version="[5.6.0,6.0.0)",
diff --git a/org.knime.ext.box.authenticator.tests/files/test_snapshots/org.knime.ext.box.authenticator.node.BoxAuthenticatorSettingsTest.snap b/org.knime.ext.box.authenticator.tests/files/test_snapshots/org.knime.ext.box.authenticator.node.BoxAuthenticatorSettingsTest.snap
index 17433db6..3dbc59aa 100644
--- a/org.knime.ext.box.authenticator.tests/files/test_snapshots/org.knime.ext.box.authenticator.node.BoxAuthenticatorSettingsTest.snap
+++ b/org.knime.ext.box.authenticator.tests/files/test_snapshots/org.knime.ext.box.authenticator.node.BoxAuthenticatorSettingsTest.snap
@@ -1,7 +1,15 @@
{
"data" : {
"model" : {
- "boxApp" : { },
+ "boxApp" : {
+ "secret" : {
+ "credentials" : {
+ "isHiddenPassword" : false,
+ "isHiddenSecondFactor" : false,
+ "username" : ""
+ }
+ }
+ },
"authType" : "OAUTH",
"redirectUrl" : "http://localhost:33749/"
}
@@ -27,13 +35,55 @@
"boxApp" : {
"type" : "object",
"properties" : {
- "flowVariable" : {
- "type" : "string",
- "title" : "App ID and secret (flow variable)",
- "description" : "Specifies a credentials flow variable with the app/client ID and secret of the custom Box app.\nThese fields can be found in the configuration settings of your custom Box app.\n"
+ "secret" : {
+ "type" : "object",
+ "properties" : {
+ "credentials" : {
+ "type" : "object",
+ "properties" : {
+ "password" : {
+ "type" : "string",
+ "default" : ""
+ },
+ "secondFactor" : {
+ "type" : "string",
+ "default" : ""
+ },
+ "username" : {
+ "type" : "string",
+ "default" : ""
+ }
+ },
+ "default" : {
+ "isHiddenPassword" : false,
+ "isHiddenSecondFactor" : false,
+ "username" : ""
+ }
+ },
+ "flowVarName" : {
+ "type" : "string"
+ }
+ },
+ "title" : "App ID and secret",
+ "description" : "Specifies the app/client ID and secret of the custom Box app.\nThese fields can be found in the configuration settings of your custom Box app.\n",
+ "default" : {
+ "credentials" : {
+ "isHiddenPassword" : false,
+ "isHiddenSecondFactor" : false,
+ "username" : ""
+ }
+ }
}
},
- "default" : { }
+ "default" : {
+ "secret" : {
+ "credentials" : {
+ "isHiddenPassword" : false,
+ "isHiddenSecondFactor" : false,
+ "username" : ""
+ }
+ }
+ }
},
"enterpriseId" : {
"type" : "string",
@@ -62,11 +112,12 @@
"type" : "Section",
"elements" : [ {
"type" : "Control",
- "scope" : "#/properties/model/properties/boxApp/properties/flowVariable",
+ "scope" : "#/properties/model/properties/boxApp/properties/secret",
"options" : {
- "format" : "dropDown"
- },
- "providedOptions" : [ "possibleValues" ]
+ "passwordLabel" : "Secret",
+ "usernameLabel" : "ID",
+ "format" : "legacyCredentials"
+ }
} ]
}, {
"label" : "Authentication method",
@@ -131,10 +182,10 @@
} ],
"displayErrorMessage" : true,
"showTitleAndDescription" : false,
- "dependencies" : [ "#/properties/model/properties/boxApp/properties/flowVariable", "#/properties/model/properties/authType", "#/properties/model/properties/enterpriseId", "#/properties/model/properties/redirectUrl" ],
+ "dependencies" : [ "#/properties/model/properties/boxApp/properties/secret", "#/properties/model/properties/authType", "#/properties/model/properties/enterpriseId", "#/properties/model/properties/redirectUrl" ],
"updateOptions" : {
"updateHandler" : "org.knime.ext.box.authenticator.node.BoxAuthenticatorSettings$LoginUpdateHandler",
- "dependencies" : [ "#/properties/model/properties/boxApp/properties/flowVariable", "#/properties/model/properties/authType", "#/properties/model/properties/enterpriseId", "#/properties/model/properties/redirectUrl" ]
+ "dependencies" : [ "#/properties/model/properties/boxApp/properties/secret", "#/properties/model/properties/authType", "#/properties/model/properties/enterpriseId", "#/properties/model/properties/redirectUrl" ]
}
},
"rule" : {
@@ -160,7 +211,18 @@
"boxApp" : {
"type" : "object",
"properties" : {
- "flowVariable" : { }
+ "secret" : {
+ "type" : "object",
+ "properties" : {
+ "credentials" : { },
+ "flowVarName" : {
+ "configPaths" : [ ]
+ }
+ },
+ "deprecatedConfigKeys" : [ {
+ "deprecated" : [ [ "flowVariable" ] ]
+ } ]
+ }
}
},
"authType" : { },
@@ -173,12 +235,16 @@
}
}
},
- "initialUpdates" : [ {
- "scope" : "#/properties/model/properties/boxApp/properties/flowVariable",
- "providedOptionName" : "possibleValues",
- "values" : [ {
- "indices" : [ ],
- "value" : [ ]
- } ]
+ "globalUpdates" : [ {
+ "trigger" : {
+ "id" : "after-open-dialog"
+ },
+ "triggerInitially" : true,
+ "dependencies" : [ "#/properties/model/properties/boxApp" ]
+ }, {
+ "trigger" : {
+ "scope" : "#/properties/model/properties/boxApp"
+ },
+ "dependencies" : [ "#/properties/model/properties/boxApp" ]
} ]
}
\ No newline at end of file
diff --git a/org.knime.ext.box.authenticator.tests/pom.xml b/org.knime.ext.box.authenticator.tests/pom.xml
index 53362e9a..2a9c5e5d 100644
--- a/org.knime.ext.box.authenticator.tests/pom.xml
+++ b/org.knime.ext.box.authenticator.tests/pom.xml
@@ -15,7 +15,7 @@
eclipse-test-plugin
- 5.9.0
+ 5.12.0
src/eclipse
diff --git a/org.knime.ext.box.authenticator/META-INF/MANIFEST.MF b/org.knime.ext.box.authenticator/META-INF/MANIFEST.MF
index cd9934d2..c97acb87 100644
--- a/org.knime.ext.box.authenticator/META-INF/MANIFEST.MF
+++ b/org.knime.ext.box.authenticator/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Plugin for the Box Authenticator node
Bundle-SymbolicName: org.knime.ext.box.authenticator;singleton:=true
-Bundle-Version: 5.9.0.qualifier
+Bundle-Version: 5.12.0.qualifier
Bundle-Vendor: KNIME AG, Zurich, Switzerland
Require-Bundle: org.knime.workbench.repository;bundle-version="[5.9.0,6.0.0)",
org.knime.core;bundle-version="[5.9.0,6.0.0)",
diff --git a/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAppSettings.java b/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAppSettings.java
index fc3088e7..3ea181de 100644
--- a/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAppSettings.java
+++ b/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAppSettings.java
@@ -50,46 +50,71 @@
import org.knime.core.node.InvalidSettingsException;
import org.knime.core.node.workflow.CredentialsProvider;
+import org.knime.core.webui.node.dialog.defaultdialog.setting.credentials.LegacyCredentials;
+import org.knime.core.webui.node.dialog.defaultdialog.widget.validation.custom.CustomValidation;
+import org.knime.credentials.base.node.CredentialVariableMigration;
import org.knime.credentials.base.node.CredentialsSettings;
import org.knime.node.parameters.Widget;
-import org.knime.node.parameters.widget.choices.ChoicesProvider;
+import org.knime.node.parameters.migration.Migration;
+import org.knime.node.parameters.updates.ParameterReference;
+import org.knime.node.parameters.widget.credentials.Credentials;
+import org.knime.node.parameters.widget.credentials.CredentialsWidget;
/**
* Implementation of {@link CredentialsSettings} to supply the ID and secret of
* a confidential OAuth2 app.
*
+ * Any instance must be annotated with a {@code ValueReference} to {@link Ref}
+ * for the validation to work.
+ *
+ *
* @author Bjoern Lohrmann, KNIME GmbH
*/
@SuppressWarnings("restriction")
public class BoxAppSettings implements CredentialsSettings {
/**
- * The name of the Credentials flow variable.
+ * The credential
*/
- @Widget(title = "App ID and secret (flow variable)", //
+ @Widget(title = "App ID and secret", //
description = """
- Specifies a credentials flow variable with the app/client ID and secret of the custom Box app.
+ Specifies the app/client ID and secret of the custom Box app.
These fields can be found in the configuration settings of your custom Box app.
""")
- @ChoicesProvider(CredentialsFlowVarChoicesProvider.class)
- public String m_flowVariable;
+ @Migration(CredentialVariableMigration.class)
+ @CustomValidation(BoxCredentialValidator.class)
+ @CredentialsWidget(usernameLabel = "ID", passwordLabel = "Secret") // NOSONAR not a password
+
+ public LegacyCredentials m_secret = new LegacyCredentials(new Credentials());
+
+ /**
+ * Used to reference this class for the validation.
+ */
+ public interface Ref extends ParameterReference {
+ }
+
+ static final class BoxCredentialValidator extends AbstractCredentialsValidator {
+ BoxCredentialValidator() {
+ super(Ref.class);
+ }
+ }
@Override
- public String flowVariableName() {
- return m_flowVariable;
+ public LegacyCredentials getCredential() {
+ return m_secret;
}
/**
- * If a flow variable has been specified, this method validates that a username
- * and password are present in the flow variable. This method should be used
- * during the configure phase, to reduce logspam if the credentials flow
- * variable is not there yet.
+ * If a credential has been specified, this method validates that a username and
+ * password are present. This method should be used during the configure phase,
+ * to reduce logspam if the credential is not there yet.
*
* @param credsProvider
- * Used to access the flow variable.
+ * Used to access the credential.
* @throws InvalidSettingsException
- * when username or password was not present in the flow variable.
+ * when username or password was not present in the credential.
*/
+ @Override
public void validateOnConfigure(final CredentialsProvider credsProvider) throws InvalidSettingsException {
if (retrieve(credsProvider).isPresent()) {
validateLogin(credsProvider, "Client/App ID is required");
@@ -98,16 +123,15 @@ public void validateOnConfigure(final CredentialsProvider credsProvider) throws
}
/**
- * This method validates both presence and validity of a credentials flow
- * variable. This method should be used during the execute phase.
+ * This method validates both presence and validity of a credential. This method
+ * should be used during the execute phase.
*
* @param credsProvider
- * Used to access the flow variable.
+ * Used to access the credential.
* @throws InvalidSettingsException
- * when flow variable was not present or invalid.
+ * when credential was not present or invalid.
*/
public void validateOnExecute(final CredentialsProvider credsProvider) throws InvalidSettingsException {
- validateFlowVariable(credsProvider);
validateLogin(credsProvider, "Client/App ID is required");
validateSecret(credsProvider, "Client/App secret is required");
}
diff --git a/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAuthenticatorSettings.java b/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAuthenticatorSettings.java
index 26f3846f..0aa8cdb1 100644
--- a/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAuthenticatorSettings.java
+++ b/org.knime.ext.box.authenticator/src-deprecated/org/knime/ext/box/authenticator/node/BoxAuthenticatorSettings.java
@@ -136,6 +136,7 @@ public EffectPredicate init(final PredicateInitializer i) {
}
@Layout(BoxAppSection.class)
+ @ValueReference(BoxAppSettings.Ref.class)
BoxAppSettings m_boxApp = new BoxAppSettings();
@Widget(title = "Type", description = "Authentication method to use.")