[Hotfix] Fix dynamic form item show by other item bug (#131)

* Fix dynamic form item show by other item bug
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thirdparty/framework/SeaTunnelOptionRuleWrapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thirdparty/framework/SeaTunnelOptionRuleWrapper.java
index 7a0bfb6..4f5e7c6 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thirdparty/framework/SeaTunnelOptionRuleWrapper.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thirdparty/framework/SeaTunnelOptionRuleWrapper.java
@@ -22,6 +22,7 @@
 import org.apache.seatunnel.api.configuration.util.OptionRule;
 import org.apache.seatunnel.api.configuration.util.RequiredOption;
 import org.apache.seatunnel.app.dynamicforms.AbstractFormOption;
+import org.apache.seatunnel.app.dynamicforms.Constants;
 import org.apache.seatunnel.app.dynamicforms.FormLocale;
 import org.apache.seatunnel.app.dynamicforms.FormOptionBuilder;
 import org.apache.seatunnel.app.dynamicforms.FormStructure;
@@ -40,6 +41,8 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static org.apache.seatunnel.app.common.SeaTunnelConnectorI18n.CONNECTOR_I18N_CONFIG_EN;
@@ -74,20 +77,14 @@
             @NonNull String name) {
         FormLocale locale = new FormLocale();
         List<AbstractFormOption> optionFormOptions = wrapperOptionOptions(name, optionList, locale);
-        List<List<AbstractFormOption>> requiredFormOptions =
+        List<AbstractFormOption> requiredFormOptions =
                 wrapperRequiredOptions(name, requiredList, locale);
 
         FormStructureBuilder formStructureBuilder = FormStructure.builder().name(name);
 
         if (!CollectionUtils.isEmpty(requiredFormOptions)) {
-            requiredFormOptions.forEach(
-                    list -> {
-                        if (CollectionUtils.isEmpty(list)) {
-                            return;
-                        }
-
-                        formStructureBuilder.addFormOption(list.toArray(new AbstractFormOption[1]));
-                    });
+            formStructureBuilder.addFormOption(
+                    requiredFormOptions.toArray(new AbstractFormOption[1]));
         }
 
         if (!CollectionUtils.isEmpty(optionFormOptions)) {
@@ -110,167 +107,177 @@
                 .collect(Collectors.toList());
     }
 
-    private static List<List<AbstractFormOption>> wrapperRequiredOptions(
+    private static List<AbstractFormOption> wrapperRequiredOptions(
             @NonNull String connectorName,
             @NonNull List<RequiredOption> requiredList,
             FormLocale locale) {
-        List<List<AbstractFormOption>> formOptionsList =
-                requiredList.stream()
-                        .map(
+        List<AbstractFormOption> result = new ArrayList<>();
+        requiredList.forEach(
+                requiredOptions -> {
+                    if (requiredOptions instanceof RequiredOption.AbsolutelyRequiredOptions) {
+                        RequiredOption.AbsolutelyRequiredOptions absolutelyRequiredOptions =
+                                (RequiredOption.AbsolutelyRequiredOptions) requiredOptions;
+                        absolutelyRequiredOptions
+                                .getRequiredOption()
+                                .forEach(
+                                        option -> {
+                                            AbstractFormOption requiredFormItem = null;
+                                            for (AbstractFormOption formItem : result) {
+                                                if (formItem.getField().equals(option.key())) {
+                                                    requiredFormItem = formItem;
+                                                    break;
+                                                }
+                                            }
+
+                                            if (requiredFormItem == null) {
+                                                requiredFormItem =
+                                                        wrapperToFormOption(
+                                                                connectorName, option, locale);
+                                                result.add(requiredFormItem);
+                                            }
+
+                                            if (requiredFormItem.getValidate() == null) {
+                                                requiredFormItem.withValidate(
+                                                        ValidateBuilder.builder()
+                                                                .nonEmptyValidateBuilder()
+                                                                .nonEmptyValidate());
+                                            }
+                                        });
+                    } else if (requiredOptions instanceof RequiredOption.BundledRequiredOptions) {
+                        List<Option<?>> bundledRequiredOptions =
+                                ((RequiredOption.BundledRequiredOptions) requiredOptions)
+                                        .getRequiredOption();
+                        List<String> bundledFields =
+                                bundledRequiredOptions.stream()
+                                        .map(requiredOption -> requiredOption.key())
+                                        .collect(Collectors.toList());
+
+                        bundledRequiredOptions.forEach(
                                 option -> {
-                                    if (option
-                                            instanceof RequiredOption.AbsolutelyRequiredOptions) {
-                                        List<AbstractFormOption> collect =
-                                                ((RequiredOption.AbsolutelyRequiredOptions) option)
-                                                        .getRequiredOption().stream()
-                                                                .map(
-                                                                        requiredOption -> {
-                                                                            return wrapperToFormOption(
-                                                                                            connectorName,
-                                                                                            requiredOption,
-                                                                                            locale)
-                                                                                    .withValidate(
-                                                                                            ValidateBuilder
-                                                                                                    .builder()
-                                                                                                    .nonEmptyValidateBuilder()
-                                                                                                    .nonEmptyValidate());
-                                                                        })
-                                                                .collect(Collectors.toList());
-                                        return collect;
-                                    }
-
-                                    if (option instanceof RequiredOption.BundledRequiredOptions) {
-                                        List<Option<?>> bundledRequiredOptions =
-                                                ((RequiredOption.BundledRequiredOptions) option)
-                                                        .getRequiredOption();
-                                        List<String> bundledFields =
-                                                bundledRequiredOptions.stream()
-                                                        .map(requiredOption -> requiredOption.key())
-                                                        .collect(Collectors.toList());
-
-                                        List<AbstractFormOption> collect =
-                                                bundledRequiredOptions.stream()
-                                                        .map(
-                                                                requiredOption -> {
-                                                                    AbstractFormOption
-                                                                            bundledRequiredFormOption =
-                                                                                    wrapperToFormOption(
-                                                                                            connectorName,
-                                                                                            requiredOption,
-                                                                                            locale);
-                                                                    bundledRequiredFormOption
-                                                                            .withValidate(
-                                                                                    ValidateBuilder
-                                                                                            .builder()
-                                                                                            .unionNonEmptyValidateBuilder()
-                                                                                            .fields(
-                                                                                                    bundledFields
-                                                                                                            .toArray(
-                                                                                                                    new String
-                                                                                                                            [1]))
-                                                                                            .unionNonEmptyValidate());
-                                                                    return bundledRequiredFormOption;
-                                                                })
-                                                        .collect(Collectors.toList());
-                                        return collect;
-                                    }
-
-                                    if (option instanceof RequiredOption.ExclusiveRequiredOptions) {
-                                        List<Option<?>> exclusiveOptions =
-                                                ((RequiredOption.ExclusiveRequiredOptions) option)
-                                                        .getExclusiveOptions();
-                                        List<String> exclusiveFields =
-                                                exclusiveOptions.stream()
-                                                        .map(requiredOption -> requiredOption.key())
-                                                        .collect(Collectors.toList());
-
-                                        List<AbstractFormOption> collect =
-                                                exclusiveOptions.stream()
-                                                        .map(
-                                                                requiredOption -> {
-                                                                    AbstractFormOption
-                                                                            exclusiveRequiredFormOption =
-                                                                                    wrapperToFormOption(
-                                                                                                    connectorName,
-                                                                                                    requiredOption,
-                                                                                                    locale)
-                                                                                            .withValidate(
-                                                                                                    ValidateBuilder
-                                                                                                            .builder()
-                                                                                                            .mutuallyExclusiveValidateBuilder()
-                                                                                                            .fields(
-                                                                                                                    exclusiveFields
-                                                                                                                            .toArray(
-                                                                                                                                    new String
-                                                                                                                                            [1]))
-                                                                                                            .mutuallyExclusiveValidate());
-                                                                    return exclusiveRequiredFormOption;
-                                                                })
-                                                        .collect(Collectors.toList());
-                                        return collect;
-                                    }
-
-                                    if (option
-                                            instanceof RequiredOption.ConditionalRequiredOptions) {
-                                        RequiredOption.ConditionalRequiredOptions
-                                                conditionalRequiredOptions =
-                                                        (RequiredOption.ConditionalRequiredOptions)
-                                                                option;
-
-                                        // we only support one field to control a form option, so we
-                                        // only need get condition key from the
-                                        // first expression. And all expression is 'or' and every
-                                        // condition have the same key.
-                                        String conditionKey =
-                                                conditionalRequiredOptions
-                                                        .getExpression()
-                                                        .getCondition()
-                                                        .getOption()
-                                                        .key();
-                                        List<Object> expectValueList = new ArrayList<>();
-                                        Expression expression =
-                                                conditionalRequiredOptions.getExpression();
-                                        expectValueList.add(
-                                                expression
-                                                        .getCondition()
-                                                        .getExpectValue()
-                                                        .toString());
-                                        while (expression.hasNext()) {
-                                            expression = expression.getNext();
-                                            expectValueList.add(
-                                                    expression
-                                                            .getCondition()
-                                                            .getExpectValue()
-                                                            .toString());
+                                    AbstractFormOption bundledRequiredFormOption = null;
+                                    for (AbstractFormOption formItem : result) {
+                                        if (formItem.getField().equals(option.key())) {
+                                            bundledRequiredFormOption = formItem;
+                                            break;
                                         }
-                                        List<AbstractFormOption> collect =
-                                                conditionalRequiredOptions.getRequiredOption()
-                                                        .stream()
-                                                        .map(
-                                                                requiredOption -> {
-                                                                    return wrapperToFormOption(
-                                                                                    connectorName,
-                                                                                    requiredOption,
-                                                                                    locale)
-                                                                            .withShow(
-                                                                                    conditionKey,
-                                                                                    expectValueList)
-                                                                            .withValidate(
-                                                                                    ValidateBuilder
-                                                                                            .builder()
-                                                                                            .nonEmptyValidateBuilder()
-                                                                                            .nonEmptyValidate());
-                                                                })
-                                                        .collect(Collectors.toList());
-                                        return collect;
                                     }
 
-                                    throw new UnSupportWrapperException(
-                                            connectorName, "Unknown", option.toString());
-                                })
-                        .collect(Collectors.toList());
+                                    if (bundledRequiredFormOption == null) {
+                                        bundledRequiredFormOption =
+                                                wrapperToFormOption(connectorName, option, locale);
+                                        result.add(bundledRequiredFormOption);
+                                    }
 
-        return formOptionsList;
+                                    bundledRequiredFormOption.withValidate(
+                                            ValidateBuilder.builder()
+                                                    .unionNonEmptyValidateBuilder()
+                                                    .fields(bundledFields.toArray(new String[1]))
+                                                    .unionNonEmptyValidate());
+                                });
+                    } else if (requiredOptions instanceof RequiredOption.ExclusiveRequiredOptions) {
+                        List<Option<?>> exclusiveOptions =
+                                ((RequiredOption.ExclusiveRequiredOptions) requiredOptions)
+                                        .getExclusiveOptions();
+                        List<String> exclusiveFields =
+                                exclusiveOptions.stream()
+                                        .map(requiredOption -> requiredOption.key())
+                                        .collect(Collectors.toList());
+
+                        exclusiveOptions.forEach(
+                                option -> {
+                                    AbstractFormOption exclusiveRequiredFormOption = null;
+                                    for (AbstractFormOption formItem : result) {
+                                        if (formItem.getField().equals(option.key())) {
+                                            exclusiveRequiredFormOption = formItem;
+                                            break;
+                                        }
+                                    }
+                                    if (exclusiveRequiredFormOption == null) {
+                                        exclusiveRequiredFormOption =
+                                                wrapperToFormOption(connectorName, option, locale);
+
+                                        result.add(exclusiveRequiredFormOption);
+                                    }
+
+                                    exclusiveRequiredFormOption.withValidate(
+                                            ValidateBuilder.builder()
+                                                    .mutuallyExclusiveValidateBuilder()
+                                                    .fields(exclusiveFields.toArray(new String[1]))
+                                                    .mutuallyExclusiveValidate());
+                                });
+                    } else if (requiredOptions
+                            instanceof RequiredOption.ConditionalRequiredOptions) {
+                        RequiredOption.ConditionalRequiredOptions conditionalRequiredOptions =
+                                (RequiredOption.ConditionalRequiredOptions) requiredOptions;
+
+                        // we only support one field to control a form option, so we
+                        // only need get condition key from the
+                        // first expression. And all expression is 'or' and every
+                        // condition have the same key.
+                        String conditionKey =
+                                conditionalRequiredOptions
+                                        .getExpression()
+                                        .getCondition()
+                                        .getOption()
+                                        .key();
+                        List<Object> expectValueList = new ArrayList<>();
+                        Expression expression = conditionalRequiredOptions.getExpression();
+                        expectValueList.add(expression.getCondition().getExpectValue().toString());
+                        while (expression.hasNext()) {
+                            expression = expression.getNext();
+                            expectValueList.add(
+                                    expression.getCondition().getExpectValue().toString());
+                        }
+
+                        conditionalRequiredOptions
+                                .getRequiredOption()
+                                .forEach(
+                                        option -> {
+                                            AbstractFormOption conditionalRequiredFormItem = null;
+                                            for (AbstractFormOption formItem : result) {
+                                                if (formItem.getField().equals(option.key())) {
+                                                    conditionalRequiredFormItem = formItem;
+                                                    break;
+                                                }
+                                            }
+
+                                            if (conditionalRequiredFormItem == null) {
+                                                conditionalRequiredFormItem =
+                                                        wrapperToFormOption(
+                                                                connectorName, option, locale);
+                                                result.add(conditionalRequiredFormItem);
+                                            }
+
+                                            if (conditionalRequiredFormItem.getShow() == null) {
+                                                conditionalRequiredFormItem.withShow(
+                                                        conditionKey, expectValueList);
+                                            } else {
+                                                Map<String, Object> show =
+                                                        conditionalRequiredFormItem.getShow();
+                                                String field =
+                                                        show.get(Constants.SHOW_FIELD).toString();
+                                                if (field.equals(conditionKey)) {
+                                                    Set values =
+                                                            (Set) show.get(Constants.SHOW_VALUE);
+                                                    values.addAll(expectValueList);
+                                                } else {
+                                                    throw new UnSupportWrapperException(
+                                                            connectorName,
+                                                            conditionalRequiredFormItem.getLabel(),
+                                                            "Only support show by one field");
+                                                }
+                                            }
+
+                                            if (conditionalRequiredFormItem.getValidate() == null) {
+                                                conditionalRequiredFormItem.withValidate(
+                                                        ValidateBuilder.builder()
+                                                                .nonEmptyValidateBuilder()
+                                                                .nonEmptyValidate());
+                                            }
+                                        });
+                    }
+                });
+        return result;
     }
 
     private static AbstractFormOption wrapperToFormOption(
diff --git a/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/AbstractFormOption.java b/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/AbstractFormOption.java
index bc3e65c..2f829b5 100644
--- a/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/AbstractFormOption.java
+++ b/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/AbstractFormOption.java
@@ -27,8 +27,10 @@
 import lombok.NonNull;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 @Data
 public abstract class AbstractFormOption<T extends AbstractFormOption, V extends AbstractValidate> {
@@ -75,8 +77,9 @@
             this.show = new HashMap<>();
         }
 
+        Set<Object> valueSet = new HashSet<>(values);
         this.show.put(Constants.SHOW_FIELD, field);
-        this.show.put(Constants.SHOW_VALUE, values);
+        this.show.put(Constants.SHOW_VALUE, valueSet);
         return (T) this;
     }
 
diff --git a/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/FormStructureValidate.java b/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/FormStructureValidate.java
index 74080b6..532c369 100644
--- a/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/FormStructureValidate.java
+++ b/seatunnel-server/seatunnel-dynamicform/src/main/java/org/apache/seatunnel/app/dynamicforms/FormStructureValidate.java
@@ -42,11 +42,13 @@
         List<String> showErrorList = validateShow(formStructure);
         List<String> unionNonErrorList = validateUnionNonEmpty(formStructure);
         List<String> exclusiveErrorList = validateMutuallyExclusive(formStructure);
+        List<String> duplicateFormItemErrorList = validateDuplicateFormItem(formStructure);
 
         apiErrorList.addAll(localeErrorList);
         apiErrorList.addAll(showErrorList);
         apiErrorList.addAll(unionNonErrorList);
         apiErrorList.addAll(exclusiveErrorList);
+        apiErrorList.addAll(duplicateFormItemErrorList);
 
         if (apiErrorList.size() > 0) {
             throw new FormStructureValidateException(formStructure.getName(), apiErrorList);
@@ -267,4 +269,28 @@
 
         return errorMessageList;
     }
+
+    public static List<String> validateDuplicateFormItem(@NonNull FormStructure formStructure) {
+        List fieldList = new ArrayList();
+        List errorFieldList = new ArrayList();
+        List errorMessage = new ArrayList();
+        formStructure
+                .getForms()
+                .forEach(
+                        form -> {
+                            if (fieldList.contains(form.getField())) {
+                                errorFieldList.add(form.getField());
+                            } else {
+                                fieldList.add(form.getField());
+                            }
+                        });
+        if (errorFieldList.size() > 0) {
+            errorMessage.add(
+                    String.format(
+                            "DuplicateFormItemValidate failed, Duplicate form items %s",
+                            errorFieldList));
+        }
+
+        return errorMessage;
+    }
 }