Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion org.knime.core.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ Export-Package: org.knime.core.ui;x-internal:=true,
org.knime.node.parameters.legacy.widget.choices.filter,
org.knime.node.parameters.legacy.widget.credentials,
org.knime.node.parameters.legacy.widget.file,
org.knime.node.parameters.updates.legacy;x-internal:=true,
org.knime.node.parameters.experimental.additionalsave;x-internal:=true,
org.knime.node.parameters.experimental.button;x-internal:=true,
org.knime.node.parameters.experimental.datatype;x-internal:=true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@

import org.knime.core.node.workflow.NodeContext;
import org.knime.core.ui.node.workflow.ContextObjectSupplierUI;
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.ConditionToPredicateTranslator;
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.PredicateInitializerExtensionPoint;
import org.knime.node.parameters.legacy.widget.file.LegacyFileWriter;
import org.knime.node.parameters.legacy.widget.file.LegacyFileWriterPredicateInitializer;
import org.knime.node.parameters.legacy.widget.file.LegacyMultiFileSelectionPredicateInitializer;
import org.knime.node.parameters.updates.ParameterReference;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

Expand All @@ -63,6 +69,24 @@ public class CoreUIPlugin implements BundleActivator {
@Override
public void start(final BundleContext context) throws Exception {
NodeContext.addContextObjectSupplier(new ContextObjectSupplierUI());
registerPredicateInitializerExtensions();
}

private static void registerPredicateInitializerExtensions() {
PredicateInitializerExtensionPoint.register(LegacyMultiFileSelectionPredicateInitializer.class,
predicateCreator -> reference -> new ConditionToPredicateTranslator.LegacyMultiFileSelectionFieldReference(
predicateCreator.apply(reference)));
PredicateInitializerExtensionPoint.register(LegacyFileWriterPredicateInitializer.class,
predicateCreator -> new LegacyFileWriterPredicateInitializer() {

@Override
public <T extends LegacyFileWriter> LegacyFileWriterReference
getLegacyFileWriter(final Class<? extends ParameterReference<T>> reference) {
return new ConditionToPredicateTranslator.LegacyFileWriterFieldReference(
predicateCreator.apply(reference));
}

});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.ArrayReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.BooleanReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.EnumReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.LegacyFileWriterReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.LegacyMultiFileSelectionReference;
import org.knime.node.parameters.legacy.widget.file.LegacyFileWriterPredicateInitializer.LegacyFileWriterReference;
import org.knime.node.parameters.legacy.widget.file.LegacyMultiFileSelectionPredicateInitializer.LegacyMultiFileSelectionReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.MultiFileSelectionReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.StringOrEnumReference;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.StringReference;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* ------------------------------------------------------------------------
*
* 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 <http://www.gnu.org/licenses>.
*
* 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.
* ---------------------------------------------------------------------
*
* History
* Apr 15, 2026 (Paul Bärnreuther): created
*/
package org.knime.core.webui.node.dialog.defaultdialog.impl.predicates;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import org.knime.node.parameters.updates.EffectPredicate;
import org.knime.node.parameters.updates.PredicateInitializerExtension;

/**
* Registry for {@link PredicateInitializerExtension} factories. Extensions are registered at plugin startup (e.g. in
* {@code CoreUIPlugin#start}) and created on demand by the predicate initializer implementation.
*
* @author Paul Bärnreuther
*/
public final class PredicateInitializerExtensionPoint {

/**
* Factory that creates extension instances given a predicate creation capability.
*
* @param <T> the extension type
*/
@FunctionalInterface
public interface ExtensionFactory<T extends PredicateInitializerExtension> {

Check warning on line 72 in org.knime.core.ui/src/eclipse/org/knime/core/webui/node/dialog/defaultdialog/impl/predicates/PredicateInitializerExtensionPoint.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Drop this interface in favor of "java.util.function.Function<Function,T>".

See more on https://sonarcloud.io/project/issues?id=knime_knime-core-ui&issues=AZ2Q_qVxAfTdVnF5GirT&open=AZ2Q_qVxAfTdVnF5GirT&pullRequest=198
/**
* @param predicateCreator maps a reference class to a function that creates predicates from conditions
* @return the extension instance
*/
T create(Function<Class<?>, Function<Condition, EffectPredicate>> predicateCreator);

Check warning on line 77 in org.knime.core.ui/src/eclipse/org/knime/core/webui/node/dialog/defaultdialog/impl/predicates/PredicateInitializerExtensionPoint.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Document this public method by adding an explicit description.

See more on https://sonarcloud.io/project/issues?id=knime_knime-core-ui&issues=AZ2Q_qVxAfTdVnF5GirS&open=AZ2Q_qVxAfTdVnF5GirS&pullRequest=198
}

private static final Map<Class<? extends PredicateInitializerExtension>, ExtensionFactory<?>> REGISTRY =
new ConcurrentHashMap<>();

private PredicateInitializerExtensionPoint() {
}

/**
* Registers an extension factory for the given type.
*
* @param <T> the extension type
* @param type the extension class
* @param factory creates extension instances given predicate creation capability
*/
public static <T extends PredicateInitializerExtension> void register(final Class<T> type,
final ExtensionFactory<T> factory) {
REGISTRY.put(type, factory);
Comment thread
PaulBrnrther marked this conversation as resolved.
}

/**
* Creates an extension instance using the registered factory.
*
* @param <T> the extension type
* @param type the extension class
* @param predicateCreator maps a reference class to a function that creates predicates from conditions
* @return the extension instance
* @throws IllegalArgumentException if no factory is registered for the type
*/
@SuppressWarnings("unchecked")
public static <T extends PredicateInitializerExtension> T createExtension(final Class<T> type,
final Function<Class<?>, Function<Condition, EffectPredicate>> predicateCreator) {
final var factory = (ExtensionFactory<T>)REGISTRY.get(type);
if (factory == null) {
throw new IllegalArgumentException("No PredicateInitializerExtension registered for " + type.getName());
}
return factory.create(predicateCreator);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,16 @@
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.ConstantPredicate;
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.FrameworkPredicate;
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.FrameworkPredicateProvider;
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.PredicateInitializerExtensionPoint;
import org.knime.core.webui.node.dialog.defaultdialog.impl.predicates.ScopedPredicate;
import org.knime.node.parameters.NodeParametersInput;
import org.knime.node.parameters.WidgetGroup;
import org.knime.node.parameters.legacy.widget.file.LegacyFileWriter;
import org.knime.node.parameters.legacy.widget.file.LegacyMultiFileSelection;
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.legacy.LegacyPredicateInitializer;
import org.knime.node.parameters.updates.PredicateInitializerExtension;

class DefaultPredicateInitializer implements LegacyPredicateInitializer {
class DefaultPredicateInitializer implements EffectPredicateProvider.PredicateInitializer {

private ScopeFromReference m_scopeFromReference;

Expand Down Expand Up @@ -165,18 +164,9 @@ public <T> ArrayReference getList(final Class<? extends ParameterReference<List<
}

@Override
public LegacyMultiFileSelectionReference
getLegacyMultiFileSelection(final Class<? extends ParameterReference<LegacyMultiFileSelection>> reference) {
return new ConditionToPredicateTranslator.LegacyMultiFileSelectionFieldReference(
condition -> createPredicate(reference, condition));
}

@Override
public <T extends LegacyFileWriter>
LegacyFileWriterReference
getLegacyFileWriter(final Class<? extends ParameterReference<T>> reference) {
return new ConditionToPredicateTranslator.LegacyFileWriterFieldReference(
condition -> createPredicate(reference, condition));
public <T extends PredicateInitializerExtension> T getRegisteredPredicateInitializer(final Class<T> type) {
return PredicateInitializerExtensionPoint.createExtension(type,
reference -> condition -> createPredicate(reference, condition));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,28 +44,32 @@
* ---------------------------------------------------------------------
*
* History
* 8 Dec 2025 (Thomas Reifenberger): created
* Apr 15, 2026 (Paul Bärnreuther): created
*/
package org.knime.node.parameters.updates.legacy;
package org.knime.node.parameters.legacy.widget.file;

import org.knime.node.parameters.legacy.widget.file.LegacyFileWriter;
import org.knime.node.parameters.legacy.widget.file.LegacyMultiFileSelection;
import org.knime.node.parameters.updates.EffectPredicateProvider;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.EnumReference;
import org.knime.node.parameters.updates.ParameterReference;
import org.knime.node.parameters.updates.PredicateInitializerExtension;
import org.knime.node.parameters.updates.ValueReference;

/**
* Extension for {@link PredicateInitializer} providing predicate support for {@link LegacyFileWriter} fields. Retrieve
* via {@link PredicateInitializer#getRegisteredPredicateInitializer(Class)}.
*
* @author Thomas Reifenberger
* @author Paul Bärnreuther
*/
public interface LegacyPredicateInitializer extends EffectPredicateProvider.PredicateInitializer {
public interface LegacyFileWriterPredicateInitializer extends PredicateInitializerExtension {

/**
* @param reference bound to exactly one {@link LegacyMultiFileSelection} field via {@link ValueReference}
* @return an object that can be further transformed to a predicate using one of its methods
* Returned by {@link #getLegacyFileWriter}
*/
LegacyMultiFileSelectionReference
getLegacyMultiFileSelection(Class<? extends ParameterReference<LegacyMultiFileSelection>> reference);
interface LegacyFileWriterReference {

EnumReference<LegacyFileWriterWithOverwritePolicyOptions.OverwritePolicy> getOverwritePolicy();

}

/**
* @param reference bound to exactly one {@link LegacyFileWriter} field (or one of its subclasses) via
Expand All @@ -73,5 +77,5 @@
* @return an object that can be further transformed to a predicate using one of its methods
*/
<T extends LegacyFileWriter> LegacyFileWriterReference
getLegacyFileWriter(Class<? extends ParameterReference<T>> reference);

Check warning on line 80 in org.knime.core.ui/src/eclipse/org/knime/node/parameters/legacy/widget/file/LegacyFileWriterPredicateInitializer.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Document this public method by adding an explicit description.

See more on https://sonarcloud.io/project/issues?id=knime_knime-core-ui&issues=AZ2Q_qUqAfTdVnF5GirQ&open=AZ2Q_qUqAfTdVnF5GirQ&pullRequest=198
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* ------------------------------------------------------------------------
*
* 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 <http://www.gnu.org/licenses>.
*
* 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.
* ---------------------------------------------------------------------
*
* History
* Apr 15, 2026 (Paul Bärnreuther): created
*/
package org.knime.node.parameters.legacy.widget.file;

import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer;
import org.knime.node.parameters.updates.EffectPredicateProvider.PredicateInitializer.EnumReference;
import org.knime.node.parameters.updates.ParameterReference;
import org.knime.node.parameters.updates.PredicateInitializerExtension;
import org.knime.node.parameters.updates.ValueReference;
import org.knime.node.parameters.widget.file.MultiFileSelectionMode;

/**
* Extension for {@link PredicateInitializer} providing predicate support for {@link LegacyMultiFileSelection} fields.
* Retrieve via {@link PredicateInitializer#getRegisteredPredicateInitializer(Class)}.
*
* @author Paul Bärnreuther
*/
public interface LegacyMultiFileSelectionPredicateInitializer extends PredicateInitializerExtension {

/**
* Returned by {@link #getLegacyMultiFileSelection}
*/
interface LegacyMultiFileSelectionReference {

EnumReference<MultiFileSelectionMode> getSelectionMode();

}

/**
* @param reference bound to exactly one {@link LegacyMultiFileSelection} field via {@link ValueReference}
* @return an object that can be further transformed to a predicate using one of its methods
*/
LegacyMultiFileSelectionReference
getLegacyMultiFileSelection(Class<? extends ParameterReference<LegacyMultiFileSelection>> reference);

Check warning on line 80 in org.knime.core.ui/src/eclipse/org/knime/node/parameters/legacy/widget/file/LegacyMultiFileSelectionPredicateInitializer.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Document this public method by adding an explicit description.

See more on https://sonarcloud.io/project/issues?id=knime_knime-core-ui&issues=AZ2Q_qVIAfTdVnF5GirR&open=AZ2Q_qVIAfTdVnF5GirR&pullRequest=198
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@
import org.knime.node.parameters.NodeParameters;
import org.knime.node.parameters.NodeParametersInput;
import org.knime.node.parameters.WidgetGroup;
import org.knime.node.parameters.legacy.widget.file.LegacyFileWriterWithOverwritePolicyOptions;
import org.knime.node.parameters.updates.legacy.LegacyPredicateInitializer;

/**
* Use the initializer to create a predicate depending on other fields in the current {@link NodeParameters} or the
Expand Down Expand Up @@ -261,28 +259,6 @@ default EffectPredicate isMultiFileSelection() {

}

/**
* Returned by {@link PredicateInitializer#getLegacyMultiFileSelectionMode}
*
* @author Thomas Reifenberger
*/
interface LegacyMultiFileSelectionReference {

EnumReference<MultiFileSelectionMode> getSelectionMode();

}

/**
* Returned by {@link LegacyPredicateInitializer#getLegacyFileWriter}
*
* @author Thomas Reifenberger
*/
interface LegacyFileWriterReference {

EnumReference<LegacyFileWriterWithOverwritePolicyOptions.OverwritePolicy> getOverwritePolicy();

}

/**
* Returned by {@link PredicateInitializer#getArray}
*
Expand Down Expand Up @@ -415,6 +391,17 @@ default EffectPredicate always() {
*/
EffectPredicate getPredicate(EffectPredicateProvider predicateProvider);

/**
* Retrieves a registered {@link PredicateInitializerExtension} by its type. Extensions are registered at
* startup and provide additional predicate capabilities beyond the built-in ones.
*
* @param <T> the type of the extension
* @param type the class of the extension to retrieve
* @return the extension instance
Comment thread
PaulBrnrther marked this conversation as resolved.
* @throws IllegalArgumentException if no extension of the requested type is registered
*/
<T extends PredicateInitializerExtension> T getRegisteredPredicateInitializer(Class<T> type);

}

/**
Expand Down
Loading