From 7564686933e3027a482d717404c6202d70401c4d Mon Sep 17 00:00:00 2001 From: aleksandrovpv
Note: several mutating methods declared in this interface throw
+ * {@link UnsupportedOperationException} when called on a {@link DesignTimeConfiguration}.
+ * Those methods are deprecated — use {@link MutableConfiguration} when you need to call them.
*/
public interface Configuration extends Comparable On {@link io.jmix.flowui.component.genericfilter.configuration.DesignTimeConfiguration}
+ * this method is intended for framework-internal initialization only (e.g. XML loader).
+ * For {@link io.jmix.flowui.component.genericfilter.configuration.RunTimeConfiguration},
+ * use {@link MutableConfiguration#setFilterComponentDefaultValue} instead.
+ *
* @param parameterName a parameter name of filter component
* @param defaultValue a default value
+ * @deprecated use {@link MutableConfiguration} instead
+ * @see MutableConfiguration
*/
+ @Deprecated(since = "3.0", forRemoval = true)
void setFilterComponentDefaultValue(String parameterName, @Nullable Object defaultValue);
/**
@@ -119,7 +152,11 @@ public interface Configuration extends Comparable
+ * This is a convenience alternative to calling {@link #addConfiguration(Configuration)}
+ * followed by {@link #setCurrentConfiguration(Configuration)}, which fails silently when
+ * the configuration is not yet registered at the time {@code setCurrentConfiguration} is
+ * invoked.
+ *
+ * @param configuration the configuration to register and activate
+ */
+ public void addAndSetCurrentConfiguration(Configuration configuration) {
+ addConfiguration(configuration);
+ setCurrentConfiguration(configuration);
+ }
+
+ /**
+ * Refreshes the layout of the current configuration.
+ *
+ * Call this method after programmatically modifying the current configuration's filter
+ * components (e.g. adding a component to the root {@link LogicalFilterComponent}) to force
+ * the filter UI to re-render remove buttons and update the data-loader condition.
+ *
+ * This is a stable public equivalent of the internal {@code refreshCurrentConfigurationLayout()}.
+ */
+ public void refreshCurrentConfiguration() {
+ refreshCurrentConfigurationLayout();
+ }
+
protected void setCurrentConfigurationInternal(Configuration currentConfiguration, boolean fromClient) {
if (configurations.contains(currentConfiguration)
|| getEmptyConfiguration().equals(currentConfiguration)) {
@@ -891,7 +920,8 @@ public void addConfiguration(Configuration configuration) {
*/
public void removeConfiguration(Configuration configuration) {
if (configuration != getEmptyConfiguration()
- && !(configuration instanceof DesignTimeConfiguration)) {
+ && !(configuration instanceof DesignTimeConfiguration)
+ && !(configuration instanceof MutableConfiguration mc && mc.isProtectedFromUserDeletion())) {
configurations.remove(configuration);
configuration.getRootLogicalFilterComponent().getElement().removeFromParent();
diff --git a/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/MutableConfiguration.java b/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/MutableConfiguration.java
new file mode 100644
index 0000000000..b202bf8edd
--- /dev/null
+++ b/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/MutableConfiguration.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2024 Haulmont.
+ *
+ * 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 io.jmix.flowui.component.genericfilter;
+
+import io.jmix.flowui.component.filter.FilterComponent;
+import io.jmix.flowui.component.genericfilter.configuration.DesignTimeConfiguration;
+import io.jmix.flowui.component.genericfilter.configuration.RunTimeConfiguration;
+import io.jmix.flowui.component.logicalfilter.LogicalFilterComponent;
+import org.springframework.lang.Nullable;
+
+/**
+ * A mutable extension of {@link Configuration}.
+ *
+ * {@link RunTimeConfiguration} implements this interface. {@link DesignTimeConfiguration}
+ * only implements the read-only {@link Configuration}.
+ *
+ * Use this interface as the declared type when you need to call mutating methods,
+ * so the compiler catches misuse of {@link DesignTimeConfiguration} at compile time:
+ *
+ * Note: this method iterates over components already added to the root at the time of the call.
+ *
+ * @param modified whether configuration is modified
+ */
+ void setModified(boolean modified);
+
+ /**
+ * Sets whether the given filter component of configuration is modified.
+ * If a filter component is modified, a remove button appears next to it.
+ *
+ * @param filterComponent a filter component
+ * @param modified whether the filter component of configuration is modified
+ */
+ void setFilterComponentModified(FilterComponent filterComponent, boolean modified);
+
+ /**
+ * Sets a default value of the given filter component for the configuration.
+ * This allows the default values to be saved and displayed in the configuration editor.
+ *
+ * @param parameterName a parameter name of filter component
+ * @param defaultValue a default value
+ */
+ void setFilterComponentDefaultValue(String parameterName, @Nullable Object defaultValue);
+
+ /**
+ * Resets the default value of the filter component identified by the parameter name.
+ *
+ * @param parameterName a parameter name of filter component
+ */
+ void resetFilterComponentDefaultValue(String parameterName);
+
+ /**
+ * Sets null as the default value for all configuration filter components.
+ */
+ void resetAllDefaultValues();
+
+ /**
+ * Returns whether the configuration is available for all users.
+ */
+ boolean isAvailableForAllUsers();
+
+ /**
+ * Sets whether the configuration is available for all users.
+ *
+ * @param availableForAllUsers whether the configuration is available for all users
+ */
+ void setAvailableForAllUsers(boolean availableForAllUsers);
+
+ /**
+ * Returns whether this configuration is protected from deletion by the user through the UI.
+ *
+ * When {@code true}, the Remove action in the filter toolbar is hidden for this configuration,
+ * and {@link GenericFilter#removeConfiguration} will not remove it even if called directly.
+ */
+ boolean isProtectedFromUserDeletion();
+
+ /**
+ * Sets whether this configuration is protected from deletion by the user through the UI.
+ *
+ * @param value {@code true} to prevent the user from deleting this configuration
+ */
+ void setProtectedFromUserDeletion(boolean value);
+
+}
diff --git a/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/DesignTimeConfiguration.java b/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/DesignTimeConfiguration.java
index 7509f6e354..08fc2b4402 100644
--- a/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/DesignTimeConfiguration.java
+++ b/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/DesignTimeConfiguration.java
@@ -24,10 +24,14 @@
import io.jmix.flowui.component.genericfilter.GenericFilter;
import io.jmix.flowui.component.logicalfilter.LogicalFilterComponent;
-import org.jspecify.annotations.Nullable;
+import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.Map;
+/**
+ * A read-only configuration defined at design time (e.g. via XML).
+ * Mutating methods inherited from {@link Configuration} throw {@link UnsupportedOperationException}.
+ */
public class DesignTimeConfiguration implements Configuration {
protected final String id;
@@ -107,7 +111,18 @@ public void setFilterComponentModified(FilterComponent filterComponent, boolean
"Use FilterCopyAction to create a modifiable copy of configuration");
}
+ /**
+ * Records the default value for the given filter component parameter.
+ *
+ * Intended for framework-internal initialization only — called by the XML loader
+ * ({@code GenericFilterLoader}) and {@code DesignTimeConfigurationBuilder} when setting up
+ * the configuration. Not deprecated here intentionally: the deprecation on
+ * {@link Configuration#setFilterComponentDefaultValue} discourages calling this method
+ * through a {@link Configuration} reference, but direct calls on this class are valid
+ * during initialization.
+ */
@Override
+ @SuppressWarnings({"deprecation", "removal"})
public void setFilterComponentDefaultValue(String parameterName, @Nullable Object defaultValue) {
Preconditions.checkNotNullArgument(parameterName);
if (isFilterComponentExist(parameterName)) {
diff --git a/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/RunTimeConfiguration.java b/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/RunTimeConfiguration.java
index c187c1f6ad..ea4d11b7f8 100644
--- a/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/RunTimeConfiguration.java
+++ b/jmix-flowui/flowui/src/main/java/io/jmix/flowui/component/genericfilter/configuration/RunTimeConfiguration.java
@@ -22,15 +22,24 @@
import io.jmix.flowui.component.filter.SingleFilterComponentBase;
import io.jmix.flowui.component.genericfilter.Configuration;
import io.jmix.flowui.component.genericfilter.GenericFilter;
+import io.jmix.flowui.component.genericfilter.MutableConfiguration;
import io.jmix.flowui.component.logicalfilter.LogicalFilterComponent;
-import org.jspecify.annotations.Nullable;
+import org.springframework.lang.Nullable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-public class RunTimeConfiguration implements Configuration {
+/**
+ * A runtime (user-created) filter configuration that supports dynamic modification of
+ * its filter components.
+ *
+ * Implements {@link MutableConfiguration} — use that interface as the declared type when
+ * you need compile-time safety against calling mutating methods on a read-only
+ * {@link DesignTimeConfiguration}.
+ */
+public class RunTimeConfiguration implements MutableConfiguration {
protected final String id;
protected final GenericFilter owner;
@@ -40,6 +49,7 @@ public class RunTimeConfiguration implements Configuration {
protected LogicalFilterComponent> rootLogicalFilterComponent;
protected Set{@code
+ * MutableConfiguration config = filter.runtimeConfigurationBuilder()
+ * .id("myConfig")
+ * .buildAndRegister();
+ * config.setModified(true);
+ * }
+ *
+ * @see Configuration
+ * @see RunTimeConfiguration
+ */
+@SuppressWarnings({"deprecation", "removal"})
+public interface MutableConfiguration extends Configuration {
+
+ /**
+ * Returns whether the configuration is modified.
+ * If a filter component is modified, a remove button appears next to it.
+ */
+ boolean isModified();
+
+ /**
+ * Returns whether the given filter component is modified.
+ * If a filter component is modified, a remove button appears next to it.
+ *
+ * @param filterComponent the filter component to check
+ */
+ boolean isFilterComponentModified(FilterComponent filterComponent);
+
+ /**
+ * Sets the name of configuration.
+ *
+ * @param name a configuration name
+ */
+ void setName(@Nullable String name);
+
+ /**
+ * Sets the root logical filter component of configuration.
+ *
+ * @param rootLogicalFilterComponent a root element of configuration
+ */
+ void setRootLogicalFilterComponent(LogicalFilterComponent> rootLogicalFilterComponent);
+
+ /**
+ * Sets whether the configuration is modified.
+ * If a filter component is modified, a remove button appears next to it.
+ *