diff --git a/.gitignore b/.gitignore index ca2137dc16..923742b631 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,4 @@ ui.tests/test-module/**/*.cy.json # Agent working artifacts docs/superpowers/ +.worktrees/ diff --git a/bundles/af-core/pom.xml b/bundles/af-core/pom.xml index 005a72f7b5..77afbc9358 100644 --- a/bundles/af-core/pom.xml +++ b/bundles/af-core/pom.xml @@ -115,6 +115,38 @@ com.github.spotbugs spotbugs-maven-plugin + + + org.apache.maven.plugins + maven-resources-plugin + + + copy-authoring-schemas-from-docs + generate-test-resources + + copy-resources + + + + ${project.build.testOutputDirectory}/authoring-schema + + + ${project.basedir}/../../docs/authoring-schema + + **/*.yaml + + false + + + + + + @@ -587,6 +619,12 @@ test + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + test + + com.sun.xml.bind jaxb-core diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/Heading.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/Heading.java index f06e05740e..3837f517b9 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/Heading.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/Heading.java @@ -18,12 +18,7 @@ import org.apache.commons.lang3.StringUtils; public enum Heading { - H1("h1"), - H2("h2"), - H3("h3"), - H4("h4"), - H5("h5"), - H6("h6"); + H1("h1"), H2("h2"), H3("h3"), H4("h4"), H5("h5"), H6("h6"); private String element; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/datalayer/ComponentDataImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/datalayer/ComponentDataImpl.java index 135a17d34a..b6146d2c7d 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/datalayer/ComponentDataImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/datalayer/ComponentDataImpl.java @@ -45,13 +45,14 @@ public class ComponentDataImpl implements FormComponentData { /** * Creates a new ComponentDataImpl instance. * - * Note: This constructor stores references to FormComponent and Resource objects. - * These objects are designed to be immutable and shared across the system. - * The FormComponent interface provides read-only access to form component data, - * and the Resource interface represents an immutable JCR resource. + * Note: This constructor stores references to FormComponent and Resource objects. These objects are designed to be + * immutable and shared across the system. The FormComponent interface provides read-only access to form component + * data, and the Resource interface represents an immutable JCR resource. * - * @param component The form component (immutable, read-only interface) - * @param resource The JCR resource (immutable, read-only interface) + * @param component + * The form component (immutable, read-only interface) + * @param resource + * The JCR resource (immutable, read-only interface) */ @SuppressFBWarnings( value = "EI_EXPOSE_REP2", @@ -161,9 +162,7 @@ public String getFieldType() { @Nullable public final String getJson() { try { - return String.format("{\"%s\":%s}", - this.getId(), - new ObjectMapper().writeValueAsString(this)); + return String.format("{\"%s\":%s}", this.getId(), new ObjectMapper().writeValueAsString(this)); } catch (JsonProcessingException e) { LOGGER.error("Unable to generate dataLayer JSON string", e); } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FeatureToggleConstants.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FeatureToggleConstants.java index 5f42d10ffe..2f7642c76c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FeatureToggleConstants.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FeatureToggleConstants.java @@ -16,18 +16,18 @@ package com.adobe.cq.forms.core.components.internal.form; /** - * Feature toggle identifiers for form components. When a toggle is enabled, the corresponding - * behavior is active; when disabled or when the toggle service is absent, legacy behavior is used. + * Feature toggle identifiers for form components. When a toggle is enabled, the corresponding behavior is active; when + * disabled or when the toggle service is absent, legacy behavior is used. *

- * Toggles are driven by system properties. Code checks only the system property; the property is - * set/unset by the Granite Toggle API when you wire a toggle to it via OSGi. Setup: + * Toggles are driven by system properties. Code checks only the system property; the property is set/unset by the + * Granite Toggle API when you wire a toggle to it via OSGi. Setup: *

    - *
  1. Enable the toggle: In the Web Console (configMgr), find "Adobe Granite - * Dynamic Toggle Provider" and add the toggle ID (e.g. {@link #FT_FRAGMENT_MERGE_CONTAINER_RULES_EVENTS}) - * to the Enabled Toggles list. You can verify the toggle is active via the web console.
  2. + *
  3. Enable the toggle: In the Web Console (configMgr), find "Adobe Granite Dynamic Toggle Provider" + * and add the toggle ID (e.g. {@link #FT_FRAGMENT_MERGE_CONTAINER_RULES_EVENTS}) to the Enabled Toggles list. + * You can verify the toggle is active via the web console.
  4. *
  5. Wire toggle to a system property: Add an OSGi factory configuration for - * {@code com.adobe.granite.toggle.monitor.systemproperty} (the ToggleMonitorSystemPropertyFactory). - * Use the same name for toggle and system property. Example JSON config: + * {@code com.adobe.granite.toggle.monitor.systemproperty} (the ToggleMonitorSystemPropertyFactory). Use the same name + * for toggle and system property. Example JSON config: * *
      * {@code
    @@ -39,49 +39,50 @@
      * }
      * 
    * - * The segment after {@code ~} is a unique instance name. When the toggle is enabled, the factory - * sets the system property; when disabled, it unsets it.
  6. - *
  7. In code: Use {@link com.adobe.cq.forms.core.components.util.ComponentUtils#isToggleEnabled(String)} - * with the toggle ID; it reads the system property (value {@code "true"} means enabled).
  8. + * The segment after {@code ~} is a unique instance name. When the toggle is enabled, the factory sets the system + * property; when disabled, it unsets it. + *
  9. In code: Use + * {@link com.adobe.cq.forms.core.components.util.ComponentUtils#isToggleEnabled(String)} with the toggle ID; it reads + * the system property (value {@code "true"} means enabled).
  10. *
- * You can also enable a toggle for local or override use by setting the JVM system property - * directly (e.g. {@code -DFT_FORMS-24087=true}) without the OSGi config. + * You can also enable a toggle for local or override use by setting the JVM system property directly (e.g. + * {@code -DFT_FORMS-24087=true}) without the OSGi config. */ public final class FeatureToggleConstants { private FeatureToggleConstants() {} /** - * When enabled, fragment container rules and events are merged with the fragment placeholder - * (panel) rules and events: for rules the panel overrides the container for the same key; for - * events panel handlers run first then fragment handlers are appended. When disabled, only the - * panel rules and events are used; fragment container rules/events are not merged. + * When enabled, fragment container rules and events are merged with the fragment placeholder (panel) rules and + * events: for rules the panel overrides the container for the same key; for events panel handlers run first then + * fragment handlers are appended. When disabled, only the panel rules and events are used; fragment container + * rules/events are not merged. *

- * System property: same name ({@code FT_FORMS-24087}); set to {@code "true"} to enable when - * using {@code ToggleMonitorSystemPropertyFactory} or for direct -D JVM override. + * System property: same name ({@code FT_FORMS-24087}); set to {@code "true"} to enable when using + * {@code ToggleMonitorSystemPropertyFactory} or for direct -D JVM override. */ public static final String FT_FRAGMENT_MERGE_CONTAINER_RULES_EVENTS = "FT_FORMS-24087"; /** - * When enabled, the default {@code custom:setProperty} event handler ({@code "$event.payload"}) - * is no longer injected into the model JSON by the server. The af2-web-runtime provides this - * default at the client side, reducing JSON payload size for every form component. + * When enabled, the default {@code custom:setProperty} event handler ({@code "$event.payload"}) is no longer + * injected into the model JSON by the server. The af2-web-runtime provides this default at the client side, + * reducing JSON payload size for every form component. *

- * Prerequisite: the af2-web-runtime must include the corresponding fallback - * in {@code Scriptable.getCompiledEvent} before this toggle is enabled. + * Prerequisite: the af2-web-runtime must include the corresponding fallback in + * {@code Scriptable.getCompiledEvent} before this toggle is enabled. *

* System property: same name ({@code FT_FORMS-24343}); set to {@code "true"} to enable. */ public static final String FT_SKIP_DEFAULT_SET_PROPERTY_EVENT = "FT_FORMS-24343"; /** - * When enabled, container components (panels, wizards, fragments, form containers) export their - * children as a flat {@code "items"} JSON array instead of the Sling Model Exporter's default - * {@code ":items"} map + {@code ":itemsOrder"} array. This reduces JSON payload size by - * eliminating the redundant resource-name keys and the separate ordering array. + * When enabled, container components (panels, wizards, fragments, form containers) export their children as a flat + * {@code "items"} JSON array instead of the Sling Model Exporter's default {@code ":items"} map + + * {@code ":itemsOrder"} array. This reduces JSON payload size by eliminating the redundant resource-name keys and + * the separate ordering array. *

- * Prerequisite: the af2-web-runtime already supports the {@code items} array - * format natively via {@code Container._initialize()}. + * Prerequisite: the af2-web-runtime already supports the {@code items} array format natively via + * {@code Container._initialize()}. *

* System property: same name ({@code FT_FORMS-24358}); set to {@code "true"} to enable. */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormClientLibManagerImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormClientLibManagerImpl.java index 6d78f06375..d131213304 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormClientLibManagerImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormClientLibManagerImpl.java @@ -29,9 +29,7 @@ import com.adobe.cq.forms.core.components.models.form.FormClientLibManager; -@Model( - adaptables = { SlingHttpServletRequest.class }, - adapters = FormClientLibManager.class) +@Model(adaptables = { SlingHttpServletRequest.class }, adapters = FormClientLibManager.class) public class FormClientLibManagerImpl implements FormClientLibManager { @SlingObject(injectionStrategy = InjectionStrategy.OPTIONAL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConfigurationProviderImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConfigurationProviderImpl.java index 99f71609a0..698dc2a19b 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConfigurationProviderImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConfigurationProviderImpl.java @@ -28,9 +28,7 @@ import com.adobe.cq.forms.core.components.models.form.FormConfigurationProvider; -@Model( - adaptables = { Resource.class }, - adapters = FormConfigurationProvider.class) +@Model(adaptables = { Resource.class }, adapters = FormConfigurationProvider.class) public class FormConfigurationProviderImpl implements FormConfigurationProvider { private static final String CUSTOM_FUNCTION_CONFIG_BUCKET_NAME = "settings/cloudconfigs"; @@ -51,8 +49,8 @@ public class FormConfigurationProviderImpl implements FormConfigurationProvider public String getCustomFunctionModuleUrl() { String customFunctionUrl = ""; if (resource != null && configurationResourceResolver != null) { - Resource configResource = configurationResourceResolver.getResource(resource, CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, - CUSTOM_FUNCTION_CONFIG_NAME); + Resource configResource = configurationResourceResolver.getResource(resource, + CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, CUSTOM_FUNCTION_CONFIG_NAME); if (configResource != null) { Resource jcrResource = configResource.getChild(JcrConstants.JCR_CONTENT); if (jcrResource != null) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java index bb441d8366..fa55d884ba 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormConstants.java @@ -127,10 +127,12 @@ private FormConstants() { /** The resource type for fragment v1 */ public static final String RT_FD_FORM_FRAGMENT_V1 = RT_FD_FORM_PREFIX + "fragment/v1/fragment"; - public static final String RT_FD_FRAGMENT_CONTAINER_V1 = RT_FD_FORM_PREFIX + "fragmentcontainer/v1/fragmentcontainer"; + public static final String RT_FD_FRAGMENT_CONTAINER_V1 = RT_FD_FORM_PREFIX + + "fragmentcontainer/v1/fragmentcontainer"; /** The resource type for terms and conditions v1 */ - public static final String RT_FD_FORM_TERMS_AND_CONDITIONS_V1 = RT_FD_FORM_PREFIX + "termsandconditions/v1/termsandconditions"; + public static final String RT_FD_FORM_TERMS_AND_CONDITIONS_V1 = RT_FD_FORM_PREFIX + + "termsandconditions/v1/termsandconditions"; public static final String FORM_FIELD_TYPE = "form"; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormStructureParserImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormStructureParserImpl.java index 7240d000c9..aa93c732da 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormStructureParserImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/FormStructureParserImpl.java @@ -42,9 +42,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; -@Model( - adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = FormStructureParser.class) +@Model(adaptables = { SlingHttpServletRequest.class, Resource.class }, adapters = FormStructureParser.class) public class FormStructureParserImpl implements FormStructureParser { private static final Logger logger = LoggerFactory.getLogger(FormStructureParserImpl.class); @SlingObject(injectionStrategy = InjectionStrategy.OPTIONAL) @@ -78,7 +76,8 @@ public String getThemeEditorThemeRef() { } // get client library from theme content path if (StringUtils.isNotBlank(themeContentPath)) { - Resource themeResource = resource.getResourceResolver().getResource(themeContentPath + ThemeConstants.RELATIVE_PATH_METADATA); + Resource themeResource = resource.getResourceResolver() + .getResource(themeContentPath + ThemeConstants.RELATIVE_PATH_METADATA); if (themeResource != null) { ValueMap themeProps = themeResource.getValueMap(); themeClientLibRef = themeProps.get(ThemeConstants.PROPERTY_CLIENTLIB_CATEGORY, ""); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/HtlUtilImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/HtlUtilImpl.java index 658735c917..0ee7007507 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/HtlUtilImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/HtlUtilImpl.java @@ -24,9 +24,7 @@ import com.adobe.cq.forms.core.components.models.form.HtlUtil; -@Model( - adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = HtlUtil.class) +@Model(adaptables = { SlingHttpServletRequest.class, Resource.class }, adapters = HtlUtil.class) public class HtlUtilImpl implements HtlUtil { @SlingObject(injectionStrategy = InjectionStrategy.OPTIONAL) @Nullable @@ -34,7 +32,8 @@ public class HtlUtilImpl implements HtlUtil { public Boolean isEdgeDeliveryRequest() { if (request != null) { - Object isEdgeDelivery = request.getAttribute("com.adobe.aem.wcm.franklin.internal.servlets.FranklinDeliveryServlet"); + Object isEdgeDelivery = request + .getAttribute("com.adobe.aem.wcm.franklin.internal.servlets.FranklinDeliveryServlet"); return isEdgeDelivery != null && isEdgeDelivery.equals(Boolean.TRUE); } return false; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java index 4942f5ad74..1b2c2de85a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/form/ReservedProperties.java @@ -104,23 +104,27 @@ private ReservedProperties() { public static final String PN_IS_TITLE_RICH_TEXT = "isTitleRichText"; public static final String PN_ORIENTATION = "orientation"; public static final String PN_TYPE_MESSAGE = "typeMessage"; - public static final String PN_REQUIRED_MESSAGE = "mandatoryMessage"; // reusing the same property name as in foundation + public static final String PN_REQUIRED_MESSAGE = "mandatoryMessage"; // reusing the same property name as in + // foundation public static final String PN_MINIMUM_MESSAGE = "minimumMessage"; public static final String PN_MAXIMUM_MESSAGE = "maximumMessage"; public static final String PN_MINLENGTH_MESSAGE = "minLengthMessage"; public static final String PN_MAXLENGTH_MESSAGE = "maxLengthMessage"; - public static final String PN_MAX_FILE_SIZE_MESSAGE = "maxFileSizeMessage"; // for fileInput min, max number of files, maximum file size + public static final String PN_MAX_FILE_SIZE_MESSAGE = "maxFileSizeMessage"; // for fileInput min, max number of + // files, maximum file size // and accept of file type messages public static final String PN_ACCEPT_MESSAGE = "acceptMessage"; public static final String PN_STEP_MESSAGE = "stepMessage"; public static final String PN_FORMAT_MESSAGE = "formatMessage"; public static final String PN_PATTERN = "pattern"; - public static final String PN_PATTERN_MESSAGE = "validatePictureClauseMessage"; // reusing the same property name as in foundation + public static final String PN_PATTERN_MESSAGE = "validatePictureClauseMessage"; // reusing the same property name as + // in foundation public static final String PN_MINITEMS_MESSAGE = "minItemsMessage"; public static final String PN_MAXITEMS_MESSAGE = "maxItemsMessage"; public static final String PN_UNIQUE_ITEMS_MESSAGE = "uniqueItemsMessage"; public static final String PN_ENFORCE_ENUM_MESSAGE = "enforceEnumMessage"; - public static final String PN_VALIDATION_EXPRESSION_MESSAGE = "validateExpMessage"; // reusing the same property name as in foundation + public static final String PN_VALIDATION_EXPRESSION_MESSAGE = "validateExpMessage"; // reusing the same property + // name as in foundation public static final String PN_MULTISELECT = "multiSelect"; public static final String PN_MULTISELECTION = "multiSelection"; public static final String PN_ENABLE_UNCHECKED_VALUE = "enableUncheckedValue"; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ButtonImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ButtonImpl.java index 6597f80a1b..2e0d23d201 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ButtonImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ButtonImpl.java @@ -43,9 +43,10 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { Button.class, ComponentExporter.class }, - resourceType = { FormConstants.RT_FD_FORM_BUTTON_V1, FormConstants.RT_FD_FORM_SUBMIT_BUTTON_V1, - FormConstants.RT_FD_FORM_RESET_BUTTON_V1 }) + adapters = { Button.class, + ComponentExporter.class }, + resourceType = { FormConstants.RT_FD_FORM_BUTTON_V1, + FormConstants.RT_FD_FORM_SUBMIT_BUTTON_V1, FormConstants.RT_FD_FORM_RESET_BUTTON_V1 }) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class ButtonImpl extends AbstractBaseImpl implements Button { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImpl.java index e82837fbcb..c0c1e63dd0 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImpl.java @@ -82,7 +82,8 @@ public Integer getMaxItems() { @Override public Type getType() { - return super.getType(); // check box group always has type array // we always return boolean[], string[] or number[] + return super.getType(); // check box group always has type array // we always return boolean[], string[] or + // number[] } @Override diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImpl.java index 92b66c8c14..ed77629e52 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImpl.java @@ -28,9 +28,8 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { CheckBox.class, ComponentExporter.class }, + adapters = { CheckBox.class, + ComponentExporter.class }, resourceType = { FormConstants.RT_FD_FORM_CHECKBOX_V1 }) -@Exporter( - name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, - extensions = ExporterConstants.SLING_MODEL_EXTENSION) +@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class CheckBoxImpl extends AbstractCheckboxImpl implements CheckBox {} diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImpl.java index 69ed63840d..649fc42eba 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImpl.java @@ -44,10 +44,8 @@ adaptables = { SlingHttpServletRequest.class, Resource.class }, adapters = { DatePicker.class, ComponentExporter.class }, - resourceType = { - FormConstants.RT_FD_FORM_DATE_PICKER_V1, - FormConstants.RT_FD_FORM_DATE_PICKER_V2 - }) + resourceType = { FormConstants.RT_FD_FORM_DATE_PICKER_V1, + FormConstants.RT_FD_FORM_DATE_PICKER_V2 }) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class DatePickerImpl extends AbstractFieldImpl implements DatePicker { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DateTimeImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DateTimeImpl.java index 2c9372cc6a..01522bc6a7 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DateTimeImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DateTimeImpl.java @@ -40,11 +40,10 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { DateTime.class, ComponentExporter.class }, + adapters = { DateTime.class, + ComponentExporter.class }, resourceType = { FormConstants.RT_FD_FORM_DATETIME_V1 }) -@Exporter( - name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, - extensions = ExporterConstants.SLING_MODEL_EXTENSION) +@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class DateTimeImpl extends AbstractFieldImpl implements DateTime { @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImpl.java index 1753357a3c..eae4a3b618 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImpl.java @@ -117,9 +117,7 @@ public String getButtonText() { @Override public List getAccept() { - return Optional.ofNullable(accept) - .map(Arrays::asList) - .orElse(Collections.emptyList()); + return Optional.ofNullable(accept).map(Arrays::asList).orElse(Collections.emptyList()); } @Override diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImpl.java index 1a6c190269..8d51474546 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImpl.java @@ -55,7 +55,8 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { FormContainer.class, ContainerExporter.class, ComponentExporter.class }, + adapters = { FormContainer.class, + ContainerExporter.class, ComponentExporter.class }, resourceType = { FormConstants.RT_FD_FORM_CONTAINER_V1 }) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class FormContainerImpl extends AbstractComponentImpl implements FormContainer { @@ -156,8 +157,8 @@ public List getItems() { @JsonIgnore public Map getModel() { Map jsonMap = null; - if (StringUtils.isNotEmpty(documentPath) - && this.request != null && this.request.getResourceResolver().getResource(documentPath) != null) { + if (StringUtils.isNotEmpty(documentPath) && this.request != null + && this.request.getResourceResolver().getResource(documentPath) != null) { // the json is coming from DAM final Resource assetResource = request.getResourceResolver().getResource(documentPath); if (assetResource != null) { @@ -171,8 +172,8 @@ public Map getModel() { logger.error("Unable to read json from resource '{}'", documentPath); } } else { - logger.error("Unable to adapt resource '{}' used by form container '{}' to an asset.", documentPath, resource - .getPath()); + logger.error("Unable to adapt resource '{}' used by form container '{}' to an asset.", documentPath, + resource.getPath()); } } } else { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImpl.java index d7d8d2fc3e..82d18488e4 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImpl.java @@ -63,11 +63,10 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { Fragment.class, ComponentExporter.class }, + adapters = { Fragment.class, + ComponentExporter.class }, resourceType = { FormConstants.RT_FD_FORM_FRAGMENT_V1 }) -@Exporter( - name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, - extensions = ExporterConstants.SLING_MODEL_EXTENSION) +@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class FragmentImpl extends PanelImpl implements Fragment { public static final String CUSTOM_FRAGMENT_PROPERTY_WRAPPER = "fd:fragment"; @@ -136,7 +135,8 @@ public boolean getLazy() { return new LinkedHashMap<>(itemModels); } - protected Map getChildrenModels(@Nullable SlingHttpServletRequest request, @NotNull Class modelClass) { + protected Map getChildrenModels(@Nullable SlingHttpServletRequest request, + @NotNull Class modelClass) { if (fragmentContainer == null) { return new LinkedHashMap<>(); } @@ -159,7 +159,8 @@ public Object getAttribute(String attrName) { } }; } - Map models = getChildrenModels(wrappedSlingHttpServletRequest, modelClass, filteredChildrenResources); + Map models = getChildrenModels(wrappedSlingHttpServletRequest, modelClass, + filteredChildrenResources); // Set i18n for fragment children since they are processed with request != null // Use fragment container-specific i18n to ensure correct resource bundle path @@ -178,9 +179,8 @@ public Object getAttribute(String attrName) { } /** - * Creates a new I18n object for fragment children using the fragment container resource path - * instead of the parent form's resource path. This ensures that fragment children use the - * correct resource bundle path for translations. + * Creates a new I18n object for fragment children using the fragment container resource path instead of the parent + * form's resource path. This ensures that fragment children use the correct resource bundle path for translations. * * @return a new I18n object configured for the fragment container resource */ @@ -199,7 +199,8 @@ public Object getAttribute(String attrName) { // Use the fragment container's resource bundle if available resourceBundle = resourceBundleProvider.getResourceBundle(baseName, desiredLocale); } else { - // Fallback to a random UUID-based resource bundle if fragment-specific translations are not available + // Fallback to a random UUID-based resource bundle if fragment-specific translations are not + // available resourceBundle = resourceBundleProvider.getResourceBundle("/" + UUID.randomUUID(), desiredLocale); } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HCaptchaImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HCaptchaImpl.java index ad27b1d95f..6603b9c20a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HCaptchaImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HCaptchaImpl.java @@ -96,7 +96,8 @@ public Map getCaptchaProperties() throws GuideException { String siteKey = null, uri = null; resource = resourceResolver.getResource(this.getPath()); if (cloudConfigurationProvider == null) { - LOGGER.info("[AF] [Captcha] [HCAPTCHA] Error while fetching cloud configuration, upgrade to latest release to use hCaptcha."); + LOGGER.info( + "[AF] [Captcha] [HCAPTCHA] Error while fetching cloud configuration, upgrade to latest release to use hCaptcha."); } try { if (resource != null && cloudConfigurationProvider != null) { @@ -107,7 +108,8 @@ public Map getCaptchaProperties() throws GuideException { } } } catch (GuideException e) { - LOGGER.error("[AF] [Captcha] [HCAPTCHA] Error while fetching cloud configuration, upgrade to latest release to use hCaptcha."); + LOGGER.error( + "[AF] [Captcha] [HCAPTCHA] Error while fetching cloud configuration, upgrade to latest release to use hCaptcha."); } customCaptchaProperties.put(CAPTCHA_SITE_KEY, siteKey); customCaptchaProperties.put(CAPTCHA_URI, uri); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java index 379c78298e..96a1917b56 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImpl.java @@ -137,10 +137,10 @@ public String getFieldType() { @PostConstruct private void initNumberInput() { - Object tempExclusiveMaximumValue = ComponentUtils.getExclusiveValue(exclusiveMaximum, maximumAsStr != null ? maximumAsStr : maximum, - excludeMaximumCheck); - Object tempExclusiveMinimumValue = ComponentUtils.getExclusiveValue(exclusiveMinimum, minimumAsStr != null ? minimumAsStr : minimum, - excludeMinimumCheck); + Object tempExclusiveMaximumValue = ComponentUtils.getExclusiveValue(exclusiveMaximum, + maximumAsStr != null ? maximumAsStr : maximum, excludeMaximumCheck); + Object tempExclusiveMinimumValue = ComponentUtils.getExclusiveValue(exclusiveMinimum, + minimumAsStr != null ? minimumAsStr : minimum, excludeMinimumCheck); if (tempExclusiveMaximumValue != null) { exclusiveMaximumValue = ComponentUtils.parseNumber(tempExclusiveMaximumValue.toString()); } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImpl.java index 0d32ad9502..811ac3d41b 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImpl.java @@ -42,7 +42,8 @@ adaptables = { SlingHttpServletRequest.class, Resource.class }, adapters = { Panel.class, ComponentExporter.class }, - resourceType = { FormConstants.RT_FD_FORM_PANEL_V1, FormConstants.RT_FD_FORM_ACCORDION_V1, FormConstants.RT_FD_FORM_TABS_ON_TOP_V1, + resourceType = { FormConstants.RT_FD_FORM_PANEL_V1, + FormConstants.RT_FD_FORM_ACCORDION_V1, FormConstants.RT_FD_FORM_TABS_ON_TOP_V1, FormConstants.RT_FD_FORM_WIZARD_V1, FormConstants.RT_FD_FORM_VERTICAL_TABS_V1 }) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) @@ -96,7 +97,8 @@ public class PanelImpl extends AbstractContainerImpl implements Panel { @JsonIgnore @Override public Boolean isRequired() { - return false; // overriding since base is defining isRequired, to avoid creating a new interface, added jsonIgnore here + return false; // overriding since base is defining isRequired, to avoid creating a new interface, added + // jsonIgnore here } @Override diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ScribbleImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ScribbleImpl.java index c8a5f2e807..53422807a6 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ScribbleImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ScribbleImpl.java @@ -38,11 +38,10 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { Scribble.class, ComponentExporter.class }, + adapters = { Scribble.class, + ComponentExporter.class }, resourceType = "core/fd/components/form/scribble/v1/scribble") -@Exporter( - name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, - extensions = ExporterConstants.SLING_MODEL_EXTENSION) +@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class ScribbleImpl extends AbstractFieldImpl implements Scribble { @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/StaticImageImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/StaticImageImpl.java index 41c97c3124..933dc7debc 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/StaticImageImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/StaticImageImpl.java @@ -42,11 +42,10 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { StaticImage.class, ComponentExporter.class }, + adapters = { StaticImage.class, + ComponentExporter.class }, resourceType = { FormConstants.RT_FD_FORM_IMAGE_V1 }) -@Exporter( - name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, - extensions = ExporterConstants.SLING_MODEL_EXTENSION) +@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class StaticImageImpl extends AbstractFormComponentImpl implements StaticImage { public static final String DAM_REPO_PATH = "fd:repoPath"; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImpl.java index ba467f2eab..8f1b1b4ebe 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImpl.java @@ -96,12 +96,12 @@ protected List getFilteredChildrenResources() { List childResources = getFilteredChildrenResources(resource); // the tnc component will either have links or consent text based upon showLink value if (showLink) { - childResources.removeIf(child -> FieldType.PLAIN_TEXT.getValue().equals(child.getValueMap().get( - ReservedProperties.PN_FIELDTYPE))); + childResources.removeIf(child -> FieldType.PLAIN_TEXT.getValue() + .equals(child.getValueMap().get(ReservedProperties.PN_FIELDTYPE))); } else { - childResources.removeIf(child -> FieldType.CHECKBOX_GROUP.getValue().equals(child.getValueMap().get( - ReservedProperties.PN_FIELDTYPE))); + childResources.removeIf(child -> FieldType.CHECKBOX_GROUP.getValue() + .equals(child.getValueMap().get(ReservedProperties.PN_FIELDTYPE))); } return childResources; } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImpl.java index de6d93342a..0eb223b1ed 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImpl.java @@ -17,12 +17,12 @@ import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; -import org.apache.sling.models.annotations.Default; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; +import org.jetbrains.annotations.Nullable; import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; @@ -32,6 +32,8 @@ import com.adobe.cq.forms.core.components.models.form.Text; import com.adobe.cq.forms.core.components.util.AbstractFormComponentImpl; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, @@ -42,8 +44,8 @@ public class TextImpl extends AbstractFormComponentImpl implements Text { @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_TEXT_IS_RICH) - @Default(booleanValues = false) - private boolean textIsRich; + @Nullable + private Boolean textIsRich; @SlingObject private Resource resource; @@ -54,7 +56,24 @@ public String getValue() { } @Override + @JsonIgnore public boolean isRichText() { + return textIsRich != null && textIsRich; + } + + /** + * Returns the rich-text flag for JSON serialization, or {@code null} when not authored in JCR. + * + *

+ * Behavior change: When {@code textIsRich} is absent from JCR, this returns {@code null} and the + * {@code richText} key is omitted from the JSON model (via {@code @JsonInclude(NON_NULL)}). Previously the + * field used {@code @Default(false)}, which caused {@code "richText": false} to always appear in the JSON even when + * the dialog default was unchanged. Downstream consumers must treat an absent {@code richText} key as {@code false} + * — the AF2 runtime already does this. + */ + @JsonProperty("richText") + @JsonInclude(JsonInclude.Include.NON_NULL) + public Boolean getRichText() { return textIsRich; } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImpl.java index 150f6bc9fc..177ae1fdf9 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImpl.java @@ -39,11 +39,11 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { TextInput.class, ComponentExporter.class }, - resourceType = { FormConstants.RT_FD_FORM_TEXT_V1, FormConstants.RT_FD_FORM_EMAIL_V1, FormConstants.RT_FD_FORM_TELEPHONE_V1 }) -@Exporter( - name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, - extensions = ExporterConstants.SLING_MODEL_EXTENSION) + adapters = { TextInput.class, + ComponentExporter.class }, + resourceType = { FormConstants.RT_FD_FORM_TEXT_V1, FormConstants.RT_FD_FORM_EMAIL_V1, + FormConstants.RT_FD_FORM_TELEPHONE_V1 }) +@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class TextInputImpl extends AbstractFieldImpl implements TextInput { // type number and date are implemented in sling model as per crispr specification diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImpl.java index 4bc9b628a0..9b66bd3413 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImpl.java @@ -44,7 +44,8 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { Title.class, ComponentExporter.class }, + adapters = { Title.class, + ComponentExporter.class }, resourceType = FormConstants.RT_FD_FORM_TITLE_V1) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) @@ -122,9 +123,7 @@ public String getType() { @Override @NotNull protected ComponentData getComponentData() { - return DataLayerBuilder.extending(super.getComponentData()).asComponent() - .withTitle(this::getText) - .build(); + return DataLayerBuilder.extending(super.getComponentData()).asComponent().withTitle(this::getText).build(); } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImpl.java index d1f3991b9e..807ab5d5c8 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImpl.java @@ -91,8 +91,7 @@ public String getSize() { } /** - * Set the turnstileConfiguration, by fetching it from the cloud configurations. - * Also sets the captchaSiteKey. + * Set the turnstileConfiguration, by fetching it from the cloud configurations. Also sets the captchaSiteKey. */ private void setTurnstileConfiguration() { LOGGER.debug("[AF] [Captcha] [TURNSTILE] Fetching cloud configuration for turnstile."); @@ -103,11 +102,13 @@ private void setTurnstileConfiguration() { if (turnstileConfiguration != null) { captchaSiteKey = turnstileConfiguration.getSiteKey(); } else { - LOGGER.debug("[AF] [Captcha] [TURNSTILE] Cloud configuration for turnstile is not available for " + this.getPath()); + LOGGER.debug("[AF] [Captcha] [TURNSTILE] Cloud configuration for turnstile is not available for " + + this.getPath()); } } catch (GuideException e) { LOGGER.error( - "[AF] [Captcha] [TURNSTILE] Error while fetching cloud configuration, upgrade to latest release to use turnstile.", e); + "[AF] [Captcha] [TURNSTILE] Error while fetching cloud configuration, upgrade to latest release to use turnstile.", + e); } } else { LOGGER.error( @@ -139,7 +140,8 @@ public String getCaptchaDisplayMode() { if (turnstileConfiguration == null) { setTurnstileConfiguration(); } - if (turnstileConfiguration != null && CaptchaDisplayMode.INVISIBLE.getValue().equals(turnstileConfiguration.getWidgetType())) { + if (turnstileConfiguration != null + && CaptchaDisplayMode.INVISIBLE.getValue().equals(turnstileConfiguration.getWidgetType())) { captchaDisplayMode = CaptchaDisplayMode.INVISIBLE; } return captchaDisplayMode.getValue(); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationImpl.java index 5f97e8e022..3411b51993 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationImpl.java @@ -32,9 +32,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -@Model( - adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = AutoSaveConfiguration.class) +@Model(adaptables = { SlingHttpServletRequest.class, Resource.class }, adapters = AutoSaveConfiguration.class) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class AutoSaveConfigurationImpl implements AutoSaveConfiguration { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImpl.java index 8e06b55d06..25ff462f15 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImpl.java @@ -69,8 +69,10 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { FormContainer.class, ContainerExporter.class, ComponentExporter.class }, - resourceType = { FormContainerImpl.RESOURCE_TYPE, FormConstants.RT_FD_FRAGMENT_CONTAINER_V1 }) + adapters = { FormContainer.class, + ContainerExporter.class, ComponentExporter.class }, + resourceType = { FormContainerImpl.RESOURCE_TYPE, + FormConstants.RT_FD_FRAGMENT_CONTAINER_V1 }) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class FormContainerImpl extends AbstractContainerImpl implements FormContainer { protected static final String RESOURCE_TYPE = "core/fd/components/form/container/v2/container"; @@ -277,8 +279,8 @@ public String getId() { } else { // handling use-case when AF is used in iframe mode inside embed form component if (request != null && request.getAttribute("formRenderingInsideEmbedContainer") != null) { - return ComponentUtils.getEncodedPath(StringUtils.replace(getPath(), "/" + JcrConstants.JCR_CONTENT + "/" - + GuideConstants.GUIDE_CONTAINER_NODE_NAME, "")); + return ComponentUtils.getEncodedPath(StringUtils.replace(getPath(), + "/" + JcrConstants.JCR_CONTENT + "/" + GuideConstants.GUIDE_CONTAINER_NODE_NAME, "")); } return ComponentUtils.getEncodedPath(getPath()); } @@ -318,17 +320,19 @@ public String getAction() { if (resourceType != null && resourceType.contains("/franklin")) { return ""; } else { - return "https://forms.adobe.com" + ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/submit/" + - ComponentUtils.getEncodedPath(resource.getPath() + ".model.json"); + return "https://forms.adobe.com" + ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/submit/" + + ComponentUtils.getEncodedPath(resource.getPath() + ".model.json"); } } - return getContextPath() + resourceResolver.map(ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/submit/" + getId()); + return getContextPath() + + resourceResolver.map(ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/submit/" + getId()); } @Override @JsonIgnore public String getDataUrl() { - return getContextPath() + resourceResolver.map(ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/data/" + getId()); + return getContextPath() + + resourceResolver.map(ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/data/" + getId()); } @Override @@ -349,7 +353,8 @@ public String getContainingPageLang() { if (request != null) { Page currentPage = getCurrentPage(); if (!GuideWCMUtils.isForms(currentPage.getPath())) { - String pagePath = currentPage.getPath(), pageLocaleRoot = LanguageUtil.getLanguageRoot(pagePath), locale = ""; + String pagePath = currentPage.getPath(), pageLocaleRoot = LanguageUtil.getLanguageRoot(pagePath), + locale = ""; if (StringUtils.isNotBlank(pageLocaleRoot)) { int localeStartIndex = StringUtils.lastIndexOf(pageLocaleRoot, '/'); locale = StringUtils.substring(pageLocaleRoot, localeStartIndex + 1); @@ -387,8 +392,8 @@ public String getLanguageDirection() { properties.put(FD_IS_HAMBURGER_MENU_ENABLED, getIsHamburgerMenuEnabled()); // adding a custom property to know if form data is enabled // this is done so that an extra API call from the client can be avoided - if (StringUtils.isNotBlank(getPrefillService()) || - (request != null && StringUtils.isNotBlank(request.getParameter(GuideConstants.AF_DATA_REF)))) { + if (StringUtils.isNotBlank(getPrefillService()) + || (request != null && StringUtils.isNotBlank(request.getParameter(GuideConstants.AF_DATA_REF)))) { formDataEnabled = true; } @@ -396,7 +401,8 @@ public String getLanguageDirection() { if (request != null && StringUtils.isNotBlank(request.getParameter(GuideConstants.AF_DATA_REF))) { final String dataRef = request.getParameter(GuideConstants.AF_DATA_REF); if (dataRef.startsWith(DRAFT_PREFILL_SERVICE)) { - properties.put(ReservedProperties.FD_DRAFT_ID, StringUtils.substringAfter(dataRef, DRAFT_PREFILL_SERVICE)); + properties.put(ReservedProperties.FD_DRAFT_ID, + StringUtils.substringAfter(dataRef, DRAFT_PREFILL_SERVICE)); } } properties.put(FD_ROLE_ATTRIBUTE, getRoleAttribute()); @@ -468,8 +474,8 @@ public String getName() { @Override public String getCustomFunctionUrl() { - return getContextPath() + resourceResolver.map(ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/customfunctions/" - + getId()); + return getContextPath() + resourceResolver + .map(ADOBE_GLOBAL_API_ROOT + FORMS_RUNTIME_API_GLOBAL_ROOT + "/customfunctions/" + getId()); } @JsonIgnore @@ -484,19 +490,14 @@ private Map getSubmitProperties() { if (request == null || ComponentUtils.shouldIncludeSubmitProperties(request)) { submitProps = new LinkedHashMap<>(); - List submitActionProperties = Arrays.asList( - ReservedProperties.PN_SUBMIT_ACTION_TYPE, + List submitActionProperties = Arrays.asList(ReservedProperties.PN_SUBMIT_ACTION_TYPE, ReservedProperties.PN_SUBMIT_ACTION_NAME); - List submitEmailProperties = Arrays.asList( - ReservedProperties.PN_SUBMIT_EMAIL_TO, - ReservedProperties.PN_SUBMIT_EMAIL_FROM, - ReservedProperties.PN_SUBMIT_EMAIL_SUBJECT, - ReservedProperties.PN_SUBMIT_EMAIL_CC, - ReservedProperties.PN_SUBMIT_EMAIL_BCC); + List submitEmailProperties = Arrays.asList(ReservedProperties.PN_SUBMIT_EMAIL_TO, + ReservedProperties.PN_SUBMIT_EMAIL_FROM, ReservedProperties.PN_SUBMIT_EMAIL_SUBJECT, + ReservedProperties.PN_SUBMIT_EMAIL_CC, ReservedProperties.PN_SUBMIT_EMAIL_BCC); - List submitSpreadsheetProperties = Arrays.asList( - ReservedProperties.PN_SUBMIT_SPREADSHEETURL); + List submitSpreadsheetProperties = Arrays.asList(ReservedProperties.PN_SUBMIT_SPREADSHEETURL); ValueMap resourceMap = resource.getValueMap(); for (Map.Entry entry : resourceMap.entrySet()) { if (submitActionProperties.contains(entry.getKey())) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java index 7c47ed49ad..baae6c8701 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2.java @@ -44,7 +44,8 @@ @Model( adaptables = { SlingHttpServletRequest.class, Resource.class }, - adapters = { FormTitle.class, ComponentExporter.class }, + adapters = { FormTitle.class, + ComponentExporter.class }, resourceType = FormConstants.RT_FD_FORM_TITLE_V2) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java index 5438940599..beda49620e 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3.java @@ -76,8 +76,6 @@ public List getAcceptExtensions() { acceptExtensions[i] = "." + acceptExtensions[i]; } } - return Optional.ofNullable(acceptExtensions) - .map(Arrays::asList) - .orElse(Collections.emptyList()); + return Optional.ofNullable(acceptExtensions).map(Arrays::asList).orElse(Collections.emptyList()); } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/AbstractDataSourceServlet.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/AbstractDataSourceServlet.java index 293168c466..ebb0cf198f 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/AbstractDataSourceServlet.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/AbstractDataSourceServlet.java @@ -58,7 +58,9 @@ public abstract class AbstractDataSourceServlet extends SlingSafeMethodsServlet /** * Returns datasource configuration. * - * @param request the request + * @param request + * the request + * * @return datasource configuration. */ Config getConfig(SlingHttpServletRequest request) { @@ -92,7 +94,8 @@ protected String getParameter(@NotNull Config config, @NotNull String name, * Creates a virtual resource to use in a datasource. */ @NotNull - protected Resource createResource(@NotNull ResourceResolver resolver, @NotNull FormsManager.ComponentDescription desc) { + protected Resource createResource(@NotNull ResourceResolver resolver, + @NotNull FormsManager.ComponentDescription desc) { ValueMap properties = new ValueMapDecorator(new HashMap<>()); List children = new ArrayList(); properties.put(PN_TEXT, desc.getTitle()); @@ -105,8 +108,9 @@ protected Resource createResource(@NotNull ResourceResolver resolver, @NotNull F Resource graniteData = formMetaDataResource.getChild(GRANITE_DATA); if (graniteData != null) { ValueMap graniteDataValueMap = new ValueMapDecorator(graniteData.getValueMap()); - Resource childResource = new ValueMapResource(resolver, formMetaDataResource.getPath() + "/" + GRANITE_DATA, - RESOURCE_TYPE_NON_EXISTING, graniteDataValueMap); + Resource childResource = new ValueMapResource(resolver, + formMetaDataResource.getPath() + "/" + GRANITE_DATA, RESOURCE_TYPE_NON_EXISTING, + graniteDataValueMap); children.add(childResource); } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java index b36e51e241..ac319029de 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServlet.java @@ -60,10 +60,8 @@ @Component( service = { Servlet.class }, property = { - "sling.servlet.resourceTypes=" + FormConstants.RT_FD_FORM_CONTAINER_DATASOURCE_V1, - "sling.servlet.methods=GET", - "sling.servlet.extensions=html" - }) + "sling.servlet.resourceTypes=" + FormConstants.RT_FD_FORM_CONTAINER_DATASOURCE_V1, "sling.servlet.methods=GET", + "sling.servlet.extensions=html" }) public class FormMetaDataDataSourceServlet extends AbstractDataSourceServlet { private static final String TYPE = "type"; @@ -83,10 +81,7 @@ public class FormMetaDataDataSourceServlet extends AbstractDataSourceServlet { * @todo: Add other metadata types here like fragment, actions etc */ public enum FormMetaDataType { - SUBMIT_ACTION("submitAction"), - PREFILL_ACTION("prefillServiceProvider"), - LANG("lang"), - FORMATTERS("formatters"); + SUBMIT_ACTION("submitAction"), PREFILL_ACTION("prefillServiceProvider"), LANG("lang"), FORMATTERS("formatters"); private String value; @@ -95,10 +90,12 @@ public enum FormMetaDataType { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation. If no representation is found, + * Given a {@link String} value, this method returns the enum's value that corresponds to the + * provided string representation. If no representation is found, * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found */ public static FormMetaDataType fromString(String value) { @@ -142,8 +139,8 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt if (config != null) { FormMetaDataType type = FormMetaDataType.fromString(getParameter(config, TYPE, request, null)); String dataModel = getParameter(config, DATA_MODEL, request, ""); - actionTypeDataSource = new SimpleDataSource(getDataSourceResources( - request, request.getResourceResolver(), type, dataModel, config).iterator()); + actionTypeDataSource = new SimpleDataSource( + getDataSourceResources(request, request.getResourceResolver(), type, dataModel, config).iterator()); } request.setAttribute(DataSource.class.getName(), actionTypeDataSource); } @@ -151,9 +148,13 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt /** * Checks if the type is related to formatters policy and the entry's key starts with the allowedformat. * - * @param type The type of form meta data. - * @param entry The entry in the form meta data map. - * @return True if the type is related to formatters policy and the entry's key starts with the allowedformat, otherwise false. + * @param type + * The type of form meta data. + * @param entry + * The entry in the form meta data map. + * + * @return True if the type is related to formatters policy and the entry's key starts with the allowedformat, + * otherwise false. */ private Boolean isFormattersPolicy(FormMetaDataType type, Map.Entry entry) { return type.equals(FormMetaDataType.FORMATTERS) && entry.getKey().startsWith(ALLOWED_FORMAT); @@ -162,17 +163,20 @@ private Boolean isFormattersPolicy(FormMetaDataType type, Map.Entry entry) { return type.equals(FormMetaDataType.LANG) && entry.getKey().startsWith(FormMetaDataType.LANG.getValue()); } - private List getDataSourceResources(SlingHttpServletRequest request, ResourceResolver resourceResolver, FormMetaDataType type, - String dataModel, Config config) { + private List getDataSourceResources(SlingHttpServletRequest request, ResourceResolver resourceResolver, + FormMetaDataType type, String dataModel, Config config) { List resources = new ArrayList<>(); FormMetaData formMetaData = resourceResolver.adaptTo(FormMetaData.class); if (formMetaData != null) { @@ -180,8 +184,8 @@ private List getDataSourceResources(SlingHttpServletRequest request, R switch (type) { case FORMATTERS: case LANG: - ContentPolicy policy = ComponentUtils.getPolicy((String) request.getAttribute(Value.CONTENTPATH_ATTRIBUTE), - resourceResolver); + ContentPolicy policy = ComponentUtils + .getPolicy((String) request.getAttribute(Value.CONTENTPATH_ATTRIBUTE), resourceResolver); resources.add(getResourceForDropdownDisplay(resourceResolver, "Select", "")); if (policy != null) { ValueMap props = policy.getProperties(); @@ -194,9 +198,11 @@ private List getDataSourceResources(SlingHttpServletRequest request, R } } if (type.equals(FormMetaDataType.FORMATTERS)) { - Map allowedCustomFormattersMap = this.getAllowedCustomFormatters(policy, resourceResolver); + Map allowedCustomFormattersMap = this.getAllowedCustomFormatters(policy, + resourceResolver); for (Map.Entry entry : allowedCustomFormattersMap.entrySet()) { - resources.add(getResourceForDropdownDisplay(resourceResolver, entry.getKey(), entry.getValue())); + resources.add( + getResourceForDropdownDisplay(resourceResolver, entry.getKey(), entry.getValue())); } } } @@ -205,15 +211,15 @@ private List getDataSourceResources(SlingHttpServletRequest request, R case SUBMIT_ACTION: // filter the submit actions by uniqueness and data model Set uniques = new HashSet<>(); - metaDataList = StreamSupport.stream(Spliterators.spliteratorUnknownSize(formMetaData.getSubmitActions(), - Spliterator.ORDERED), false) + metaDataList = StreamSupport + .stream(Spliterators.spliteratorUnknownSize(formMetaData.getSubmitActions(), + Spliterator.ORDERED), false) .filter(e -> uniques.add(e.getResourceType())) // In case of overlay, we honor only one .filter(e -> { // only return submit action based on data model configured - return resourceResolver.getResource(e.getResourceType()).getValueMap().get(DATA_MODEL, "").toLowerCase() - .contains(dataModel.toLowerCase()); - }) - .collect(Collectors.toList()).iterator(); + return resourceResolver.getResource(e.getResourceType()).getValueMap().get(DATA_MODEL, "") + .toLowerCase().contains(dataModel.toLowerCase()); + }).collect(Collectors.toList()).iterator(); resources = this.getResourceListFromComponentDescription(metaDataList, resourceResolver); break; case PREFILL_ACTION: @@ -231,8 +237,10 @@ private List getDataSourceResources(SlingHttpServletRequest request, R private Map getAllowedCustomFormatters(ContentPolicy policy, ResourceResolver resourceResolver) { Resource policyResource = resourceResolver.resolve(policy.getPath()); Map allowedCustomFormattersMap = new HashMap<>(); - List allowedcustomFormattersResourceList = StreamSupport.stream(policyResource.getChildren().spliterator(), false).filter( - (childResource) -> childResource.getName().equals(ALLOWED_CUSTOM_FORMAT)).collect(Collectors.toList()); + List allowedcustomFormattersResourceList = StreamSupport + .stream(policyResource.getChildren().spliterator(), false) + .filter((childResource) -> childResource.getName().equals(ALLOWED_CUSTOM_FORMAT)) + .collect(Collectors.toList()); allowedcustomFormattersResourceList.forEach((allowedcustomFormattersResource) -> { allowedcustomFormattersResource.getChildren().forEach(allowedCustomFormatters -> { @@ -253,7 +261,8 @@ private Map getAllowedCustomFormatters(ContentPolicy policy, Res return allowedCustomFormattersMap; } - private SyntheticResource getResourceForDropdownDisplay(ResourceResolver resourceResolver, String key, String value) { + private SyntheticResource getResourceForDropdownDisplay(ResourceResolver resourceResolver, String key, + String value) { Map dropdownMap = new HashMap<>(); dropdownMap.put("text", key); dropdownMap.put("value", value); @@ -262,8 +271,7 @@ private SyntheticResource getResourceForDropdownDisplay(ResourceResolver resourc } private List getResourceListFromComponentDescription( - Iterator metaDataList, - ResourceResolver resourceResolver) { + Iterator metaDataList, ResourceResolver resourceResolver) { List resources = new ArrayList<>(); if (metaDataList != null) { while (metaDataList.hasNext()) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java index bd73c36b6d..3c539c5623 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServlet.java @@ -51,15 +51,12 @@ @Component( service = { Servlet.class }, property = { - "sling.servlet.resourceTypes=" + FormConstants.RT_FD_FORM_REVIEW_DATASOURCE_V1, - "sling.servlet.methods=GET", - "sling.servlet.extensions=html" - }) + "sling.servlet.resourceTypes=" + FormConstants.RT_FD_FORM_REVIEW_DATASOURCE_V1, "sling.servlet.methods=GET", + "sling.servlet.extensions=html" }) public class ReviewDataSourceServlet extends AbstractDataSourceServlet { /** - * Defines the form meta data type. Possible values: {@code submitAction}, - * {@code prefillServiceProvider} + * Defines the form meta data type. Possible values: {@code submitAction}, {@code prefillServiceProvider} * * @todo: Add other metadata types here like fragment, actions etc */ @@ -83,8 +80,8 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt Resource formInstance = ComponentUtils.getFormContainer(componentInstance); if (formInstance != null) { FormContainer formContainer = formInstance.adaptTo(FormContainer.class); - List panels = ((List) getMultipleChildPanels(formContainer)) - .stream().filter(x -> "panel".equals(x.getFieldType())).collect(Collectors.toList()); + List panels = ((List) getMultipleChildPanels(formContainer)).stream() + .filter(x -> "panel".equals(x.getFieldType())).collect(Collectors.toList()); for (Base panel : panels) { String name = panel != null ? panel.getName() : ""; String title = ""; @@ -108,10 +105,12 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt } /** - * Retrieves a list of child panels that have at least two siblings. - * If a panel has fewer than two siblings, it will not be included in the returned list. + * Retrieves a list of child panels that have at least two siblings. If a panel has fewer than two siblings, it will + * not be included in the returned list. * - * @param formContainer the top-level form container + * @param formContainer + * the top-level form container + * * @return a list of panels with at least two siblings */ private List getMultipleChildPanels(FormComponent formContainer) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/StaticImageGETServlet.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/StaticImageGETServlet.java index fa6d425eb9..546fdbd195 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/StaticImageGETServlet.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/internal/servlets/StaticImageGETServlet.java @@ -44,18 +44,13 @@ @Component( service = { Servlet.class }, - property = { - "sling.servlet.resourceTypes=" + FormConstants.RT_FD_FORM_IMAGE_V1, - "sling.servlet.extensions=jpg", - "sling.servlet.extensions=png", - "sling.servlet.extensions=gif", - "sling.servlet.methods=GET" - }) + property = { "sling.servlet.resourceTypes=" + FormConstants.RT_FD_FORM_IMAGE_V1, + "sling.servlet.extensions=jpg", "sling.servlet.extensions=png", "sling.servlet.extensions=gif", + "sling.servlet.methods=GET" }) public class StaticImageGETServlet extends AbstractImageServlet { @Override - protected Layer createLayer(ImageContext c) - throws RepositoryException, IOException { + protected Layer createLayer(ImageContext c) throws RepositoryException, IOException { // don't create the layer yet. handle everything later return null; } @@ -71,10 +66,8 @@ protected ImageResource createImageResource(Resource resource) { } @Override - protected void writeLayer(SlingHttpServletRequest req, - SlingHttpServletResponse resp, - ImageContext imageContext, Layer layer) - throws IOException, RepositoryException { + protected void writeLayer(SlingHttpServletRequest req, SlingHttpServletResponse resp, ImageContext imageContext, + Layer layer) throws IOException, RepositoryException { Image image = new Image(imageContext.resource); image = getImage(resp, imageContext, image); @@ -101,8 +94,8 @@ protected void writeLayer(SlingHttpServletRequest req, resp.flushBuffer(); } - protected boolean isModified(SlingHttpServletRequest req, SlingHttpServletResponse resp, ImageContext imageContext, Layer layer, - Image image, boolean modified) throws RepositoryException { + protected boolean isModified(SlingHttpServletRequest req, SlingHttpServletResponse resp, ImageContext imageContext, + Layer layer, Image image, boolean modified) throws RepositoryException { if (layer != null) { // crop modified = image.crop(layer) != null; diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AssistPriority.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AssistPriority.java index da4ef90650..2df7e87e08 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AssistPriority.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AssistPriority.java @@ -25,10 +25,7 @@ * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ public enum AssistPriority { - CUSTOM("custom"), - DESCRIPTION("description"), - LABEL("label"), - NAME("name"); + CUSTOM("custom"), DESCRIPTION("description"), LABEL("label"), NAME("name"); private String value; @@ -37,11 +34,14 @@ public enum AssistPriority { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation + * Given a {@link String} value, this method returns the enum's value that corresponds to the provided + * string representation * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found + * * @since com.adobe.cq.wcm.core.components.models.form 13.0.0 */ public static AssistPriority fromString(String value) { @@ -57,6 +57,7 @@ public static AssistPriority fromString(String value) { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.wcm.core.components.models.form 13.0.0 */ public String getValue() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AutoSaveConfiguration.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AutoSaveConfiguration.java index 8671eb3ca7..3ae3c33f1e 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AutoSaveConfiguration.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/AutoSaveConfiguration.java @@ -42,11 +42,14 @@ public String getStrategyType() { } /** - * Given a {@link String} strategyType, this method returns the enum's value that corresponds to the provided string - * representation + * Given a {@link String} strategyType, this method returns the enum's value that corresponds to + * the provided string representation * - * @param strategyType the string representation for which an enum value should be returned + * @param strategyType + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found + * * @since com.adobe.cq.forms.core.components.models.form 5.5.4 */ public static AutoSaveStrategyType fromString(String strategyType) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Base.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Base.java index 6a191ab4d7..c13c097371 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Base.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Base.java @@ -47,6 +47,7 @@ public interface Base extends FormComponent { * Returns label of the form field * * @return label of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -58,6 +59,7 @@ default Label getLabel() { * Returns the description of the field * * @return the description of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -66,9 +68,11 @@ default String getDescription() { } /** - * Returns json formula rule to indicate the text to be read by screen readers based on the {@link AssistPriority} configured. + * Returns json formula rule to indicate the text to be read by screen readers based on the {@link AssistPriority} + * configured. * * @return the screen reader text as json formula rule + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -77,10 +81,11 @@ default String getScreenReaderText() { } /** - * Returns the string to indicate the text to be read by screen readers. This - * could be used on server side to compute initial rendition + * Returns the string to indicate the text to be read by screen readers. This could be used on server side to + * compute initial rendition * * @return the screen reader text + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @Nullable @@ -93,6 +98,7 @@ default String getHtmlScreenReaderText() { * Returns {@code true} if form field should be enabled, otherwise {@code false}. * * @return {@code true} if form field should be enabled, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -105,6 +111,7 @@ default Boolean isEnabled() { * list would change based on the form field type * * @return map of constraint messages specific to each constraint. + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @NotNull @@ -117,6 +124,7 @@ default Map getConstraintMessages() { * Returns the tool tip of the field * * @return the tool tip of the field + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @Nullable @@ -128,6 +136,7 @@ default String getTooltip() { * Returns {@code true} if tooltip should always be visible, otherwise {@code false}. * * @return {@code true} if tooltip should always be visible, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonIgnore diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/BaseConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/BaseConstraint.java index 0bc56bfffb..9a46c5633c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/BaseConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/BaseConstraint.java @@ -30,8 +30,8 @@ public interface BaseConstraint { /** - * Defines the data type. Possible values: {@code string}, {@code file}, {@code file[]}, {@code number}, {@code boolean}, {@code array} - * , {@code object} + * Defines the data type. Possible values: {@code string}, {@code file}, {@code file[]}, {@code number}, + * {@code boolean}, {@code array} , {@code object} * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @@ -56,11 +56,14 @@ public enum Type { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation. If no representation is found, {@link #STRING} will be returned. + * Given a {@link String} value, this method returns the enum's value that corresponds to the + * provided string representation. If no representation is found, {@link #STRING} will be returned. * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found, or {@link #STRING} + * * @since com.adobe.cq.wcm.core.components.models.form 13.0.0 */ public static Type fromString(String value) { @@ -76,6 +79,7 @@ public static Type fromString(String value) { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.wcm.core.components.models.form 13.0.0 */ public String getValue() { @@ -93,6 +97,7 @@ public String toString() { * Returns {@code true} if field is required, otherwise {@code false}. * * @return {@code true} if field is required, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -104,6 +109,7 @@ default Boolean isRequired() { * Returns the data type of the form field. * * @return the data type of the form field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default Type getType() { @@ -114,6 +120,7 @@ default Type getType() { * Returns an expression returning boolean value indicating whether the value in the field is valid or not * * @return an expression + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Button.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Button.java index 00feb82aea..95eb233f2c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Button.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Button.java @@ -28,6 +28,7 @@ public interface Button extends Base { * Returns the button value. * * @return the button value + * * @since com.adobe.cq.forms.core.components.models 2.1.0 */ default String getValue() { @@ -38,6 +39,7 @@ default String getValue() { * Returns the button icon identifier. * * @return the button icon identifier + * * @since com.adobe.cq.forms.core.components.models 2.1.0 */ default String getIcon() { @@ -48,6 +50,7 @@ default String getIcon() { * Returns the button default value. * * @return the button icon identifier + * * @since com.adobe.cq.forms.core.components.models 2.1.0 */ default String getDefault() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Captcha.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Captcha.java index baf2e33847..2dbbd4e05f 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Captcha.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Captcha.java @@ -31,14 +31,12 @@ public interface Captcha extends Field { /** - * Defines the display mode for captcha. - * Possible values: {@code visible}, {@code invisible} + * Defines the display mode for captcha. Possible values: {@code visible}, {@code invisible} * * @since com.adobe.cq.forms.core.components.models.form 5.10.0 */ enum CaptchaDisplayMode { - VISIBLE("visible"), - INVISIBLE("invisible"); + VISIBLE("visible"), INVISIBLE("invisible"); private String displayMode; @@ -50,6 +48,7 @@ enum CaptchaDisplayMode { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.forms.core.components.models.form 5.10.0 */ public String getValue() { @@ -74,6 +73,7 @@ default String getCloudServicePath() { * Returns the display mode of the captcha component. * * @return the string value of the one of the {@link CaptchaDisplayMode} enum + * * @since com.adobe.cq.forms.core.components.models.form 5.10.0 */ default String getCaptchaDisplayMode() { @@ -84,6 +84,7 @@ default String getCaptchaDisplayMode() { * Returns the site key of the captcha component. * * @return the site key + * * @since com.adobe.cq.forms.core.components.models.form 5.10.0 */ default String getCaptchaSiteKey() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBox.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBox.java index 266a64faf9..0f42fbc51a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBox.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBox.java @@ -22,7 +22,8 @@ import com.fasterxml.jackson.annotation.JsonValue; /** - * Defines the form {@code CheckBox} Sling Model used for the {@code /apps/core/fd/components/form/checkbox/v1/checkbox} component. + * Defines the form {@code CheckBox} Sling Model used for the {@code /apps/core/fd/components/form/checkbox/v1/checkbox} + * component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @@ -35,8 +36,7 @@ public interface CheckBox extends Field, OptionsConstraint { * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ public enum Orientation { - HORIZONTAL("horizontal"), - VERTICAL("vertical"); + HORIZONTAL("horizontal"), VERTICAL("vertical"); private String value; @@ -45,11 +45,14 @@ public enum Orientation { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation. If no representation is found, {@link #HORIZONTAL} will be returned. + * Given a {@link String} value, this method returns the enum's value that corresponds to the + * provided string representation. If no representation is found, {@link #HORIZONTAL} will be returned. * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found, or {@link #HORIZONTAL} + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ public static Orientation fromString(String value) { @@ -65,6 +68,7 @@ public static Orientation fromString(String value) { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ public String getValue() { @@ -82,6 +86,7 @@ public String toString() { * Returns the orientation of the checkbox component * * @return {@link Orientation}. + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonIgnore diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBoxGroup.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBoxGroup.java index a001048cab..fc62f94c28 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBoxGroup.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/CheckBoxGroup.java @@ -18,8 +18,8 @@ import org.osgi.annotation.versioning.ConsumerType; /** - * Defines the form {@code CheckBoxGroup} Sling Model used for the {@code /apps/core/fd/components/form/checkboxgroup/v1/checkboxgroup} - * component. + * Defines the form {@code CheckBoxGroup} Sling Model used for the + * {@code /apps/core/fd/components/form/checkboxgroup/v1/checkboxgroup} component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ConstraintType.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ConstraintType.java index 1f443a9e99..eb13ba90bb 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ConstraintType.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ConstraintType.java @@ -21,8 +21,9 @@ /** * Defines the constraint type. Possible values: {@code type}, {@code required}, {@code minimum}, {@code maximum}, - * {@code minLength}, {@code maxLength}, {@code step}, {@code format}, {@code pattern}, {@code minItems}, {@code maxItems}, - * {@code minOccur}, {@code maxOccur}, {@code uniqueItems}, {@code enforceEnum}, {@code validationExpression} + * {@code minLength}, {@code maxLength}, {@code step}, {@code format}, {@code pattern}, {@code minItems}, + * {@code maxItems}, {@code minOccur}, {@code maxOccur}, {@code uniqueItems}, {@code enforceEnum}, + * {@code validationExpression} * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @@ -53,11 +54,14 @@ public enum ConstraintType { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation + * Given a {@link String} value, this method returns the enum's value that corresponds to the provided + * string representation * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ public static ConstraintType fromString(String value) { @@ -73,6 +77,7 @@ public static ConstraintType fromString(String value) { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.wcm.core.components.models.form 13.0.0 */ public String getValue() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Container.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Container.java index 4e4660b17a..ec3cf545ea 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Container.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Container.java @@ -43,6 +43,7 @@ public interface Container extends Base, BaseConstraint, ContainerExporter { * Returns the list of items present inside the container as an array. * * @return list of items + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_EMPTY) @@ -53,6 +54,7 @@ public interface Container extends Base, BaseConstraint, ContainerExporter { /** * @see ContainerExporter#getExportedItems() + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @NotNull @@ -78,6 +80,7 @@ default String[] getExportedItemsOrder() { /** * @see ContainerExporter#getExportedType() + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @NotNull @@ -94,6 +97,7 @@ default String getAppliedCssClasses() { /** * @return returns the role attribute that will be applied on the container. + * * @since com.adobe.cq.forms.core.components.models.form 5.4.3 */ @Nullable @@ -103,7 +107,8 @@ default String getRoleAttribute() { } // the below mentioned interface methods are copied from ResponsiveGridExporter - // done because CM throws this, the product interface com.day.cq.wcm.foundation.model.responsivegrid.export.ResponsiveGridExporter + // done because CM throws this, the product interface + // com.day.cq.wcm.foundation.model.responsivegrid.export.ResponsiveGridExporter // annotated with @ProviderType should not be implemented by custom code. /** diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ContainerConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ContainerConstraint.java index ac3bf9a1fd..38cca15bab 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ContainerConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ContainerConstraint.java @@ -31,6 +31,7 @@ public interface ContainerConstraint { * Returns the minimum items of the container (ie array data type) * * @return the minimum items + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -43,6 +44,7 @@ default Integer getMinItems() { * Returns the maximum items of the container (ie array data type) * * @return the maximum items + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -55,6 +57,7 @@ default Integer getMaxItems() { * Returns the minimum occurrence of the container (ie array data type) * * @return the minimum occurrence + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -67,6 +70,7 @@ default Integer getMinOccur() { * Returns the maximum occurrence of the container (ie array data type) * * @return the maximum occurrence + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateConstraint.java index 697be24746..5b175920f5 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateConstraint.java @@ -35,6 +35,7 @@ public interface DateConstraint extends FormatConstraint { * Returns the minimum value for the date. The constraint is applicable only for field with type date * * @return minimum date + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -46,6 +47,7 @@ public interface DateConstraint extends FormatConstraint { * Returns the maximum value for the date. The constraint is applicable only for field with type date * * @return maximum date + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -57,6 +59,7 @@ public interface DateConstraint extends FormatConstraint { * Returns the Maximum value (exclusive) that can be entered by the user. * * @return maximum value (exclusive) for the date + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -68,6 +71,7 @@ public interface DateConstraint extends FormatConstraint { * Returns the minimum value (exclusive) that can be entered by the user. * * @return minimum value (exclusive) for the date + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DatePicker.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DatePicker.java index 82ba1a54af..13eb293447 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DatePicker.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DatePicker.java @@ -20,7 +20,8 @@ import com.fasterxml.jackson.annotation.JsonFormat; /** - * Defines the form {@code DatePicker} Sling Model used for the {@code /apps/core/fd/components/form/datepicker/v1/datepicker} component. + * Defines the form {@code DatePicker} Sling Model used for the + * {@code /apps/core/fd/components/form/datepicker/v1/datepicker} component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @@ -29,6 +30,7 @@ public interface DatePicker extends Field, DateConstraint { /** * @see Field#getDefault() + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = Base.DATE_FORMATTER, timezone = "UTC") diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTime.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTime.java index 86466757a0..1dae46e40a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTime.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTime.java @@ -20,7 +20,8 @@ import org.osgi.annotation.versioning.ConsumerType; /** - * Interface for {@code Password} Sling Model used for the {@code /apps/core/fd/components/form/password/v1/password} component. + * Interface for {@code Password} Sling Model used for the {@code /apps/core/fd/components/form/password/v1/password} + * component. * * @since com.adobe.cq.forms.core.components.models.form 5.12.0 */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTimeConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTimeConstraint.java index f578ddbd5e..76bb55ec34 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTimeConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DateTimeConstraint.java @@ -25,6 +25,7 @@ public interface DateTimeConstraint extends FormatConstraint { * Returns the minimum value for the date. The constraint is applicable only for field with type date * * @return minimum date + * * @since com.adobe.cq.forms.core.components.models.form 5.11.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -36,6 +37,7 @@ public interface DateTimeConstraint extends FormatConstraint { * Returns the maximum value for the date. The constraint is applicable only for field with type date * * @return maximum date + * * @since com.adobe.cq.forms.core.components.models.form 5.11.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DropDown.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DropDown.java index 3d753cb699..61d74e3c84 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DropDown.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/DropDown.java @@ -20,7 +20,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; /** - * Defines the form {@code DropDown} Sling Model used for the {@code /apps/core/fd/components/form/dropdown/v1/dropdown} component. + * Defines the form {@code DropDown} Sling Model used for the {@code /apps/core/fd/components/form/dropdown/v1/dropdown} + * component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Field.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Field.java index 8041dd3e97..6b5d35b535 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Field.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Field.java @@ -35,6 +35,7 @@ public interface Field extends Base, BaseConstraint { * Checks if the field should be rendered read only. * * @return {@code true} if the field should be read-only, {@code false} otherwise + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -46,6 +47,7 @@ default Boolean isReadOnly() { * The placeholder to show on the field. * * @return placeholder to show on the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonProperty("placeholder") @@ -54,10 +56,11 @@ default String getPlaceHolder() { } /** - * The format in which the value will be displayed to the user on screen in the field. - * For example when using a currency field, the currency sign should be shown to the user. + * The format in which the value will be displayed to the user on screen in the field. For example when using a + * currency field, the currency sign should be shown to the user. * * @return display format of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getDisplayFormat() { @@ -65,10 +68,11 @@ default String getDisplayFormat() { } /** - * The format in which the value will be edited by the user. - * For instance users in Germany would want to interchange decimal (.) and comma (,) when entering numerical values. + * The format in which the value will be edited by the user. For instance users in Germany would want to interchange + * decimal (.) and comma (,) when entering numerical values. * * @return edit format of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getEditFormat() { @@ -79,6 +83,7 @@ default String getEditFormat() { * The format in which the value will be exported or submitted. * * @return data format of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getDataFormat() { @@ -86,11 +91,12 @@ default String getDataFormat() { } /** - * The value of the field when no value is provided by the end user or data model. - * The type of this property should match the value of the type property defined in the Field. - * If not, then a type coercion will be tried and if that fails, the value will be set to null. + * The value of the field when no value is provided by the end user or data model. The type of this property should + * match the value of the type property defined in the Field. If not, then a type coercion will be tried and if that + * fails, the value will be set to null. * * @return default value of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonSerialize(using = DefaultValueSerializer.class) @@ -99,16 +105,15 @@ default Object[] getDefault() { } /** - * The value that represents an empty state for the field. - * This can be used to distinguish between null, empty string, or undefined values. + * The value that represents an empty state for the field. This can be used to distinguish between null, empty + * string, or undefined values. * - * Valid values for this property are: - * - "null" - represents null value - * - "undefined" - represents undefined value - * - "" - represents empty string + * Valid values for this property are: - "null" - represents null value - "undefined" - represents undefined value - + * "" - represents empty string * * * @return empty value representation for the field + * * @since com.adobe.cq.forms.core.components.models.form 5.12.1 */ @Nullable @@ -120,6 +125,7 @@ default String getEmptyValue() { * The expression that when evaluated would determine what the displayValue of a field would be * * @return display value expression of the field + * * @since com.adobe.cq.forms.core.components.models.form 5.2.0 */ default String getDisplayValueExpression() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FieldType.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FieldType.java index afe215afd1..f2bbb520a4 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FieldType.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FieldType.java @@ -51,11 +51,14 @@ public enum FieldType { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation. If no representation is found, {@link #TEXT_INPUT} will be returned. + * Given a {@link String} value, this method returns the enum's value that corresponds to the provided + * string representation. If no representation is found, {@link #TEXT_INPUT} will be returned. * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value, if one was found, or {@link #TEXT_INPUT} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ public static FieldType fromString(String value) { @@ -71,6 +74,7 @@ public static FieldType fromString(String value) { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ public String getValue() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java index a266d076ab..a5e784b298 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileConstraint.java @@ -33,13 +33,15 @@ public interface FileConstraint { String DEFAULT_MAX_FILE_SIZE = "2MB"; - List DEFAULT_ACCEPT = Collections.unmodifiableList(Arrays.asList("audio/*", "video/*", "image/*", "text/*", "application/pdf")); + List DEFAULT_ACCEPT = Collections + .unmodifiableList(Arrays.asList("audio/*", "video/*", "image/*", "text/*", "application/pdf")); /** - * Returns the Maximum file size (in IEC specification) that a field can accept. The constraint is - * applicable for file attachment field + * Returns the Maximum file size (in IEC specification) that a field can accept. The constraint is applicable for + * file attachment field * * @return the maximum file size + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getMaxFileSize() { @@ -47,10 +49,11 @@ default String getMaxFileSize() { } /** - * Returns the list of standard IANA media types which field can accept. The constraint is - * applicable for file attachment field + * Returns the list of standard IANA media types which field can accept. The constraint is applicable for file + * attachment field * * @return the list of standard IANA media types + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default List getAccept() { @@ -58,10 +61,11 @@ default List getAccept() { } /** - * Returns the list of file extensions which field can accept. The constraint is - * applicable for file attachment field + * Returns the list of file extensions which field can accept. The constraint is applicable for file attachment + * field * * @return the list of extensions supported by the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default List getAcceptExtensions() { @@ -69,8 +73,8 @@ default List getAcceptExtensions() { } /** - * The constraint is - * applicable for file attachment field. If the type is {@code String}, the format will always be {@code data-url}. + * The constraint is applicable for file attachment field. If the type is {@code String}, the format will always be + * {@code data-url}. * * @since com.adobe.cq.forms.core.components.models.form 5.7.4 */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java index 9843eccacf..50a0f37319 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FileInput.java @@ -23,7 +23,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; /** - * Defines the form {@code FileInput} Sling Model used for the {@code /apps/core/fd/components/form/fileinput/v1/fileinput} component. + * Defines the form {@code FileInput} Sling Model used for the + * {@code /apps/core/fd/components/form/fileinput/v1/fileinput} component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @@ -44,8 +45,8 @@ default Boolean isMultiple() { } /** - * Returns the list of file extensions which field can accept. The constraint is - * applicable for file attachment field + * Returns the list of file extensions which field can accept. The constraint is applicable for file attachment + * field * * @return the list of extensions supported by the field */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormClientLibManager.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormClientLibManager.java index 11d4a94921..7cd7ae03f9 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormClientLibManager.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormClientLibManager.java @@ -29,7 +29,8 @@ public interface FormClientLibManager { /** - * Adds a client library associated with form or fragment for a request, that can be consumed later within the scope of request. + * Adds a client library associated with form or fragment for a request, that can be consumed later within the scope + * of request. * * @param clientLibRef */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormComponent.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormComponent.java index 2b80641e68..b93153a234 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormComponent.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormComponent.java @@ -35,12 +35,14 @@ @ProviderType public interface FormComponent extends Component { - public final String CUSTOM_PROPERTY_WRAPPER = "afs:layout"; // needs to be renamed to "CUSTOM_LAYOUT_PROPERTY_WRAPPER" later + public final String CUSTOM_PROPERTY_WRAPPER = "afs:layout"; // needs to be renamed to + // "CUSTOM_LAYOUT_PROPERTY_WRAPPER" later /** * Returns the field type * * @return the field type + * * @since com.adobe.cq.forms.core.components.models.form 1.0.0 */ String getFieldType(); // todo: keeping string here to support custom view types @@ -49,6 +51,7 @@ public interface FormComponent extends Component { * Returns {@code true} if form field should be visible, otherwise {@code false}. * * @return {@code true} if form field should be visible, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -93,6 +96,7 @@ default Map getDorContainer() { * Returns getPath of the form field * * @return getPath of the field + * * @since com.adobe.cq.forms.core.components.util 3.1.0 */ @JsonView(Views.Author.class) @@ -105,6 +109,7 @@ default String getPath() { * Returns the name of the form field * * @return name of the form field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -116,6 +121,7 @@ default String getName() { * Returns the reference to the data model * * @return reference to the data model + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -124,8 +130,8 @@ default String getDataRef() { } /** - * Returns the rules defined for the component after filtering out invalid rules - * If no rules are defined, returns an empty map + * Returns the rules defined for the component after filtering out invalid rules If no rules are defined, returns an + * empty map * * @return map containing the rules and their expressions */ @@ -138,8 +144,7 @@ default Map getRules() { /** * Returns the events defined for the component after filtering out invalid rules * - * @return map containing the events and their expressions - * If no rules are defined, returns an empty map + * @return map containing the events and their expressions If no rules are defined, returns an empty map */ @NotNull @JsonInclude(JsonInclude.Include.NON_EMPTY) @@ -150,7 +155,9 @@ default Map getEvents() { /** * Sets i18n object * - * @param i18n reference to the {@link I18n} object + * @param i18n + * reference to the {@link I18n} object + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonIgnore @@ -161,7 +168,9 @@ default void setI18n(@Nonnull I18n i18n) { /** * Sets the language for the form component * - * @param lang the language code + * @param lang + * the language code + * * @since com.adobe.cq.forms.core.components.models.form 5.12.2 */ default void setLang(@Nullable String lang) { @@ -172,6 +181,7 @@ default void setLang(@Nullable String lang) { * Returns the language to use for formatting the field. * * @return returns the language to use for formatting the field. + * * @since com.adobe.cq.forms.core.components.models.form 5.3.1 */ @Nullable @@ -183,6 +193,7 @@ default String getLang() { * Returns the language if it is present as a property in JCR * * @return the language code if present in JCR, null otherwise + * * @since com.adobe.cq.forms.core.components.models.form 5.12.2 */ @JsonProperty("lang") @@ -193,6 +204,7 @@ default String getLangIfPresent() { /** * @see ComponentExporter#getExportedType() + * * @since com.adobe.cq.wcm.core.components.models.form 14.2.0 */ @NotNull diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormContainer.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormContainer.java index 463ccbbbd4..e3cee4079b 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormContainer.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormContainer.java @@ -29,7 +29,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * Defines the form container {@code FormContainer} Sling Model used for the {@code /apps/core/fd/components/form/formcontainer} component. + * Defines the form container {@code FormContainer} Sling Model used for the + * {@code /apps/core/fd/components/form/formcontainer} component. * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @@ -70,6 +71,7 @@ public interface FormContainer extends Container { * Returns form metadata {@link FormMetaData} * * @return form meta data + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonProperty("metadata") @@ -102,6 +104,7 @@ default String getSchemaRef() { * Returns schema type {@link GuideSchemaType} * * @return schema type + * * @since com.adobe.cq.forms.core.components.models.form 2.1.0 */ @Nullable @@ -114,6 +117,7 @@ default GuideSchemaType getSchemaType() { * Returns name of the client lib category * * @return name of the client lib category + * * @since com.adobe.cq.forms.core.components.models.form 2.1.0 */ @Nullable @@ -126,6 +130,7 @@ default String getClientLibRef() { * Returns a unique identifier * * @return unique identifier + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -141,7 +146,8 @@ default String getFieldType() { @JsonIgnore @Override default Boolean isEnabled() { - // explicitly setting true, since form container does not have enabled property, but other containers like panel have enabled + // explicitly setting true, since form container does not have enabled property, but other containers like panel + // have enabled return true; } @@ -149,6 +155,7 @@ default Boolean isEnabled() { * Returns the hamburger menu support * * @return the hamburger menu support of the form + * * @since com.adobe.cq.forms.core.components.models.form 5.7.5 */ @JsonIgnore @@ -159,28 +166,32 @@ default Boolean getIsHamburgerMenuEnabled() { @Override @JsonIgnore default Label getLabel() { - // explicitly setting null, since form container does not have label, but other containers like panel have a label + // explicitly setting null, since form container does not have label, but other containers like panel have a + // label return null; } @JsonIgnore @Override default Boolean isVisible() { - // explicitly setting true, since form container does not have visible property, but other containers like panel have visible + // explicitly setting true, since form container does not have visible property, but other containers like panel + // have visible return true; } @JsonIgnore @Override default String getName() { - // explicitly setting null, since form container does not have name property, but other containers like panel have a name + // explicitly setting null, since form container does not have name property, but other containers like panel + // have a name return null; } @JsonIgnore @Override default BaseConstraint.Type getType() { - // explicitly setting null, since form container does not have type property, but other containers like panel have a type + // explicitly setting null, since form container does not have type property, but other containers like panel + // have a type return null; } @@ -188,6 +199,7 @@ default BaseConstraint.Type getType() { * Returns the form title * * @return form title + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getTitle() { @@ -198,6 +210,7 @@ default String getTitle() { * Returns the form description * * @return form description + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getDescription() { @@ -208,6 +221,7 @@ default String getDescription() { * Returns the form model * * @return the form model, based on the document path configured or the items + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonIgnore @@ -219,6 +233,7 @@ default Map getModel() { * Returns the document path (dam asset) containing the form model json * * @return the document path containing form model json, if one was set, or {@code null} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonIgnore @@ -230,6 +245,7 @@ default String getDocumentPath() { * Returns base64 encoded current page path * * @return base64 encoded current page path + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonIgnore @@ -240,6 +256,7 @@ default String getDocumentPath() { * Returns the form thank you message * * @return form thank you message + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonIgnore @@ -249,6 +266,7 @@ default String getDocumentPath() { * Returns the form thank you page * * @return form thank you page + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonIgnore @@ -260,6 +278,7 @@ default String getThankYouPage() { * Returns the form thank you option * * @return form thank you option + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ @JsonIgnore @@ -271,6 +290,7 @@ default ThankYouOption getThankYouOption() { * Returns the form data * * @return the form data + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonProperty("data") @@ -282,6 +302,7 @@ default String getFormData() { * Returns the submit action * * @return the submit action + * * @since com.adobe.cq.forms.core.components.models.form 4.0.0 */ default String getAction() { @@ -292,6 +313,7 @@ default String getAction() { * Returns the data url to fetch form data * * @return the data url to fetch form data + * * @since com.adobe.cq.forms.core.components.models.form 4.0.0 */ default String getDataUrl() { @@ -302,6 +324,7 @@ default String getDataUrl() { * Returns the language in which the form was authored * * @return the language of the form + * * @since com.adobe.cq.forms.core.components.models.form 4.0.0 */ default String getLang() { @@ -312,6 +335,7 @@ default String getLang() { * Returns the language of the containing page * * @return the language of the containing page + * * @since com.adobe.cq.forms.core.components.models.form 4.7.1 */ @JsonIgnore @@ -323,6 +347,7 @@ default String getContainingPageLang() { * API to give direction of content in HTML for a given language. * * @return one of the constants "rtl" or "ltr" depending on direction of given language + * * @since com.adobe.cq.forms.core.components.models.form 4.5.0 */ @JsonIgnore @@ -334,6 +359,7 @@ default String getLanguageDirection() { * Returns the redirect url after form submission * * @return the redirect url of the form + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ @JsonIgnore @@ -345,6 +371,7 @@ default String getRedirectUrl() { * Returns the prefill service for the form * * @return the prefill service + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ @JsonIgnore @@ -367,6 +394,7 @@ default void visit(Consumer callback) throws Exception {} * Returns site page path if dropped in sites else the form page path. * * @return parent page path before jcr:content + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ @JsonIgnore @@ -378,6 +406,7 @@ default String getParentPagePath() { * Returns the url from where the custom functions should be registered * * @return custom function registration url + * * @since com.adobe.cq.forms.core.components.models.form 5.9.5 */ @JsonIgnore @@ -389,6 +418,7 @@ default String getCustomFunctionUrl() { * Returns the auto save configuration * * @return auto save configuration + * * @since com.adobe.cq.forms.core.components.models.form 5.11.0 */ @JsonIgnore diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormMetaData.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormMetaData.java index 46b979dfd7..495b2eb7ac 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormMetaData.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormMetaData.java @@ -29,6 +29,7 @@ public interface FormMetaData { * Returns the version of the adaptive form specification * * @return the version of adaptive form specification + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getVersion() { @@ -39,6 +40,7 @@ default String getVersion() { * Returns the version of the rule grammar * * @return the version of the rule grammar + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getGrammar() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java index 92ba5aeecc..4e6e302021 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormTitle.java @@ -30,7 +30,8 @@ // import com.adobe.cq.forms.core.components.models.form.BaseConstraint.Type; /** - * Defines the form {@code Title} Sling Model used for the {@code /apps/core/fd/components/form/title/v2/title} component. + * Defines the form {@code Title} Sling Model used for the {@code /apps/core/fd/components/form/title/v2/title} + * component. * * @since com.adobe.cq.forms.core.components.models.form 5.5.3 */ @@ -41,6 +42,7 @@ public interface FormTitle extends FormComponent { * Returns the HTML element type (h1-h6) used for the markup. * * @return the element type + * * @since com.adobe.cq.forms.core.components.models.form 5.5.3; */ @JsonIgnore @@ -64,6 +66,7 @@ default String getText() { * Retrieves the text value to be displayed. * * @return the text value to be displayed, or {@code null} if no value can be returned + * * @since com.adobe.cq.forms.core.components.models.form 5.5.3; */ default String getValue() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormatConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormatConstraint.java index 1af1820fde..ea968af0a8 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormatConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/FormatConstraint.java @@ -62,6 +62,7 @@ public String toString() { * Returns the format of the form field as specified in the json schema specification(for example, date, binary etc) * * @return the format of the form field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Fragment.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Fragment.java index b3c8bccc68..e34041ba2e 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Fragment.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Fragment.java @@ -21,7 +21,8 @@ import org.osgi.annotation.versioning.ConsumerType; /** - * Defines the form {@code Fragment} Sling Model used for the {@code /apps/core/fd/components/form/fragment/v1/fragment} component. + * Defines the form {@code Fragment} Sling Model used for the {@code /apps/core/fd/components/form/fragment/v1/fragment} + * component. * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ @@ -32,6 +33,7 @@ public interface Fragment extends Panel { * Fragment reference * * @return {@code fragRef} + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ String getFragmentPath(); @@ -40,6 +42,7 @@ public interface Fragment extends Panel { * List of children of fragment container * * @return + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ List getFragmentChildren(); @@ -48,6 +51,7 @@ public interface Fragment extends Panel { * Returns fragment container resource * * @return + * * @since com.adobe.cq.forms.core.components.models.form 5.4.1 */ Resource getFragmentContainer(); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/HtlUtil.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/HtlUtil.java index a32859ef30..ebf21b2011 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/HtlUtil.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/HtlUtil.java @@ -23,6 +23,7 @@ public interface HtlUtil { * Checks whether this request has been originated from edge delivery services * * @return {Boolean} true if the request is from edge delivery services, false otherwise + * * @since com.adobe.cq.forms.core.components.models.form 5.3.2 */ Boolean isEdgeDeliveryRequest(); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Label.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Label.java index a7106b9f97..5071b793ac 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Label.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Label.java @@ -30,6 +30,7 @@ public interface Label { * Returns {@code true} if label is rich text, otherwise {@code false}. * * @return {@code true} if label is rich text, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -41,6 +42,7 @@ default Boolean isRichText() { * Returns {@code true} if label should be visible, otherwise {@code false}. * * @return {@code true} if label should be visible, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -52,6 +54,7 @@ default Boolean isVisible() { * Returns the value of this label. * * @return the value of this label + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java index c99e497c3d..150c718b80 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraint.java @@ -24,6 +24,7 @@ * A interface which specifies the different form number type constraints * * @deprecated Use {@link NumberConstraintV2} instead. + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @Deprecated @@ -34,6 +35,7 @@ public interface NumberConstraint { * Returns the minimum value for the number. The constraint is applicable only for field with type number * * @return minimum value for the number + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -46,6 +48,7 @@ default Long getMinimum() { * Returns the maximum value for the number. The constraint is applicable only for field with type number * * @return maximum value for the number + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -58,6 +61,7 @@ default Long getMaximum() { * Returns the Maximum value (exclusive) that can be entered by the user. * * @return maximum value (exclusive) for the number + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -70,6 +74,7 @@ default Long getExclusiveMaximum() { * Returns the minimum value (exclusive) that can be entered by the user. * * @return minimum value (exclusive) for the number + * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java index 17b261c0cf..66f4e8ff1b 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberConstraintV2.java @@ -32,6 +32,7 @@ public interface NumberConstraintV2 extends NumberConstraint { * Returns the minimum value for the number. The constraint is applicable only for field with type number. * * @return minimum value for the number + * * @since com.adobe.cq.forms.core.components.models.form 5.6.4 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -44,6 +45,7 @@ default Number getMinimumNumber() { * Returns the maximum value for the number. The constraint is applicable only for field with type number. * * @return maximum value for the number + * * @since com.adobe.cq.forms.core.components.models.form 5.6.4 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -56,6 +58,7 @@ default Number getMaximumNumber() { * Returns the Maximum value (exclusive) that can be entered by the user. * * @return maximum value (exclusive) for the number + * * @since com.adobe.cq.forms.core.components.models.form 5.6.4 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -68,6 +71,7 @@ default Number getExclusiveMaximumNumber() { * Returns the minimum value (exclusive) that can be entered by the user. * * @return minimum value (exclusive) for the number + * * @since com.adobe.cq.forms.core.components.models.form 5.6.4 */ @JsonInclude(JsonInclude.Include.NON_NULL) diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java index f78e96bb93..25930edcb0 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/NumberInput.java @@ -21,7 +21,8 @@ import com.fasterxml.jackson.annotation.JsonIgnore; /** - * Defines the form {@code NumberInput} Sling Model used for the {@code /apps/core/fd/components/form/numberinput/v1/numberinput} component. + * Defines the form {@code NumberInput} Sling Model used for the + * {@code /apps/core/fd/components/form/numberinput/v1/numberinput} component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @@ -35,6 +36,7 @@ default String getEditFormat() { /** * @see BaseConstraint#getType() + * * @since com.adobe.cq.wcm.core.components.models.form 4.4.0 */ @Override diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/OptionsConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/OptionsConstraint.java index 58bced92bc..6e37c7f297 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/OptionsConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/OptionsConstraint.java @@ -29,12 +29,13 @@ public interface OptionsConstraint { /** - * Returns {@code true} if enforceEnum is set, otherwise {@code false}. - * Whether a user can enter a value that is not present in the enum array. If set to true, a user will be able to enter - * any other value that is not in the list of enum. That generally means that enum is used a aid for users to enter the value but - * is not a validation constraint. The constraint is applicable only if the enum property is defined on the Field + * Returns {@code true} if enforceEnum is set, otherwise {@code false}. Whether a user can enter a value that is not + * present in the enum array. If set to true, a user will be able to enter any other value that is not in the list + * of enum. That generally means that enum is used a aid for users to enter the value but is not a validation + * constraint. The constraint is applicable only if the enum property is defined on the Field * * @return {@code true} if enforceEnum is set, otherwise {@code false}. + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default boolean isEnforceEnum() { @@ -42,20 +43,22 @@ default boolean isEnforceEnum() { } /** - * Returns a list of options to put restrictions on the possible values of the field. - * The type of values in the enum array must match the value of the type property defined in the field. + * Returns a list of options to put restrictions on the possible values of the field. The type of values in the enum + * array must match the value of the type property defined in the field. * * @return the list of enum + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonProperty("enum") Object[] getEnums(); /** - * Returns a user friendly text to display for the possible options to be shown to the end user. - * The length of enum and enumNames array must match + * Returns a user friendly text to display for the possible options to be shown to the end user. The length of enum + * and enumNames array must match * * @return the list of enum names + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ String[] getEnumNames(); @@ -64,6 +67,7 @@ default boolean isEnforceEnum() { * Returns screen reader friendly aria labels for the options. * * @return the list of aria labels for the options + * * @since com.adobe.cq.forms.core.components.models.form 5.12.3 */ @JsonIgnore diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Panel.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Panel.java index 2ba29fed56..94cfa0532e 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Panel.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Panel.java @@ -20,7 +20,8 @@ import org.osgi.annotation.versioning.ConsumerType; /** - * Defines the form {@code panel} Sling Model used for the {@code /apps/core/fd/components/form/panel/v1/panel} component. + * Defines the form {@code panel} Sling Model used for the {@code /apps/core/fd/components/form/panel/v1/panel} + * component. * * @since com.adobe.cq.forms.core.components.models.form 2.0.0 */ @@ -30,6 +31,7 @@ public interface Panel extends Container, ContainerConstraint { * Checks if the container should be rendered read only. * * @return {@code true} if the container should be read-only, {@code false} otherwise + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java index 066a376a7d..5e3acddf80 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Review.java @@ -28,15 +28,18 @@ public interface Review extends Base { /** - * @return an array of linked panels to be reviewed on the review page. Each linked panel is the name of a panel that is linked to the - * review page. + * @return an array of linked panels to be reviewed on the review page. Each linked panel is the name of a panel + * that is linked to the review page. + * * @since com.adobe.cq.forms.core.components.models.form 5.9.6 */ @JsonIgnore String[] getLinkedPanels(); /** - * @return the edit mode action, which indicates whether edit button is visible on the review page at field, panel, both, or none + * @return the edit mode action, which indicates whether edit button is visible on the review page at field, panel, + * both, or none + * * @since com.adobe.cq.forms.core.components.models.form 5.9.6 */ @JsonIgnore diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Scribble.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Scribble.java index 78ff7427eb..75764aba8c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Scribble.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Scribble.java @@ -32,6 +32,7 @@ public interface Scribble extends Field { * Returns the data-url string of the scribble. * * @return data-url string representing the scribble + * * @since com.adobe.cq.forms.core.components.models.form 5.12.0 */ String getValue(); @@ -40,6 +41,7 @@ public interface Scribble extends Field { * Returns the format of the scribble. * * @return the format of the scribble, e.g., data-url + * * @since com.adobe.cq.forms.core.components.models.form 5.12.0 */ String getFormat(); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StaticImage.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StaticImage.java index f1649f1cd3..460a4ca802 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StaticImage.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StaticImage.java @@ -31,6 +31,7 @@ public interface StaticImage extends FormComponent { * Returns the source where the image is present. * * @return the source where the image is present + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable @@ -43,6 +44,7 @@ default String getImageSrc() throws RepositoryException, IOException { * Retrieves the text value to be displayed. * * @return the text value to be displayed, or {@code null} if no value can be returned + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1; */ default String getValue() { @@ -53,6 +55,7 @@ default String getValue() { * Returns the alternate text in place of image. * * @return the alternate text in place of image + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StringConstraint.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StringConstraint.java index 998be84069..7e68b83069 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StringConstraint.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/StringConstraint.java @@ -31,6 +31,7 @@ public interface StringConstraint extends BaseConstraint, FormatConstraint { * Returns the minimum length of the data. The constraint is applicable only for field with type string * * @return minimum length of the data + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_NULL) @@ -40,17 +41,20 @@ public interface StringConstraint extends BaseConstraint, FormatConstraint { * Returns the maximum length of the data. The constraint is applicable only for field with type string * * @return maximum length of the data + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonInclude(JsonInclude.Include.NON_NULL) Integer getMaxLength(); /** - * As specified in the JSON Schema specification, the regex against which the value of the field should be tested with. + * As specified in the JSON Schema specification, the regex against which the value of the field should be tested + * with. * * Returns the regex. The constraint is applicable only for field with type string * * @return string represented as pattern + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ default String getPattern() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Text.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Text.java index 213ce42c5b..ba147180cb 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Text.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Text.java @@ -28,6 +28,7 @@ public interface Text extends FormComponent { * Retrieves the text value to be displayed. * * @return the text value to be displayed, or {@code null} if no value can be returned + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1; */ default String getValue() { @@ -38,6 +39,7 @@ default String getValue() { * Checks if the text to be displayed is rich text or not. * * @return {@code true} if the text is rich (HTML formatting), {@code false otherwise} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1; */ default boolean isRichText() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/TextInput.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/TextInput.java index 4415ceabde..91db70e16c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/TextInput.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/TextInput.java @@ -22,7 +22,8 @@ import com.fasterxml.jackson.annotation.JsonProperty; /** - * Defines the form {@code Text} Sling Model used for the {@code /apps/core/fd/components/form/textinput/v1/textinput} component. + * Defines the form {@code Text} Sling Model used for the {@code /apps/core/fd/components/form/textinput/v1/textinput} + * component. * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @@ -36,6 +37,7 @@ public interface TextInput extends Field, NumberConstraint, DateConstraint, Stri * Returns {@code true} if multi line, otherwise {@code false}. * * @return {@code true} if multi line, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @JsonIgnore @@ -59,6 +61,7 @@ default String getAutoComplete() { * Returns the format of the form field as specified in the json schema specification(for example, date, binary etc) * * @return the format of the form field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Nullable diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ThankYouOption.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ThankYouOption.java index 45166f1c83..b323d5506c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ThankYouOption.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/ThankYouOption.java @@ -20,8 +20,7 @@ import com.fasterxml.jackson.annotation.JsonValue; public enum ThankYouOption { - PAGE("page"), - MESSAGE("message"); + PAGE("page"), MESSAGE("message"); private String value; @@ -30,11 +29,14 @@ public enum ThankYouOption { } /** - * Given a {@link String} value, this method returns the enum's value that corresponds to the provided string - * representation. + * Given a {@link String} value, this method returns the enum's value that corresponds to the provided + * string representation. * - * @param value the string representation for which an enum value should be returned + * @param value + * the string representation for which an enum value should be returned + * * @return the corresponding enum value + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ public static ThankYouOption fromString(String value) { @@ -50,6 +52,7 @@ public static ThankYouOption fromString(String value) { * Returns the string value of this enum constant. * * @return the string value of this enum constant + * * @since com.adobe.cq.forms.core.components.models.form 4.4.0 */ public String getValue() { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Turnstile.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Turnstile.java index 10d55eeb51..b03e018c5a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Turnstile.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/Turnstile.java @@ -19,8 +19,8 @@ import org.osgi.annotation.versioning.ConsumerType; /** - * Defines the form {@code Turnstile} Sling Model used for the {@code /apps/core/fd/components/form/turnstile/v1/turnstile} - * component. + * Defines the form {@code Turnstile} Sling Model used for the + * {@code /apps/core/fd/components/form/turnstile/v1/turnstile} component. * * @since com.adobe.cq.forms.core.components.models.form 5.10.0 */ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java index 28bc21d5c0..37631b672a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/models/form/package-info.java @@ -15,23 +15,24 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /** *

- * This package defines the Sling Models exposed by the Adobe Experience Manager Forms Components Bundle for the form components. + * This package defines the Sling Models exposed by the Adobe Experience Manager Forms Components Bundle for the form + * components. *

*

- * Implementors of this API can choose which API level they support, by implementing all the methods up to a specified version of the - * API. All the provided interfaces document in which API version they were added. Furthermore, all methods also specify the API - * version in which they were introduced and deprecated. + * Implementors of this API can choose which API level they support, by implementing all the methods up to a specified + * version of the API. All the provided interfaces document in which API version they were added. Furthermore, all + * methods also specify the API version in which they were introduced and deprecated. *

*

- * All the interfaces from this package provide {@code default} methods that throw {@link java.lang.UnsupportedOperationException}s. - * The reasoning behind this pattern is that implementors can upgrade the bundle without being forced to implement all the - * new methods provided by a newer API version, since the interfaces from this package are - * {@link org.osgi.annotation.versioning.ConsumerType}s. An {@link java.lang.UnsupportedOperationException} could be thrown when a - * component script would start using the newer API, without the actual implementation to support it. This can happen when an - * implementor migrates a - * proxy component - * to a newer version of the core component it proxies and a custom Sling Model implementation, supporting an older API - * version, is bound to this proxy component resource type. + * All the interfaces from this package provide {@code default} methods that throw + * {@link java.lang.UnsupportedOperationException}s. The reasoning behind this pattern is that implementors can upgrade + * the bundle without being forced to implement all the new methods provided by a newer API version, since the + * interfaces from this package are {@link org.osgi.annotation.versioning.ConsumerType}s. An + * {@link java.lang.UnsupportedOperationException} could be thrown when a component script would start using the newer + * API, without the actual implementation to support it. This can happen when an implementor migrates a proxy + * component to a newer version of the core component it proxies and a custom Sling Model implementation, + * supporting an older API version, is bound to this proxy component resource type. *

*/ diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractBaseImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractBaseImpl.java index a786a8df35..2113c4b627 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractBaseImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractBaseImpl.java @@ -71,7 +71,9 @@ public abstract class AbstractBaseImpl extends AbstractFormComponentImpl impleme @Default(booleanValues = false) protected boolean tooltipVisible; - @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_TYPE) // needs to be implemented in dialog + @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_TYPE) // needs to be + // implemented in + // dialog @Nullable protected String typeJcr; // todo: note this should never be array, we infer array types based on other metadata protected Type type; @@ -135,6 +137,7 @@ protected void initBaseModel() { * Returns label of the form field * * @return label of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -166,7 +169,8 @@ public boolean isTooltipVisible() { public String getScreenReaderText() { // needs to be represented as json formula since labels, name, description can be dynamic, and hence // screen reader text can be dynamic - String screenReaderText = null; // only if assist priority is set in JCR, we return screenReaderText to the client + String screenReaderText = null; // only if assist priority is set in JCR, we return screenReaderText to the + // client if (AssistPriority.LABEL.equals(assistPriority)) { Label label = getLabel(); if (label != null) { @@ -206,6 +210,7 @@ public String getHtmlScreenReaderText() { * Returns the description of the field * * @return the description of the field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -218,6 +223,7 @@ public String getDescription() { * Returns {@code true} if form field should be enabled, otherwise {@code false}. * * @return {@code true} if form field should be enabled, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -339,103 +345,113 @@ private class ConstraintMessagesProvider implements ConstraintMessages { @Override @Nullable public String getTypeConstraintMessage() { - return translate(ReservedProperties.PN_TYPE_MESSAGE, properties.get(ReservedProperties.PN_TYPE_MESSAGE, String.class)); + return translate(ReservedProperties.PN_TYPE_MESSAGE, + properties.get(ReservedProperties.PN_TYPE_MESSAGE, String.class)); } @Override @Nullable public String getRequiredConstraintMessage() { - return translate(ReservedProperties.PN_REQUIRED_MESSAGE, properties.get(ReservedProperties.PN_REQUIRED_MESSAGE, String.class)); + return translate(ReservedProperties.PN_REQUIRED_MESSAGE, + properties.get(ReservedProperties.PN_REQUIRED_MESSAGE, String.class)); } @Override @Nullable public String getMinimumConstraintMessage() { - return translate(ReservedProperties.PN_MINIMUM_MESSAGE, properties.get(ReservedProperties.PN_MINIMUM_MESSAGE, String.class)); + return translate(ReservedProperties.PN_MINIMUM_MESSAGE, + properties.get(ReservedProperties.PN_MINIMUM_MESSAGE, String.class)); } @Override @Nullable public String getMaximumConstraintMessage() { - return translate(ReservedProperties.PN_MAXIMUM_MESSAGE, properties.get(ReservedProperties.PN_MAXIMUM_MESSAGE, String.class)); + return translate(ReservedProperties.PN_MAXIMUM_MESSAGE, + properties.get(ReservedProperties.PN_MAXIMUM_MESSAGE, String.class)); } @Override @Nullable public String getMinLengthConstraintMessage() { - return translate(ReservedProperties.PN_MINLENGTH_MESSAGE, properties.get(ReservedProperties.PN_MINLENGTH_MESSAGE, - String.class)); + return translate(ReservedProperties.PN_MINLENGTH_MESSAGE, + properties.get(ReservedProperties.PN_MINLENGTH_MESSAGE, String.class)); } @Override @Nullable public String getMaxLengthConstraintMessage() { - return translate(ReservedProperties.PN_MAXLENGTH_MESSAGE, properties.get(ReservedProperties.PN_MAXLENGTH_MESSAGE, - String.class)); + return translate(ReservedProperties.PN_MAXLENGTH_MESSAGE, + properties.get(ReservedProperties.PN_MAXLENGTH_MESSAGE, String.class)); } @Override @Nullable public String getMaxFileSizeConstraintMessage() { - return translate(ReservedProperties.PN_MAX_FILE_SIZE_MESSAGE, properties.get(ReservedProperties.PN_MAX_FILE_SIZE_MESSAGE, - String.class)); + return translate(ReservedProperties.PN_MAX_FILE_SIZE_MESSAGE, + properties.get(ReservedProperties.PN_MAX_FILE_SIZE_MESSAGE, String.class)); } @Override @Nullable public String getAcceptConstraintMessage() { - return translate(ReservedProperties.PN_ACCEPT_MESSAGE, properties.get(ReservedProperties.PN_ACCEPT_MESSAGE, String.class)); + return translate(ReservedProperties.PN_ACCEPT_MESSAGE, + properties.get(ReservedProperties.PN_ACCEPT_MESSAGE, String.class)); } @Override @Nullable public String getStepConstraintMessage() { - return translate(ReservedProperties.PN_STEP_MESSAGE, properties.get(ReservedProperties.PN_STEP_MESSAGE, String.class)); + return translate(ReservedProperties.PN_STEP_MESSAGE, + properties.get(ReservedProperties.PN_STEP_MESSAGE, String.class)); } @Override @Nullable public String getFormatConstraintMessage() { - return translate(ReservedProperties.PN_FORMAT_MESSAGE, properties.get(ReservedProperties.PN_FORMAT_MESSAGE, String.class)); + return translate(ReservedProperties.PN_FORMAT_MESSAGE, + properties.get(ReservedProperties.PN_FORMAT_MESSAGE, String.class)); } @Override @Nullable public String getPatternConstraintMessage() { - return translate(ReservedProperties.PN_PATTERN_MESSAGE, properties.get(ReservedProperties.PN_PATTERN_MESSAGE, String.class)); + return translate(ReservedProperties.PN_PATTERN_MESSAGE, + properties.get(ReservedProperties.PN_PATTERN_MESSAGE, String.class)); } @Override @Nullable public String getMinItemsConstraintMessage() { - return translate(ReservedProperties.PN_MINITEMS_MESSAGE, properties.get(ReservedProperties.PN_MINITEMS_MESSAGE, String.class)); + return translate(ReservedProperties.PN_MINITEMS_MESSAGE, + properties.get(ReservedProperties.PN_MINITEMS_MESSAGE, String.class)); } @Override @Nullable public String getMaxItemsConstraintMessage() { - return translate(ReservedProperties.PN_MAXITEMS_MESSAGE, properties.get(ReservedProperties.PN_MAXITEMS_MESSAGE, String.class)); + return translate(ReservedProperties.PN_MAXITEMS_MESSAGE, + properties.get(ReservedProperties.PN_MAXITEMS_MESSAGE, String.class)); } @Override @Nullable public String getUniqueItemsConstraintMessage() { - return translate(ReservedProperties.PN_UNIQUE_ITEMS_MESSAGE, properties.get(ReservedProperties.PN_UNIQUE_ITEMS_MESSAGE, - String.class)); + return translate(ReservedProperties.PN_UNIQUE_ITEMS_MESSAGE, + properties.get(ReservedProperties.PN_UNIQUE_ITEMS_MESSAGE, String.class)); } @Override @Nullable public String getEnforceEnumConstraintMessage() { - return translate(ReservedProperties.PN_ENFORCE_ENUM_MESSAGE, properties.get(ReservedProperties.PN_ENFORCE_ENUM_MESSAGE, - String.class)); + return translate(ReservedProperties.PN_ENFORCE_ENUM_MESSAGE, + properties.get(ReservedProperties.PN_ENFORCE_ENUM_MESSAGE, String.class)); } @Override @Nullable public String getValidationExpressionConstraintMessage() { - return translate(ReservedProperties.PN_VALIDATION_EXPRESSION_MESSAGE, properties.get( - ReservedProperties.PN_VALIDATION_EXPRESSION_MESSAGE, String.class)); + return translate(ReservedProperties.PN_VALIDATION_EXPRESSION_MESSAGE, + properties.get(ReservedProperties.PN_VALIDATION_EXPRESSION_MESSAGE, String.class)); } } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCaptchaImplV2.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCaptchaImplV2.java index cc1e17c282..5431fb922a 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCaptchaImplV2.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCaptchaImplV2.java @@ -28,21 +28,17 @@ /** * AbstractCaptchaImplV2 is an updated implementation for handling captcha field types. * - * This class represents an evolution in the captcha JSON structure where captchaProvider - * is promoted to a top-level property, improving JSON clarity and eliminating redundancy. + * This class represents an evolution in the captcha JSON structure where captchaProvider is promoted to a top-level + * property, improving JSON clarity and eliminating redundancy. * - * Background: - * Previous Implementation (AbstractCaptchaImpl): - * - Captcha provider information was embedded within the fd:captcha custom property - * - This led to redundant data and a less clean JSON structure with the updated forms spec + * Background: Previous Implementation (AbstractCaptchaImpl): - Captcha provider information was embedded within the + * fd:captcha custom property - This led to redundant data and a less clean JSON structure with the updated forms spec * - * Current Implementation (AbstractCaptchaImplV2): - * - CaptchaProvider is now a first-class citizen at the root level of the JSON - * - This change results in a cleaner and more efficient JSON structure + * Current Implementation (AbstractCaptchaImplV2): - CaptchaProvider is now a first-class citizen at the root level of + * the JSON - This change results in a cleaner and more efficient JSON structure * - * Note: AbstractCaptchaImpl is not deprecated yet, as it is still used by - * recaptcha/hcaptcha v1 implementations in core components. Once these are migrated - * to AbstractCaptchaImplV2, the V1 implementation will be deprecated. + * Note: AbstractCaptchaImpl is not deprecated yet, as it is still used by recaptcha/hcaptcha v1 implementations in core + * components. Once these are migrated to AbstractCaptchaImplV2, the V1 implementation will be deprecated. */ public abstract class AbstractCaptchaImplV2 extends AbstractCaptchaImpl implements Captcha { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCheckboxImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCheckboxImpl.java index 6ea1c9dfac..a0850cfd8b 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCheckboxImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractCheckboxImpl.java @@ -46,7 +46,8 @@ public void initBaseCheckboxModel() { checkedValue = String.valueOf(getEnums()[0]); uncheckedValue = getEnums().length > 1 ? String.valueOf(getEnums()[1]) : null; } - enums = (checkedValue != null) ? (Boolean.TRUE.equals(enableUncheckedValue)) ? new String[] { checkedValue, uncheckedValue } + enums = (checkedValue != null) ? (Boolean.TRUE.equals(enableUncheckedValue)) + ? new String[] { checkedValue, uncheckedValue } : new String[] { checkedValue } : null; } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractComponentImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractComponentImpl.java index cbf4c0e2d6..63b52cc6d8 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractComponentImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractComponentImpl.java @@ -120,7 +120,8 @@ protected Page getCurrentPage() { /** * Setter for current page. * - * @param currentPage The {@link Page} to set + * @param currentPage + * The {@link Page} to set */ protected void setCurrentPage(Page currentPage) { this.currentPage = currentPage; @@ -129,7 +130,8 @@ protected void setCurrentPage(Page currentPage) { @PostConstruct private void init() { // Setting currentPage to ResourcePage to prevent id miss-match when invoked via iframe mode in sites. - if (currentPage != null && resource != null && request.getAttribute(FormConstants.REQ_ATTR_REFERENCED_PATH) != null) { + if (currentPage != null && resource != null + && request.getAttribute(FormConstants.REQ_ATTR_REFERENCED_PATH) != null) { if (!GuideWCMUtils.isForms(getCurrentPage().getPath())) { PageManager pageManager = currentPage.getPageManager(); String pagePath = (String) request.getAttribute(FormConstants.REQ_ATTR_REFERENCED_PATH); @@ -145,7 +147,8 @@ private void init() { @Override public String getId() { if (id == null) { - String resourceCallerPath = request != null ? (String) request.getAttribute(REQ_ATTR_RESOURCE_CALLER_PATH) : null; + String resourceCallerPath = request != null ? (String) request.getAttribute(REQ_ATTR_RESOURCE_CALLER_PATH) + : null; this.id = ComponentUtils.getId(this.resource, this.currentPage, resourceCallerPath, this.componentContext); } return id; @@ -168,7 +171,8 @@ public ComponentData getData() { if (componentData == null) { if (this.dataLayerEnabled == null) { if (this.currentPage != null) { - // Check at page level to allow components embedded via containers in editable templates to inherit the setting + // Check at page level to allow components embedded via containers in editable templates to inherit + // the setting this.dataLayerEnabled = ComponentUtils.isDataLayerEnabled(this.currentPage.getContentResource()); } else { this.dataLayerEnabled = ComponentUtils.isDataLayerEnabled(this.resource); @@ -191,9 +195,18 @@ public ComponentData getData() { public String getAppliedCssClasses() { return Optional.ofNullable(this.resource.adaptTo(ComponentStyleInfo.class)) - .map(ComponentStyleInfo::getAppliedCssClasses) - .filter(StringUtils::isNotBlank) - .orElse(null); // Returning null so sling model exporters don't return anything for this property if not configured + .map(ComponentStyleInfo::getAppliedCssClasses).filter(StringUtils::isNotBlank).orElse(null); // Returning + // null so + // sling + // model + // exporters + // don't + // return + // anything + // for this + // property + // if not + // configured } /** @@ -204,17 +217,13 @@ public String getAppliedCssClasses() { */ @NotNull protected ComponentData getComponentData() { - return DataLayerBuilder.forComponent() - .withId(this::getId) - .withLastModifiedDate(() -> - // Note: this can be simplified in JDK 11 - Optional.ofNullable(resource.getValueMap().get(JcrConstants.JCR_LASTMODIFIED, Calendar.class)) - .map(Calendar::getTime) - .orElseGet(() -> Optional.ofNullable(resource.getValueMap().get(JcrConstants.JCR_CREATED, Calendar.class)) - .map(Calendar::getTime) - .orElse(null))) - .withType(() -> this.resource.getResourceType()) - .build(); + return DataLayerBuilder.forComponent().withId(this::getId).withLastModifiedDate(() -> + // Note: this can be simplified in JDK 11 + Optional.ofNullable(resource.getValueMap().get(JcrConstants.JCR_LASTMODIFIED, Calendar.class)) + .map(Calendar::getTime).orElseGet( + () -> Optional.ofNullable(resource.getValueMap().get(JcrConstants.JCR_CREATED, Calendar.class)) + .map(Calendar::getTime).orElse(null))) + .withType(() -> this.resource.getResourceType()).build(); } @Nullable @@ -222,7 +231,8 @@ protected String translate(@NotNull String propertyName, @Nullable String proper if (StringUtils.isBlank(propertyValue)) { return null; } - return com.adobe.cq.forms.core.components.util.ComponentUtils.translate(propertyValue, propertyName, resource, i18n); + return com.adobe.cq.forms.core.components.util.ComponentUtils.translate(propertyValue, propertyName, resource, + i18n); } } \ No newline at end of file diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractContainerImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractContainerImpl.java index 71cf235d8b..34dac05869 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractContainerImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractContainerImpl.java @@ -139,13 +139,14 @@ public String[] getExportedItemsOrder() { return Arrays.copyOf(exportedItemsOrder, exportedItemsOrder.length); } - protected Map getChildrenModels(@Nullable SlingHttpServletRequest request, @NotNull Class modelClass) { + protected Map getChildrenModels(@Nullable SlingHttpServletRequest request, + @NotNull Class modelClass) { List filteredChildrenResources = getFilteredChildrenResources(); return getChildrenModels(request, modelClass, filteredChildrenResources); } - protected Map getChildrenModels(@Nullable SlingHttpServletRequest request, @NotNull Class modelClass, - List filteredChildrenResources) { + protected Map getChildrenModels(@Nullable SlingHttpServletRequest request, + @NotNull Class modelClass, List filteredChildrenResources) { Map models = new LinkedHashMap<>(); for (Resource child : filteredChildrenResources) { T model = null; @@ -154,7 +155,8 @@ protected Map getChildrenModels(@Nullable SlingHttpServletRequest ValueMap additionalProperties = new ValueMapDecorator(new HashMap<>()); additionalProperties.put("fd:channel", this.channel); ValueMap properties = ValueMapUtil.merge(ResourceUtil.getValueMap(child), additionalProperties); - child = new ValueMapResource(child.getResourceResolver(), child.getPath(), child.getResourceType(), properties); + child = new ValueMapResource(child.getResourceResolver(), child.getPath(), child.getResourceType(), + properties); } if (request != null) { // todo: if possible set i18n form parent to child here, this would optimize the first form rendering @@ -167,10 +169,12 @@ protected Map getChildrenModels(@Nullable SlingHttpServletRequest ((FormComponent) model).setLang(lang); } } catch (Exception e) { - // Log the exception as info, since there can be site component inside form, but we don't care about they being adapted + // Log the exception as info, since there can be site component inside form, but we don't care about + // they being adapted // or not // by default, site component cannot be adapted with resource - logger.info("Could not adapt resource {} to model class {}: {}", child.getPath(), modelClass.getName(), e.getMessage()); + logger.info("Could not adapt resource {} to model class {}: {}", child.getPath(), + modelClass.getName(), e.getMessage()); } } if (model != null) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java index 9e19a5bb38..700369d81c 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFieldImpl.java @@ -42,9 +42,7 @@ public abstract class AbstractFieldImpl extends AbstractBaseImpl implements Fiel * Enum representing the possible values for emptyValue property. */ public static enum EmptyValue { - NULL("null"), - UNDEFINED("undefined"), - EMPTY_STRING(""); + NULL("null"), UNDEFINED("undefined"), EMPTY_STRING(""); private final String value; @@ -57,8 +55,7 @@ public String getValue() { } /** - * Converts a string value to EmptyValue enum. - * Returns EMPTY_STRING for any unrecognized values. + * Converts a string value to EmptyValue enum. Returns EMPTY_STRING for any unrecognized values. */ public static EmptyValue fromString(String value) { if (value == null) { @@ -196,15 +193,13 @@ public Boolean getRequiredIfPresent() { @Override public Object[] getDefault() { if (defaultValue != null) { - return Arrays.stream(defaultValue) - .map(p -> { - if (p instanceof Calendar) { - return ((Calendar) p).getTime(); - } else { - return p; - } - }) - .toArray(); + return Arrays.stream(defaultValue).map(p -> { + if (p instanceof Calendar) { + return ((Calendar) p).getTime(); + } else { + return p; + } + }).toArray(); } return null; } diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java index 74bdfcafc7..dec90678a8 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImpl.java @@ -137,6 +137,7 @@ public class AbstractFormComponentImpl extends AbstractComponentImpl implements * Returns dorBindRef of the form field * * @return dorBindRef of the field + * * @since com.adobe.cq.forms.core.components.util 4.0.0 */ @JsonIgnore @@ -226,6 +227,7 @@ public String getText() { * Returns the name of the form field * * @return name of the form field + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -245,6 +247,7 @@ protected String getDefaultName() { * Returns the view type * * @return the view type + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -263,6 +266,7 @@ protected String getFieldType(@Nonnull FieldType defaultFieldType) { * Returns {@code true} if form field should be visible, otherwise {@code false}. * * @return {@code true} if form field should be visible, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -294,7 +298,8 @@ protected boolean getEditMode() { // TODO: for some reason sling model wrapper request (through model.json) is giving incorrect wcmmode // we anyways dont need to rely on wcmmode while fetching form definition. if (!matches) { - editMode = WCMMode.fromRequest(request) == WCMMode.EDIT || WCMMode.fromRequest(request) == WCMMode.DESIGN; + editMode = WCMMode.fromRequest(request) == WCMMode.EDIT + || WCMMode.fromRequest(request) == WCMMode.DESIGN; } } return editMode; @@ -315,13 +320,11 @@ protected boolean getEditMode() { public static final String CUSTOM_RULE_PROPERTY_WRAPPER = "fd:rules"; /** - * Predicate to check if a map entry is non empty - * return true if and only if - * 1) the value is not of type string and non empty or - * 2) the value is of type string[] and has more than 1 elements + * Predicate to check if a map entry is non empty return true if and only if 1) the value is not of type string and + * non empty or 2) the value is of type string[] and has more than 1 elements */ - private final Predicate> isEntryNonEmpty = obj -> (obj.getValue() instanceof String && ((String) obj - .getValue()).length() > 0) + private final Predicate> isEntryNonEmpty = obj -> (obj.getValue() instanceof String + && ((String) obj.getValue()).length() > 0) || (obj.getValue() instanceof String[] && ((String[]) obj.getValue()).length > 0); @Override @@ -362,20 +365,21 @@ public Map getRules() { } /** - * Returns rules (visible, required, etc.) for the given resource. Used when exporting - * fragment components so that rules configured on the referenced fragment are - * included in the stitched output as root-level "rules" (parallel to "events"). + * Returns rules (visible, required, etc.) for the given resource. Used when exporting fragment components so that + * rules configured on the referenced fragment are included in the stitched output as root-level "rules" (parallel + * to "events"). * - * @param resource the resource that may have an fd:rules child + * @param resource + * the resource that may have an fd:rules child + * * @return map of rule name to expression, never null */ protected final Map getRulesForResource(Resource resource) { - String[] VALID_RULES = new String[] { "description", "enabled", "enum", "enumNames", - "exclusiveMaximum", "exclusiveMinimum", "label", "maximum", "minimum", - "readOnly", "required", "value", "visible" }; + String[] VALID_RULES = new String[] { "description", "enabled", "enum", "enumNames", "exclusiveMaximum", + "exclusiveMinimum", "label", "maximum", "minimum", "readOnly", "required", "value", "visible" }; - Predicate> isRuleNameValid = obj -> Arrays.stream(VALID_RULES).anyMatch(validKey -> validKey.equals(obj - .getKey())); + Predicate> isRuleNameValid = obj -> Arrays.stream(VALID_RULES) + .anyMatch(validKey -> validKey.equals(obj.getKey())); Predicate> isRuleValid = isEntryNonEmpty.and(isRuleNameValid); @@ -385,9 +389,7 @@ protected final Map getRulesForResource(Resource resource) { Resource ruleNode = resource.getChild("fd:rules"); if (ruleNode != null) { ValueMap ruleNodeProps = ruleNode.getValueMap(); - return ruleNodeProps.entrySet() - .stream() - .filter(isRuleValid) + return ruleNodeProps.entrySet().stream().filter(isRuleValid) .map(entry -> new AbstractMap.SimpleEntry<>(entry.getKey(), (String) entry.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } @@ -400,11 +402,12 @@ private Map getRulesProperties() { } /** - * Returns rules properties (fd:rules) for the given resource. Used when exporting - * fragment components so that rules configured on the referenced fragment are - * included in the stitched output. + * Returns rules properties (fd:rules) for the given resource. Used when exporting fragment components so that rules + * configured on the referenced fragment are included in the stitched output. * - * @param resource the resource that may have an fd:rules child + * @param resource + * the resource that may have an fd:rules child + * * @return map of rules properties, never null */ protected final Map getRulesPropertiesForResource(Resource resource) { @@ -431,8 +434,10 @@ private void addValidationStatus(Resource ruleNode, Map customRu } } - private void populateAdditionalRulesProperties(@NotNull Resource ruleNode, Map customRulesProperties) { - String[] RULES = { "fd:formReady", "fd:layoutReady", "fd:docReady", "fd:calc", "fd:init", "fd:validate", "fd:indexChange" }; + private void populateAdditionalRulesProperties(@NotNull Resource ruleNode, + Map customRulesProperties) { + String[] RULES = { "fd:formReady", "fd:layoutReady", "fd:docReady", "fd:calc", "fd:init", "fd:validate", + "fd:indexChange" }; ValueMap props = ruleNode.adaptTo(ValueMap.class); if (props != null) { Arrays.stream(RULES).forEach(rule -> addRuleProperty(props, customRulesProperties, rule)); @@ -448,6 +453,7 @@ private void addRuleProperty(@NotNull ValueMap props, Map custom * If atleast one rule is invalid then status of rule for component is considered as invalid * * @param rulesResource + * * @return */ private String getRulesStatus(Resource rulesResource) { @@ -468,20 +474,21 @@ private String getRulesStatus(Resource rulesResource) { } /** - * Sanitizes the event entry by - * * removing invalid event names, - * * removing events where the handler is not of type string or string[] - * * converts all the event handlers into string[] for easy consumption - * * updates custom event key (as we cannot save custom:eventName in JCR) + * Sanitizes the event entry by * removing invalid event names, * removing events where the handler is not of type + * string or string[] * converts all the event handlers into string[] for easy consumption * updates custom event + * key (as we cannot save custom:eventName in JCR) * - * @param entry the event entry to manipulate + * @param entry + * the event entry to manipulate + * * @return the updated event entry */ private Stream> sanitizeEvent(Map.Entry entry) { - String[] VALID_EVENTS = new String[] { "click", "submit", "initialize", "load", "change", "submitSuccess", "submitError" }; + String[] VALID_EVENTS = new String[] { "click", "submit", "initialize", "load", "change", "submitSuccess", + "submitError" }; - Predicate> isEventNameValid = obj -> obj.getKey().startsWith("custom_") || - Arrays.stream(VALID_EVENTS).anyMatch(validKey -> validKey.equals(obj.getKey())); + Predicate> isEventNameValid = obj -> obj.getKey().startsWith("custom_") + || Arrays.stream(VALID_EVENTS).anyMatch(validKey -> validKey.equals(obj.getKey())); Predicate> isEventValid = isEntryNonEmpty.and(isEventNameValid); Stream> updatedEntry; @@ -517,11 +524,12 @@ public Map getEvents() { } /** - * Returns events (fd:events) for the given resource. Used when exporting - * fragment components so that events configured on the referenced fragment are - * included in the stitched output. + * Returns events (fd:events) for the given resource. Used when exporting fragment components so that events + * configured on the referenced fragment are included in the stitched output. * - * @param resource the resource that may have an fd:events child + * @param resource + * the resource that may have an fd:events child + * * @return map of event name to handler expressions, never null */ protected final Map getEventsForResource(Resource resource) { @@ -533,8 +541,7 @@ protected final Map getEventsForResource(Resource resource) { eventSet.addAll(eventNodeProps.entrySet()); } } - return eventSet.stream() - .flatMap(this::sanitizeEvent) + return eventSet.stream().flatMap(this::sanitizeEvent) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } @@ -542,6 +549,7 @@ protected final Map getEventsForResource(Resource resource) { * Returns the reference to the data model * * @return reference to the data model + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -556,6 +564,7 @@ public String getDataRef() { * Returns getPath of the form field * * @return getPath of the field + * * @since com.adobe.cq.forms.core.components.util 3.1.0 */ @Override @@ -590,9 +599,10 @@ public FormComponentData getData() { if (componentData == null) { if (this.dataLayerEnabled == null) { if (this.getCurrentPage() != null) { - // Check at page level to allow components embedded via containers in editable templates to inherit the setting - this.dataLayerEnabled = com.adobe.cq.wcm.core.components.util.ComponentUtils.isDataLayerEnabled(this.getCurrentPage() - .getContentResource()); + // Check at page level to allow components embedded via containers in editable templates to inherit + // the setting + this.dataLayerEnabled = com.adobe.cq.wcm.core.components.util.ComponentUtils + .isDataLayerEnabled(this.getCurrentPage().getContentResource()); } else { this.dataLayerEnabled = ComponentUtils.isDataLayerEnabled(this.resource); } @@ -606,8 +616,8 @@ public FormComponentData getData() { private static class DataRefSerializer extends JsonSerializer { @Override - public void serialize(String s, JsonGenerator jsonGenerator, - SerializerProvider serializerProvider) throws IOException { + public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException { if (NULL_DATA_REF.equals(s)) { jsonGenerator.writeString((String) null); } else { @@ -622,13 +632,15 @@ public boolean isEmpty(SerializerProvider provider, String value) { } private boolean isAllowedType(Object value) { - return value instanceof String || value instanceof String[] || value instanceof Boolean || value instanceof Boolean[] - || value instanceof Calendar || value instanceof Calendar[] || value instanceof BigDecimal - || value instanceof BigDecimal[] || value instanceof Long || value instanceof Long[]; + return value instanceof String || value instanceof String[] || value instanceof Boolean + || value instanceof Boolean[] || value instanceof Calendar || value instanceof Calendar[] + || value instanceof BigDecimal || value instanceof BigDecimal[] || value instanceof Long + || value instanceof Long[]; } /** - * Fetches all the custom properties associated with a given component's instance (including additional custom properties) + * Fetches all the custom properties associated with a given component's instance (including additional custom + * properties) * * @return {@code Map} returns all custom property key value pairs associated with the resource */ @@ -639,17 +651,14 @@ private Map getCustomProperties() { Set reservedProperties = ReservedProperties.getReservedProperties(); ValueMap resourceMap = resource.getValueMap(); - Map nodeBasedCustomProperties = resourceMap.entrySet() - .stream() - .filter(entry -> isAllowedType(entry.getValue()) - && !reservedProperties.contains(entry.getKey()) + Map nodeBasedCustomProperties = resourceMap.entrySet().stream() + .filter(entry -> isAllowedType(entry.getValue()) && !reservedProperties.contains(entry.getKey()) && excludedPrefixes.stream().noneMatch(prefix -> entry.getKey().startsWith(prefix))) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); nodeBasedCustomProperties.forEach(customProperties::putIfAbsent); try { templateBasedCustomProperties = Optional.ofNullable(this.resource.adaptTo(CustomPropertyInfo.class)) - .map(CustomPropertyInfo::getProperties) - .orElse(Collections.emptyMap()); + .map(CustomPropertyInfo::getProperties).orElse(Collections.emptyMap()); } catch (NoClassDefFoundError e) { logger.info("CustomPropertyInfo class not found. This feature is available in the latest Forms addon."); templateBasedCustomProperties = Collections.emptyMap(); @@ -665,7 +674,8 @@ private Map getAssociateProperties() { Resource associatePropertiesResource = resource.getChild(CUSTOM_ASSOCIATE_PROPERTY_WRAPPER); if (associatePropertiesResource != null) { try { - AssociateProperties associateProperties = associatePropertiesResource.adaptTo(AssociateProperties.class); + AssociateProperties associateProperties = associatePropertiesResource + .adaptTo(AssociateProperties.class); ObjectMapper objectMapper = new ObjectMapper(); if (associateProperties != null) { return objectMapper.convertValue(associateProperties, new TypeReference>() {}); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java index ce1ac5c3d3..e0d5d9351d 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/AbstractOptionsFieldImpl.java @@ -53,9 +53,9 @@ public abstract class AbstractOptionsFieldImpl extends AbstractFieldImpl impleme protected String[] enumNames; /** - * Default for single and multivalued fields used the same 'default' crx property. - * This was not compatible with Universal Editor's Property Rail Configuration. - * Therefore, adding this property as an additional way of defining default values. + * Default for single and multivalued fields used the same 'default' crx property. This was not compatible with + * Universal Editor's Property Rail Configuration. Therefore, adding this property as an additional way of defining + * default values. **/ @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL, name = ReservedProperties.PN_MULTI_DEFAULT_VALUES) @Nullable @@ -88,8 +88,8 @@ private Map getEnumPairs() { } } String[] finalEnumNamesArray = enumNamesArray != null ? enumNamesArray : new String[enumArray.length]; - map = IntStream.range(0, enumArray.length).collect(LinkedHashMap::new, (m, i) -> m.put(enumArray[i], finalEnumNamesArray[i]), - LinkedHashMap::putAll); + map = IntStream.range(0, enumArray.length).collect(LinkedHashMap::new, + (m, i) -> m.put(enumArray[i], finalEnumNamesArray[i]), LinkedHashMap::putAll); } return map; @@ -101,7 +101,8 @@ public Object[] getEnums() { if (enums == null) { return null; } else { - // todo: we can only typecast to number or boolean if type is present in JCR, for array types, we need to store the type of each + // todo: we can only typecast to number or boolean if type is present in JCR, for array types, we need to + // store the type of each // array element in JCR // todo: and compute based on it (hence using typeJcr below) // may expose internal representation of mutable object, hence cloning diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/CacheManager.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/CacheManager.java index 49177cf655..3de5a1eb59 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/CacheManager.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/CacheManager.java @@ -44,9 +44,10 @@ public class CacheManager { /** * Retrieves a value from the cache if it exists and has not expired * - * @param cacheKey The key to look up in the cache - * @return The cached List if found and valid, null if not found or - * expired + * @param cacheKey + * The key to look up in the cache + * + * @return The cached List if found and valid, null if not found or expired */ public static List getFromCache(String cacheKey) { Long timestamp = CACHE_TIMESTAMPS.get(cacheKey); @@ -66,8 +67,10 @@ public static List getFromCache(String cacheKey) { /** * Stores a value in the cache with the current timestamp * - * @param cacheKey The key under which to store the value - * @param value The List value to cache + * @param cacheKey + * The key under which to store the value + * @param value + * The List value to cache */ public static void putInCache(String cacheKey, List value) { SUBMIT_ACTIONS_CACHE.put(cacheKey, value); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java index 3571b0a73f..e93915589f 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/ComponentUtils.java @@ -61,7 +61,8 @@ public class ComponentUtils { private static final String EDGE_DELIVERY_FRAGMENT_CONTAINER_REL_PATH = "root/section/form"; - private static final String[] EDGE_DELIVERY_RESOURCE_TYPES = new String[] { "core/franklin/components/page/v1/page" }; + private static final String[] EDGE_DELIVERY_RESOURCE_TYPES = new String[] { + "core/franklin/components/page/v1/page" }; private static final Logger logger = LoggerFactory.getLogger(ComponentUtils.class); private ComponentUtils() { @@ -69,15 +70,16 @@ private ComponentUtils() { } /** - * Checks whether a feature toggle is enabled via a system property. The property is set/unset - * by the Granite Toggle API when the toggle is wired via OSGi factory - * {@code com.adobe.granite.toggle.monitor.systemproperty} (see + * Checks whether a feature toggle is enabled via a system property. The property is set/unset by the Granite Toggle + * API when the toggle is wired via OSGi factory {@code com.adobe.granite.toggle.monitor.systemproperty} (see * {@link com.adobe.cq.forms.core.components.internal.form.FeatureToggleConstants} for setup). *

* Convention: the system property name is the toggle ID; value {@code "true"} (via * {@link Boolean#parseBoolean(String)}) means enabled. * - * @param toggleId the toggle identifier (also used as the system property name) + * @param toggleId + * the toggle identifier (also used as the system property name) + * * @return true if the system property is set to "true", false otherwise */ public static boolean isToggleEnabledBySystemProperty(@NotNull String toggleId) { @@ -87,7 +89,10 @@ public static boolean isToggleEnabledBySystemProperty(@NotNull String toggleId) /** * Checks whether a feature toggle is enabled (system property only). * - * @param toggleId the toggle identifier (e.g. from {@link com.adobe.cq.forms.core.components.internal.form.FeatureToggleConstants}) + * @param toggleId + * the toggle identifier (e.g. from + * {@link com.adobe.cq.forms.core.components.internal.form.FeatureToggleConstants}) + * * @return true if the toggle is enabled, false otherwise */ public static boolean isToggleEnabled(@NotNull String toggleId) { @@ -95,11 +100,13 @@ public static boolean isToggleEnabled(@NotNull String toggleId) { } /** - * Determines whether the current request is in author mode. Returns {@code true} when the - * request is in WCM EDIT or DESIGN mode and has not been explicitly marked as a publish-view - * request (e.g. via {@link FormConstants#REQ_ATTR_PUBLISH_VIEW}). + * Determines whether the current request is in author mode. Returns {@code true} when the request is in WCM EDIT or + * DESIGN mode and has not been explicitly marked as a publish-view request (e.g. via + * {@link FormConstants#REQ_ATTR_PUBLISH_VIEW}). * - * @param request the current request, may be {@code null} + * @param request + * the current request, may be {@code null} + * * @return {@code true} if the request is in author mode, {@code false} otherwise */ public static boolean isAuthorMode(@Nullable SlingHttpServletRequest request) { @@ -116,7 +123,9 @@ public static boolean isAuthorMode(@Nullable SlingHttpServletRequest request) { /** * Returns the base64 encoded path * - * @param path page path + * @param path + * page path + * * @return base64 encoded path */ @NotNull @@ -127,7 +136,9 @@ public static String getEncodedPath(@NotNull String path) { /** * Checks if the given resource if a core adaptive form container * - * @param resource reference to the {@link Resource} + * @param resource + * reference to the {@link Resource} + * * @return true, if it is an adaptive form container, false otherwise */ @NotNull @@ -139,7 +150,9 @@ public static boolean isAFContainer(@NotNull Resource resource) { /** * Returns the form container resource * - * @param resource reference to the {@link Resource} + * @param resource + * reference to the {@link Resource} + * * @return form container resource, null if no form container found */ public static Resource getFormContainer(Resource resource) { @@ -155,32 +168,42 @@ public static Resource getFormContainer(Resource resource) { /** * Translates the given property as per the {@link I18n} object passed * - * @param propertyValue value of the property (for example, in case of array type property, one needs to pass the value stored in array - * index) - * @param propertyName name of the property - * @param resource reference to the {@link Resource} - * @param i18n reference to the {@link I18n} object + * @param propertyValue + * value of the property (for example, in case of array type property, one needs to pass the value stored + * in array index) + * @param propertyName + * name of the property + * @param resource + * reference to the {@link Resource} + * @param i18n + * reference to the {@link I18n} object + * * @return translated value */ @NotNull - public static String translate(@NotNull String propertyValue, @NotNull String propertyName, @NotNull Resource resource, - @Nullable I18n i18n) { + public static String translate(@NotNull String propertyValue, @NotNull String propertyName, + @NotNull Resource resource, @Nullable I18n i18n) { return translate(propertyValue, propertyName, resource.getValueMap(), i18n); } /** * Translates the given property as per the {@link I18n} object passed * - * @param propertyValue value of the property (for example, in case of array type property, one needs to pass the value stored in array - * index) - * @param propertyName name of the property - * @param valueMap reference to the {@link ValueMap} - * @param i18n reference to the {@link I18n} object + * @param propertyValue + * value of the property (for example, in case of array type property, one needs to pass the value stored + * in array index) + * @param propertyName + * name of the property + * @param valueMap + * reference to the {@link ValueMap} + * @param i18n + * reference to the {@link I18n} object + * * @return translated value */ @NotNull - public static String translate(@NotNull String propertyValue, @NotNull String propertyName, @NotNull ValueMap valueMap, - @Nullable I18n i18n) { + public static String translate(@NotNull String propertyValue, @NotNull String propertyName, + @NotNull ValueMap valueMap, @Nullable I18n i18n) { String translatedValue = propertyValue; if (i18n != null) { translatedValue = GuideUtils.translateOrReturnOriginal(propertyValue, propertyName, i18n, valueMap); @@ -191,28 +214,31 @@ public static String translate(@NotNull String propertyValue, @NotNull String pr /** * Returns clone of the date object (mutable) provided as input * - * @param date date + * @param date + * date + * * @return clone of date object */ public static Date clone(@Nullable Date date) { - return Optional.ofNullable(date) - .map(Date::getTime) - .map(Date::new) - .orElse(null); + return Optional.ofNullable(date).map(Date::getTime).map(Date::new).orElse(null); } /** * Retrieves the exclusive value based on certain conditions. * - * @param exclusiveValue The exclusive value to be checked. - * @param value The actual value to be returned if conditions are met. - * @param exclusiveValueCheck An additional check for exclusive value. + * @param exclusiveValue + * The exclusive value to be checked. + * @param value + * The actual value to be returned if conditions are met. + * @param exclusiveValueCheck + * An additional check for exclusive value. + * * @return The exclusive value if conditions are met; otherwise, null. */ public static T getExclusiveValue(Object exclusiveValue, T value, Object exclusiveValueCheck) { // Check if exclusive value is a boolean and true, and value is not null - if (exclusiveValue instanceof Boolean && (Boolean.TRUE.equals(exclusiveValue) || Boolean.TRUE.equals(exclusiveValueCheck)) - && value != null) { + if (exclusiveValue instanceof Boolean + && (Boolean.TRUE.equals(exclusiveValue) || Boolean.TRUE.equals(exclusiveValueCheck)) && value != null) { // If so, return the value return (T) value; } else if (exclusiveValue instanceof Long) { // special case @@ -225,7 +251,8 @@ public static T getExclusiveValue(Object exclusiveValue, T value, Object exc } else { return null; } - } else if (Boolean.TRUE.equals(exclusiveValueCheck) && value != null) { // backward compatibility case // not to be changed + } else if (Boolean.TRUE.equals(exclusiveValueCheck) && value != null) { // backward compatibility case // not to + // be changed // If so, return the value return (T) value; } else { @@ -235,11 +262,12 @@ public static T getExclusiveValue(Object exclusiveValue, T value, Object exc } /** - * Parses a given string value into a Number. - * The method attempts to parse the string as a Long first, and if that fails, - * it attempts to parse it as a Float. If both parsing attempts fail, it returns null. + * Parses a given string value into a Number. The method attempts to parse the string as a Long first, and if that + * fails, it attempts to parse it as a Float. If both parsing attempts fail, it returns null. * - * @param value the string value to be parsed, can be null + * @param value + * the string value to be parsed, can be null + * * @return the parsed Number (Long or Float), or null if the value cannot be parsed */ public static Number parseNumber(@Nullable String value) { @@ -257,16 +285,10 @@ public static Number parseNumber(@Nullable String value) { @NotNull public static Object[] coerce(@NotNull BaseConstraint.Type type, @NotNull Object[] objArr) { if (type.equals(type.NUMBER) || type.equals(type.NUMBER_ARRAY)) { - return Arrays.stream(objArr) - .filter(Objects::nonNull) - .map(Object::toString) - .map(Long::parseLong) + return Arrays.stream(objArr).filter(Objects::nonNull).map(Object::toString).map(Long::parseLong) .toArray(Long[]::new); } else if (type.equals(type.BOOLEAN) || type.equals(type.BOOLEAN_ARRAY)) { - return Arrays.stream(objArr) - .filter(Objects::nonNull) - .map(Object::toString) - .map(Boolean::parseBoolean) + return Arrays.stream(objArr).filter(Objects::nonNull).map(Object::toString).map(Boolean::parseBoolean) .toArray(Boolean[]::new); } else { return ArrayUtils.clone(objArr); @@ -303,16 +325,16 @@ public static boolean isFragmentComponent(Resource resource) { } /** - * Determines whether submit properties should be included in the form - * definition. + * Determines whether submit properties should be included in the form definition. * *

- * This method checks if the request contains x-adobe-form-definition attribute - * or header and if it is equal to submission - * that indicates submit properties should be included in the form definition. + * This method checks if the request contains x-adobe-form-definition attribute or header and if it is equal to + * submission that indicates submit properties should be included in the form definition. *

* - * @param request the {@link SlingHttpServletRequest} to check + * @param request + * the {@link SlingHttpServletRequest} to check + * * @return true if submit properties should be included, false otherwise */ public static boolean shouldIncludeSubmitProperties(SlingHttpServletRequest request) { @@ -320,29 +342,27 @@ public static boolean shouldIncludeSubmitProperties(SlingHttpServletRequest requ return false; } String submissionHeaderName = FormConstants.FORM_DEFINITION_SUBMISSION; - return submissionHeaderName.equals(request.getAttribute(FormConstants.X_ADOBE_FORM_DEFINITION)) || - submissionHeaderName.equals(request.getHeader(FormConstants.X_ADOBE_FORM_DEFINITION)); + return submissionHeaderName.equals(request.getAttribute(FormConstants.X_ADOBE_FORM_DEFINITION)) + || submissionHeaderName.equals(request.getHeader(FormConstants.X_ADOBE_FORM_DEFINITION)); } /** * Retrieves a list of supported submit actions from the Adobe Forms service. * *

- * This method makes an HTTP GET request to the Adobe Forms service to fetch - * the list of supported submit actions. The response is expected to be a - * JSON object containing a "submissions" array of action names, which is then + * This method makes an HTTP GET request to the Adobe Forms service to fetch the list of supported submit actions. + * The response is expected to be a JSON object containing a "submissions" array of action names, which is then * converted to a list. *

* *

- * If the request fails or an error occurs during processing, an error is logged - * and an empty list is returned. + * If the request fails or an error occurs during processing, an error is logged and an empty list is returned. *

* - * @param clientBuilderFactory The HTTP client builder factory used to create - * the HTTP client - * @return A list of supported submit action names, or an empty list if the - * request fails + * @param clientBuilderFactory + * The HTTP client builder factory used to create the HTTP client + * + * @return A list of supported submit action names, or an empty list if the request fails */ public static List getSupportedSubmitActions(HttpClientBuilderFactory clientBuilderFactory) { // Check cache first @@ -357,13 +377,9 @@ public static List getSupportedSubmitActions(HttpClientBuilderFactory cl return supportedSubmitActions; } try { - RequestConfig requestConfig = RequestConfig.custom() - .setConnectTimeout(5000) - .setSocketTimeout(5000) - .setConnectionRequestTimeout(5000) - .build(); - CloseableHttpClient httpClient = clientBuilderFactory.newBuilder() - .setDefaultRequestConfig(requestConfig) + RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(5000) + .setConnectionRequestTimeout(5000).build(); + CloseableHttpClient httpClient = clientBuilderFactory.newBuilder().setDefaultRequestConfig(requestConfig) .build(); HttpGet httpGet = new HttpGet(supportedSubmitActionsUrl); try (CloseableHttpResponse response = httpClient.execute(httpGet)) { diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/DefaultValueSerializer.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/DefaultValueSerializer.java index 6c448b8695..72b8091b89 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/DefaultValueSerializer.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/DefaultValueSerializer.java @@ -64,8 +64,7 @@ private void serialize(Object value, JsonGenerator gen) throws IOException { } @Override - public void serialize( - Object[] value, JsonGenerator gen, SerializerProvider arg2) + public void serialize(Object[] value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException { if (value.length == 1) { serialize(value[0], gen); diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/LabelImpl.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/LabelImpl.java index 5b3a2877fb..1da8dcc736 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/LabelImpl.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/util/LabelImpl.java @@ -43,6 +43,7 @@ public LabelImpl(Resource field, String defaultTitle, I18n i18n) { * Returns {@code true} if label is rich text, otherwise {@code false}. * * @return {@code true} if label is rich text, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -56,6 +57,7 @@ public Boolean isRichText() { * Returns {@code true} if label should be visible, otherwise {@code false}. * * @return {@code true} if label should be visible, otherwise {@code false} + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override @@ -73,6 +75,7 @@ public Boolean isVisible() { * Returns the value of this label. * * @return the value of this label + * * @since com.adobe.cq.forms.core.components.models.form 0.0.1 */ @Override diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/Views.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/Views.java index 62dd56a224..e455eba85e 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/Views.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/Views.java @@ -23,15 +23,13 @@ public class Views { public static class Publish {} /** - * Use this view for serialising the property required in control plane. - * It is a superset of properties in Publish view. - * Eg: DoR related properties of forms core components + * Use this view for serialising the property required in control plane. It is a superset of properties in Publish + * view. Eg: DoR related properties of forms core components */ public static class Author extends Publish {} /** - * Use this view for including the print-specific properties - * Eg; dorContainer and pageTemplate + * Use this view for including the print-specific properties Eg; dorContainer and pageTemplate */ public static class DoR extends Author {} diff --git a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/package-info.java b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/package-info.java index ffdf14dc18..7f193a2006 100644 --- a/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/package-info.java +++ b/bundles/af-core/src/main/java/com/adobe/cq/forms/core/components/views/package-info.java @@ -15,8 +15,8 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /** *

- * This package defines the JSONViews exposed by the Adobe Experience Manager Forms Components Bundle for the form components. - * It is meant to be used by Jackson serialisation of Sling models of core components. + * This package defines the JSONViews exposed by the Adobe Experience Manager Forms Components Bundle for the form + * components. It is meant to be used by Jackson serialisation of Sling models of core components. *

*/ @Version("1.0.0") diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/Utils.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/Utils.java index ad6744e94a..73b98c5839 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/Utils.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/Utils.java @@ -21,13 +21,19 @@ import java.io.Writer; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Set; +import java.util.stream.Stream; import javax.json.Json; import javax.json.JsonReader; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; +import org.apache.sling.api.resource.Resource; import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest; import org.jetbrains.annotations.NotNull; @@ -39,6 +45,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.google.common.base.Joiner; import com.networknt.schema.JsonSchema; import com.networknt.schema.JsonSchemaFactory; @@ -95,7 +102,8 @@ public static InputStream getCompleteJson(Object model) { * @param expectedJsonResource * the class path resource providing the expected JSON object */ - public static void testJSONExport(Object model, String expectedJsonResource, Class viewType) { + public static void testJSONExport(Object model, String expectedJsonResource, + Class viewType) { InputStream modeInputStream = getJson(model, viewType); JsonReader outputReader = Json.createReader(modeInputStream); InputStream is = Utils.class.getResourceAsStream(expectedJsonResource); @@ -130,7 +138,8 @@ public static void testJSONExport(Object model, String expectedJsonResource) { /** * The given model is validated against adaptive form specification * - * @param model reference to the sling model + * @param model + * reference to the sling model */ public static void testSchemaValidation(@NotNull Object model) { // we check complete json in schema validation, to validate complete model json @@ -144,7 +153,8 @@ public static void testSchemaValidation(@NotNull Object model) { JsonSchema schema = schemaFactory.getSchema(schemaStream); // read data from the stream and store it into JsonNode JsonNode json = objectMapper.readTree(jsonStream); - // if there is a version bump of schema, then it needs to be validated against its corresponding sling model here + // if there is a version bump of schema, then it needs to be validated against its corresponding sling model + // here // by explicitly checking the model implementation if (!(model instanceof FormContainerImpl)) { InputStream formContainerTemplate = Utils.class.getResourceAsStream("/schema/0.15.2/form.json"); @@ -157,12 +167,48 @@ public static void testSchemaValidation(@NotNull Object model) { // show the validation errors if (!validationResult.isEmpty()) { // show all the validation error - fail(String.format("Error found during schema validation : %s", - Joiner.on(" ").join(validationResult))); + fail(String.format("Error found during schema validation : %s", Joiner.on(" ").join(validationResult))); } } catch (IOException ex) { - fail(String.format("Unable to validate form model definition : %s", - ex.getMessage())); + fail(String.format("Unable to validate form model definition : %s", ex.getMessage())); + } + } + + /** + * Loads a JCR authoring schema by its YAML classpath path. The schema and all its $ref dependencies are resolved + * via a shared temp-directory cache initialised on first call — no pre-flattened JSON copies are needed. + * + * @param yamlClasspathPath + * e.g. "/authoring-schema/components/textinput.authoring.schema.yaml" + * + * @return the loaded {@link JsonSchema} ready for validation + */ + public static JsonSchema loadAuthoringSchema(@NotNull String yamlClasspathPath) { + return SchemaCache.load(yamlClasspathPath); + } + + /** + * Validates the JCR ValueMap of a resource against the JCR authoring schema for a component. The schema is loaded + * from the shared {@link SchemaCache} which resolves all $ref chains at runtime — no pre-flattened JSON schema + * files are needed in source control. + * + * @param resource + * the Sling resource whose ValueMap to validate + * @param yamlClasspathPath + * classpath path to the component YAML authoring schema, e.g. + * "/authoring-schema/components/textinput.authoring.schema.yaml" + */ + public static void testJcrSchemaValidation(@NotNull Resource resource, @NotNull String yamlClasspathPath) { + try { + JsonSchema schema = SchemaCache.load(yamlClasspathPath); + JsonNode jcrNode = new ObjectMapper().valueToTree(resource.getValueMap()); + Set errors = schema.validate(jcrNode); + if (!errors.isEmpty()) { + fail(String.format("JCR authoring schema validation failed for %s: %s", resource.getPath(), + Joiner.on(" ").join(errors))); + } + } catch (Exception ex) { + fail("Unable to validate JCR node against authoring schema: " + ex.getMessage()); } } @@ -187,6 +233,7 @@ public static void testSchemaValidation(@NotNull Object model) { * the test base folder (under the {@code src/test/resources} folder) * @param testResourcePath * the test resource path in the virtual repository + * * @return the expected class path location of the JSON exporter file */ public static String getTestExporterJSONPath(String testBase, String testResourcePath) { @@ -196,9 +243,12 @@ public static String getTestExporterJSONPath(String testBase, String testResourc /** * Set internal state on a private field. * - * @param target target object to set the private field - * @param field name of the private field - * @param value value of the private field + * @param target + * target object to set the private field + * @param field + * name of the private field + * @param value + * value of the private field */ @SuppressWarnings("squid:S00112") public static void setInternalState(Object target, String field, Object value) { @@ -208,7 +258,8 @@ public static void setInternalState(Object target, String field, Object value) { f.setAccessible(true); f.set(target, value); } catch (IllegalAccessException | RuntimeException e) { - throw new RuntimeException("Unable to set internal state on a private field. Please report to mockito mailing list.", e); + throw new RuntimeException( + "Unable to set internal state on a private field. Please report to mockito mailing list.", e); } } @@ -219,10 +270,8 @@ private static Field getFieldFromHierarchy(Class clazz, String field) { f = getField(clazz, field); } if (f == null) { - throw new IllegalArgumentException( - "You want me to get this field: '" + field + - "' on this class: '" + clazz.getSimpleName() + - "' but this field is not declared withing hierarchy of this class!"); + throw new IllegalArgumentException("You want me to get this field: '" + field + "' on this class: '" + + clazz.getSimpleName() + "' but this field is not declared withing hierarchy of this class!"); } return f; } @@ -252,4 +301,57 @@ public static Method getPrivateMethod(Class clazz, String privateMethodName) { return null; } } + + /** + * Lazily initialises a shared temp-directory tree of JSON-converted authoring schemas. All *.yaml files under the + * /authoring-schema classpath directory are converted once per JVM and written to a mirrored temp directory so + * networknt can resolve relative $refs via file: URIs — no pre-flattened JSON copies needed in source control. + */ + private static final class SchemaCache { + + private static final String SCHEMA_ROOT = "/authoring-schema"; + + static final Path TEMP_DIR; + static final JsonSchemaFactory FACTORY = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); + + static { + try { + TEMP_DIR = Files.createTempDirectory("jcr-authoring-schema-"); + ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); + ObjectMapper jsonMapper = new ObjectMapper(); + URL rootUrl = SchemaCache.class.getResource(SCHEMA_ROOT); + if (rootUrl == null) { + throw new IllegalStateException( + "Authoring schema directory not found on classpath: " + SCHEMA_ROOT); + } + Path resourceRoot = Paths.get(rootUrl.toURI()); + try (Stream walk = Files.walk(resourceRoot)) { + walk.filter(p -> p.toString().endsWith(".yaml")).forEach(yamlPath -> { + try { + Path rel = resourceRoot.relativize(yamlPath); + Path out = TEMP_DIR.resolve(rel.toString()); + Files.createDirectories(out.getParent()); + try (InputStream in = Files.newInputStream(yamlPath)) { + ObjectNode node = (ObjectNode) yamlMapper.readTree(in); + node.remove("$id"); + jsonMapper.writerWithDefaultPrettyPrinter().writeValue(out.toFile(), node); + } + } catch (IOException e) { + throw new RuntimeException("Failed to convert schema: " + yamlPath, e); + } + }); + } + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + static JsonSchema load(String yamlClasspathPath) { + String rel = yamlClasspathPath.substring(SCHEMA_ROOT.length()); + if (rel.startsWith("/")) { + rel = rel.substring(1); + } + return FACTORY.getSchema(TEMP_DIR.resolve(rel).toUri()); + } + } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/BlankTitleTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/BlankTitleTest.java index ec10ac163c..a332bd7be8 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/BlankTitleTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/BlankTitleTest.java @@ -69,10 +69,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImplTest.java index 2132af9625..b5afef2490 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxGroupImplTest.java @@ -50,11 +50,14 @@ public class CheckBoxGroupImplTest { private static final String PATH_CHECKBOX_GROUP = CONTENT_ROOT + "/checkboxgroup"; private static final String PATH_CHECKBOX_GROUP_DATALAYER = CONTENT_ROOT + "/checkboxgroup-datalayer"; - private static final String PATH_CHECKBOX_GROUP_WITH_DUPLICATE_ENUMS = CONTENT_ROOT + "/checkboxgroup-duplicate-enum"; - private static final String PATH_CHECKBOX_GROUP_FOR_INSERTION_ORDER = CONTENT_ROOT + "/checkboxgroup-insertion-order"; + private static final String PATH_CHECKBOX_GROUP_WITH_DUPLICATE_ENUMS = CONTENT_ROOT + + "/checkboxgroup-duplicate-enum"; + private static final String PATH_CHECKBOX_GROUP_FOR_INSERTION_ORDER = CONTENT_ROOT + + "/checkboxgroup-insertion-order"; private static final String PATH_CHECKBOX_GROUP_FOR_BOOLEAN = CONTENT_ROOT + "/checkboxgroup-boolean"; private static final String PATH_CHECKBOX_GROUP_NO_FIELDTYPE = CONTENT_ROOT + "/checkboxgroup-without-fieldtype"; - private static final String PATH_CHECKBOX_GROUP_OPTION_SCREEN_READER_LABEL = CONTENT_ROOT + "/checkboxgroup-option-screenreader-label"; + private static final String PATH_CHECKBOX_GROUP_OPTION_SCREEN_READER_LABEL = CONTENT_ROOT + + "/checkboxgroup-option-screenreader-label"; private static final String PATH_CHECKBOX_GROUP_WITH_NULL_VALUES = CONTENT_ROOT + "/checkboxgroup-with-null-values"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -358,7 +361,8 @@ private CheckBoxGroup getCheckBoxGroupUnderTest(String resourcePath) { @Test void testDataLayerProperties() throws IllegalAccessException { - CheckBoxGroup checkBox = Utils.getComponentUnderTest(PATH_CHECKBOX_GROUP_DATALAYER, CheckBoxGroup.class, context); + CheckBoxGroup checkBox = Utils.getComponentUnderTest(PATH_CHECKBOX_GROUP_DATALAYER, CheckBoxGroup.class, + context); FieldUtils.writeField(checkBox, "dataLayerEnabled", true, true); FormComponentData dataObject = (FormComponentData) checkBox.getData(); assert (dataObject != null); @@ -371,7 +375,8 @@ void testDataLayerProperties() throws IllegalAccessException { @Test void testJSONExportDataLayer() throws Exception { - CheckBoxGroup checkBox = Utils.getComponentUnderTest(PATH_CHECKBOX_GROUP_DATALAYER, CheckBoxGroup.class, context); + CheckBoxGroup checkBox = Utils.getComponentUnderTest(PATH_CHECKBOX_GROUP_DATALAYER, CheckBoxGroup.class, + context); FieldUtils.writeField(checkBox, "dataLayerEnabled", true, true); Utils.testJSONExport(checkBox, Utils.getTestExporterJSONPath(BASE, PATH_CHECKBOX_GROUP_DATALAYER)); } @@ -379,8 +384,8 @@ void testJSONExportDataLayer() throws Exception { @Test void testInsertionOrderForEnums() { CheckBoxGroup checkboxGroup = getCheckBoxGroupUnderTest(PATH_CHECKBOX_GROUP_FOR_INSERTION_ORDER); - Set set = new LinkedHashSet<>(Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, - 15L, 16L, 17L, 18L, 19L, 20L)); + Set set = new LinkedHashSet<>(Arrays.asList(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, + 14L, 15L, 16L, 17L, 18L, 19L, 20L)); assertArrayEquals(set.toArray(new Object[0]), checkboxGroup.getEnums()); } @@ -394,8 +399,9 @@ void testForBooleanType() { @Test void testInsertionOrderForEnumNames() { CheckBoxGroup checkboxGroup = getCheckBoxGroupUnderTest(PATH_CHECKBOX_GROUP_FOR_INSERTION_ORDER); - Set set = new LinkedHashSet<>(Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", - "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty")); + Set set = new LinkedHashSet<>(Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five", "Six", + "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", + "Seventeen", "Eighteen", "Nineteen", "Twenty")); assertArrayEquals(set.toArray(new String[0]), checkboxGroup.getEnumNames()); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImplTest.java index a03844aee0..c70d0b0488 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/CheckBoxImplTest.java @@ -57,6 +57,8 @@ public class CheckBoxImplTest { private static final String PATH_CHECKBOX_NOENUM = CONTENT_ROOT + "/checkboxNoEnum"; private static final String PATH_CHECKBOX_ENABLEUNCHECKEDOFF = CONTENT_ROOT + "/checkbox-enableUncheckedValueFalse"; + private static final String PATH_CHECKBOX_ENABLEUNCHECKEDABSENT = CONTENT_ROOT + + "/checkbox-enableUncheckedValueAbsent"; private static final String PATH_CHECKBOX_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/checkbox-without-fieldtype"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -350,6 +352,28 @@ void shouldOnlyHaveOnEnumIfEnableUncheckedValueOff() { assertArrayEquals(new String[] { "on" }, checkbox.getEnums()); } + @Test + void shouldOnlyHaveCheckedValueEnumIfEnableUncheckedValueAbsent() { + CheckBox checkbox = getCheckBoxUnderTest(PATH_CHECKBOX_ENABLEUNCHECKEDABSENT); + // When enableUncheckedValue is absent (null), Boolean.TRUE.equals(null) is false, + // so only the checkedValue should be included in enums + assertArrayEquals(new String[] { "on" }, checkbox.getEnums()); + } + + @Test + void testIsReadOnlyAbsent() { + // PATH_CHECKBOX has no readOnly property; isReadOnly() should default to false + CheckBox checkbox = getCheckBoxUnderTest(PATH_CHECKBOX); + assertEquals(false, checkbox.isReadOnly()); + } + + @Test + void testIsRequiredAbsent() { + // PATH_CHECKBOX has no required property; isRequired() should default to false + CheckBox checkbox = getCheckBoxUnderTest(PATH_CHECKBOX); + assertEquals(false, checkbox.isRequired()); + } + private CheckBox getCheckBoxUnderTest(String resourcePath) { context.currentResource(resourcePath); MockSlingHttpServletRequest request = context.request(); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImplTest.java index ef4d39c7d2..a2402e2a84 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DatePickerImplTest.java @@ -46,12 +46,15 @@ public class DatePickerImplTest { private static final String PATH_DATEPICKER = CONTENT_ROOT + "/datepicker"; private static final String PATH_DATEPICKER_DATALAYER = CONTENT_ROOT + "/datepicker-datalayer"; - private static final String PATH_DATEPICKER_DISPLAY_VALUE_EXPRESSION = CONTENT_ROOT + "/datepicker-displayValueExpression"; + private static final String PATH_DATEPICKER_DISPLAY_VALUE_EXPRESSION = CONTENT_ROOT + + "/datepicker-displayValueExpression"; private static final String PATH_DATEPICKER_BACKWARD_COMPATIBLE = CONTENT_ROOT + "/datepicker-backwardcompatible"; private static final String PATH_DATEPICKER_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/datepicker-without-fieldtype"; private static final String PATH_DATEPICKER_WITH_DISPLAY_FORMAT = CONTENT_ROOT + "/datepicker-with-display-format"; - private static final String PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT = CONTENT_ROOT + "/datepicker-with-custom-display-format"; - private static final String PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS = CONTENT_ROOT + "/datepicker-with-both-display-formats"; + private static final String PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT = CONTENT_ROOT + + "/datepicker-with-custom-display-format"; + private static final String PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS = CONTENT_ROOT + + "/datepicker-with-both-display-formats"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -214,13 +217,15 @@ void testGetDisplayFormat() { @Test void testGetDisplayFormatWithCustomDisplayFormat() { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT, DatePicker.class, context); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT, + DatePicker.class, context); assertEquals("DD/MM/YYYY", datePicker.getDisplayFormat()); } @Test void testGetDisplayFormatWithBothFormats() { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS, DatePicker.class, context); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS, DatePicker.class, + context); // customDisplayFormat should take priority over displayFormat assertEquals("DD/MM/YYYY", datePicker.getDisplayFormat()); } @@ -261,7 +266,8 @@ void testJSONExport() throws Exception { @Test void testJSONExportBackwardCompatibility() throws Exception { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_BACKWARD_COMPATIBLE, DatePicker.class, context); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_BACKWARD_COMPATIBLE, DatePicker.class, + context); Utils.testJSONExport(datePicker, Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_BACKWARD_COMPATIBLE)); } @@ -320,26 +326,32 @@ void testJSONExportDataLayer() throws Exception { @Test void testJSONExportForDisplayValueExpression() throws Exception { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_DISPLAY_VALUE_EXPRESSION, DatePicker.class, context); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_DISPLAY_VALUE_EXPRESSION, DatePicker.class, + context); Utils.testJSONExport(datePicker, Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_DISPLAY_VALUE_EXPRESSION)); } @Test void testNoFieldType() throws Exception { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITHOUT_FIELDTYPE, DatePicker.class, context); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITHOUT_FIELDTYPE, DatePicker.class, + context); Utils.testJSONExport(datePicker, Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_WITHOUT_FIELDTYPE)); } @Test void testJSONExportWithCustomDisplayFormat() throws Exception { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT, DatePicker.class, context); - Utils.testJSONExport(datePicker, Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT)); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT, + DatePicker.class, context); + Utils.testJSONExport(datePicker, + Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_WITH_CUSTOM_DISPLAY_FORMAT)); } @Test void testJSONExportWithBothDisplayFormats() throws Exception { - DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS, DatePicker.class, context); - Utils.testJSONExport(datePicker, Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS)); + DatePicker datePicker = Utils.getComponentUnderTest(PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS, DatePicker.class, + context); + Utils.testJSONExport(datePicker, + Utils.getTestExporterJSONPath(BASE, PATH_DATEPICKER_WITH_BOTH_DISPLAY_FORMATS)); } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DropDownImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DropDownImplTest.java index 726e1980e8..e7120d82aa 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DropDownImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/DropDownImplTest.java @@ -54,7 +54,8 @@ public class DropDownImplTest { private static final String CONTENT_ROOT = "/content"; private static final String PATH_DROPDOWN_1 = CONTENT_ROOT + "/dropdown-1"; private static final String PATH_MULTISELECT_DROPDOWN = CONTENT_ROOT + "/multiselect-dropdown"; - private static final String PATH_MULTISELECT_DROPDOWN_WITH_VARIANT_PROPERTY = CONTENT_ROOT + "/multiselect-dropdown-2"; + private static final String PATH_MULTISELECT_DROPDOWN_WITH_VARIANT_PROPERTY = CONTENT_ROOT + + "/multiselect-dropdown-2"; private static final String PATH_DROPDOWN2 = CONTENT_ROOT + "/dropdown2"; private static final String PATH_DROPDOWN = CONTENT_ROOT + "/dropdown"; @@ -357,7 +358,8 @@ void testGetMultiSelectDefault() { @Test void testGetMultiSelectDefault_WithDiffProperty() { - DropDown dropdown = Utils.getComponentUnderTest(PATH_MULTISELECT_DROPDOWN_WITH_VARIANT_PROPERTY, DropDown.class, context); + DropDown dropdown = Utils.getComponentUnderTest(PATH_MULTISELECT_DROPDOWN_WITH_VARIANT_PROPERTY, DropDown.class, + context); assertArrayEquals(new Long[] { 0L, 1L }, dropdown.getDefault()); } @@ -438,24 +440,25 @@ void testJSONExportDataLayer() throws Exception { @Test void testInsertionOrderForEnums() { DropDown dropdown = Utils.getComponentUnderTest(PATH_DROPDOWN_FOR_INSERTION_ORDER, DropDown.class, context); - Set set = new LinkedHashSet<>(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", - "15", "16", "17", "18", "19", "20")); + Set set = new LinkedHashSet<>(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20")); assertArrayEquals(set.toArray(new String[0]), dropdown.getEnums()); } @Test void testInsertionOrderForEnumNames() { DropDown dropdown = Utils.getComponentUnderTest(PATH_DROPDOWN_FOR_INSERTION_ORDER, DropDown.class, context); - Set set = new LinkedHashSet<>(Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", - "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty")); + Set set = new LinkedHashSet<>(Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five", "Six", + "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", + "Seventeen", "Eighteen", "Nineteen", "Twenty")); assertArrayEquals(set.toArray(new String[0]), dropdown.getEnumNames()); } @Test void testEnumsWithoutEnumNames() { DropDown dropdown = Utils.getComponentUnderTest(PATH_DROPDOWN_FOR_NO_ENUM_NAMES, DropDown.class, context); - Set set = new LinkedHashSet<>(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", - "15", "16", "17", "18", "19", "20")); + Set set = new LinkedHashSet<>(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20")); assertArrayEquals(set.toArray(new String[0]), dropdown.getEnums()); assertNull(dropdown.getEnumNames()); } @@ -463,7 +466,8 @@ void testEnumsWithoutEnumNames() { @Test void testEnumsWithLesserEnumNames() { DropDown dropdown1 = Utils.getComponentUnderTest(PATH_DROPDOWN_FOR_LESSER_ENUM_NAMES, DropDown.class, context); - Set set1 = new LinkedHashSet<>(Arrays.asList("zero", "one", "two", "three", "4", "5", "6", "7", "8", "9")); + Set set1 = new LinkedHashSet<>( + Arrays.asList("zero", "one", "two", "three", "4", "5", "6", "7", "8", "9")); assertArrayEquals(set1.toArray(new String[0]), dropdown1.getEnumNames()); } @@ -531,4 +535,11 @@ void testGetTypeWithExistingArrayType() throws IllegalAccessException { FieldUtils.writeField(dropdown, "multiSelect", false, true); assertEquals(Type.STRING, dropdown.getType()); } + + @Test + void testJcrAuthoringSchemaCompliance() { + context.currentResource(PATH_DROPDOWN_1); + Resource resource = context.currentResource(); + Utils.testJcrSchemaValidation(resource, "/authoring-schema/components/dropdown.authoring.schema.yaml"); + } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImplTest.java index e25bb6a7b2..1248ecd6f2 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FileInputImplTest.java @@ -58,7 +58,8 @@ public class FileInputImplTest { private static final String PATH_FILEINPUT = CONTENT_ROOT + "/fileinput"; private static final String PATH_FILEINPUT_DATALAYER = CONTENT_ROOT + "/fileinput-datalayer"; private static final String PATH_MULTISELECT_FILEINPUT = CONTENT_ROOT + "/multiselect-fileinput"; - private static final String PATH_MULTISELECT_FILEINPUT_WITHNOTYPE = CONTENT_ROOT + "/multiselect-fileinput-withNoType"; + private static final String PATH_MULTISELECT_FILEINPUT_WITHNOTYPE = CONTENT_ROOT + + "/multiselect-fileinput-withNoType"; private static final String PATH_MULTISELECT_FILEINPUT_WITH_TYPE = CONTENT_ROOT + "/fileInput-withType"; private static final String PATH_FILEINPUT_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/fileinput-without-fieldtype"; @@ -86,13 +87,15 @@ void testFieldType() { @Test void testType() { - FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITHNOTYPE, FileInput.class, context); + FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITHNOTYPE, FileInput.class, + context); assertEquals(BaseConstraint.Type.FILE_ARRAY, fileInput.getType()); } @Test void testStringType() { - FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITH_TYPE, FileInput.class, context); + FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITH_TYPE, FileInput.class, + context); assertEquals(BaseConstraint.Type.STRING_ARRAY, fileInput.getType()); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormConfigurationProviderImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormConfigurationProviderImplTest.java index 6844f56561..21356b23dc 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormConfigurationProviderImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormConfigurationProviderImplTest.java @@ -56,7 +56,8 @@ public class FormConfigurationProviderImplTest { private final AemContext context = FormsCoreComponentTestContext.newAemContext(); - private ConfigurationResourceResolver configurationResourceResolverMock = Mockito.mock(ConfigurationResourceResolver.class); + private ConfigurationResourceResolver configurationResourceResolverMock = Mockito + .mock(ConfigurationResourceResolver.class); @BeforeEach void setUp() { @@ -80,10 +81,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -93,10 +92,11 @@ void testGetCustomFunctionModuleUrl() { context.load().json(BASE + TEST_CONTENT_CONF_JSON, CONF_PATH); String path = "/content/formcontainerv2"; FormConfigurationProvider formConfigurationProvider = getFormConfigProviderUnderTest(path); - Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, - CUSTOM_FUNCTION_CONFIG_NAME)).thenReturn(context.resourceResolver().resolve(CONF_PATH)); - assertEquals("https://main--test-repo--testOwner.hlx.live/blocks/form/functions.js", formConfigurationProvider - .getCustomFunctionModuleUrl()); + Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), + CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, CUSTOM_FUNCTION_CONFIG_NAME)) + .thenReturn(context.resourceResolver().resolve(CONF_PATH)); + assertEquals("https://main--test-repo--testOwner.hlx.live/blocks/form/functions.js", + formConfigurationProvider.getCustomFunctionModuleUrl()); } @Test @@ -104,30 +104,29 @@ void testGetCustomFunctionModuleUrlWithNoConf() { context.load().json(BASE + TEST_CONTENT_CONF_JSON, CONF_PATH); String path = "/content/formcontainerv2"; FormConfigurationProvider formConfigurationProvider = getFormConfigProviderUnderTest(path); - Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, - CUSTOM_FUNCTION_CONFIG_NAME)).thenReturn(null); - assertEquals("", formConfigurationProvider - .getCustomFunctionModuleUrl()); + Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), + CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, CUSTOM_FUNCTION_CONFIG_NAME)).thenReturn(null); + assertEquals("", formConfigurationProvider.getCustomFunctionModuleUrl()); } @Test void testGetCustomFunctionModuleUrlWithNoOwner() { context.load().json(BASE + TEST_BLANK_OWNER_CONF_JSON, CONF_PATH); FormConfigurationProvider formConfigurationProvider = getFormConfigProviderUnderTest(CONF_PATH); - Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, - CUSTOM_FUNCTION_CONFIG_NAME)).thenReturn(context.resourceResolver().resolve(CONF_PATH)); - assertEquals("", formConfigurationProvider - .getCustomFunctionModuleUrl()); + Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), + CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, CUSTOM_FUNCTION_CONFIG_NAME)) + .thenReturn(context.resourceResolver().resolve(CONF_PATH)); + assertEquals("", formConfigurationProvider.getCustomFunctionModuleUrl()); } @Test void testGetCustomFunctionModuleUrlWithNoRepo() { context.load().json(BASE + TEST_BLANK_REPO_CONF_JSON, CONF_PATH); FormConfigurationProvider formConfigurationProvider = getFormConfigProviderUnderTest(CONF_PATH); - Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, - CUSTOM_FUNCTION_CONFIG_NAME)).thenReturn(context.resourceResolver().resolve(CONF_PATH)); - assertEquals("", formConfigurationProvider - .getCustomFunctionModuleUrl()); + Mockito.when(configurationResourceResolverMock.getResource(context.currentResource(), + CUSTOM_FUNCTION_CONFIG_BUCKET_NAME, CUSTOM_FUNCTION_CONFIG_NAME)) + .thenReturn(context.resourceResolver().resolve(CONF_PATH)); + assertEquals("", formConfigurationProvider.getCustomFunctionModuleUrl()); } private FormConfigurationProvider getFormConfigProviderUnderTest(String resourcePath) { diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImplTest.java index ca4c0b8795..9906e0d41b 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormContainerImplTest.java @@ -89,10 +89,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -177,10 +175,8 @@ private FormContainer getFormContainerUnderTest(String resourcePath) throws Exce private void createAsset(Asset asset, String path) throws Exception { InputStream jsonStream = getClass().getResourceAsStream(BASE + path); - context.create().resource(asset.getOriginal().getPath() + "/" + JCR_CONTENT, ImmutableMap.of( - JCR_PRIMARYTYPE, NT_RESOURCE, - JCR_DATA, jsonStream, - JCR_MIMETYPE, ContentType.APPLICATION_JSON.toString())); + context.create().resource(asset.getOriginal().getPath() + "/" + JCR_CONTENT, ImmutableMap.of(JCR_PRIMARYTYPE, + NT_RESOURCE, JCR_DATA, jsonStream, JCR_MIMETYPE, ContentType.APPLICATION_JSON.toString())); } @Test diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormStructureParserImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormStructureParserImplTest.java index cb3d935436..776d4994d3 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormStructureParserImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FormStructureParserImplTest.java @@ -74,10 +74,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -108,10 +106,12 @@ void testFormDefinitionWithHTMLEncoding() throws JsonProcessingException { HashMap formJson = (HashMap) new ObjectMapper().readValue(formDef, new TypeReference>() {}); Assertions.assertNotNull(formStructureParser.getFormDefinition()); - Map datepicker = (Map) ((Map) formJson.get(":items")).get("datepicker"); + Map datepicker = (Map) ((Map) formJson.get(":items")) + .get("datepicker"); Assertions.assertEquals(datepicker.get("description"), "

dummy

"); Assertions.assertEquals(datepicker.get("tooltip"), "

test-short-description

"); - Map textinput = (Map) ((Map) formJson.get(":items")).get("textinput"); + Map textinput = (Map) ((Map) formJson.get(":items")) + .get("textinput"); Assertions.assertEquals(textinput.get("description"), "<ul> <li style="font-weight: bold;"><strong>abc</strong></li> <li style="font-weight: bold;"><strong>def</strong></li> <li style="font-weight: bold;"><strong>xyz</strong></li> </ul>"); Assertions.assertEquals(textinput.get("pattern"), @@ -124,7 +124,8 @@ void testFormDefinitionWithHTMLEncoding() throws JsonProcessingException { @Test void testFormContainerPathEmbedWithoutIframe() { - FormStructureParser formStructureParser = getFormStructureParserUnderTest(JCR_CONTENT_PATH, FORM_CONTAINER_PATH); + FormStructureParser formStructureParser = getFormStructureParserUnderTest(JCR_CONTENT_PATH, + FORM_CONTAINER_PATH); assertEquals(FORM_CONTAINER_PATH, formStructureParser.getFormContainerPath()); } @@ -185,12 +186,14 @@ public void containsFormContainer_should_return_false() { void testGetThemeEditorThemeRef() { Resource formContainer = context.resourceResolver().getResource(FORM_CONTAINER_PATH); ModifiableValueMap formContainerProps = formContainer.adaptTo(ModifiableValueMap.class); - formContainerProps.put(FormContainer.PN_CLIENT_LIB_REF, "/content/dam/formsanddocuments-themes/test-theme/jcr:content"); + formContainerProps.put(FormContainer.PN_CLIENT_LIB_REF, + "/content/dam/formsanddocuments-themes/test-theme/jcr:content"); String path = CONTENT_ROOT + "/myTestPage"; context.currentResource(path); MockSlingHttpServletRequest request = context.request(); - request.setAttribute(ThemeConstants.THEME_OVERRIDE, "/content/dam/formsanddocuments-themes/test-theme/jcr:content"); + request.setAttribute(ThemeConstants.THEME_OVERRIDE, + "/content/dam/formsanddocuments-themes/test-theme/jcr:content"); FormStructureParser formStructureParser = request.adaptTo(FormStructureParser.class); String themeClientLibRef = formStructureParser.getThemeEditorThemeRef(); assertEquals("fdtheme.test-theme", themeClientLibRef); @@ -201,7 +204,8 @@ void testGetThemeEditorThemeRefWithRequestAttribute() { String path = CONTENT_ROOT + "/myTestPage"; context.currentResource(path); MockSlingHttpServletRequest request = context.request(); - request.setAttribute(ThemeConstants.THEME_OVERRIDE, "/content/dam/formsanddocuments-themes/test-theme/jcr:content"); + request.setAttribute(ThemeConstants.THEME_OVERRIDE, + "/content/dam/formsanddocuments-themes/test-theme/jcr:content"); FormStructureParser formStructureParser = request.adaptTo(FormStructureParser.class); String themeClientLibRef = formStructureParser.getThemeEditorThemeRef(); assertEquals("fdtheme.test-theme", themeClientLibRef); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImplTest.java index f174a77545..c92077ee3a 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/FragmentImplTest.java @@ -68,7 +68,8 @@ public class FragmentImplTest { private static final String PATH_FRAGMENT_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/fragment-without-fieldtype"; private static final String PATH_FRAGMENT_WITH_FRAGMENT_PATH = CONTENT_ROOT + "/fragment-with-fragment-path"; private static final String PATH_FRAGMENT_WITH_INVALID_PATH = CONTENT_ROOT + "/fragment-with-invalid-path"; - private static final String PATH_FRAGMENT_WITH_PLACEHOLDER_RULES = CONTENT_ROOT + "/fragment-with-placeholder-rules"; + private static final String PATH_FRAGMENT_WITH_PLACEHOLDER_RULES = CONTENT_ROOT + + "/fragment-with-placeholder-rules"; private static final String PATH_FRAGMENT_LAZY = CONTENT_ROOT + "/fragment-lazy"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -92,10 +93,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -165,7 +164,8 @@ void testFragmentContainerEventsIncludedInGetEvents() { assertTrue("Stitched fragment should include events from referenced fragment container", events.containsKey("change")); Assertions.assertArrayEquals(new String[] { "fragmentChangeHandler" }, events.get("change")); - assertTrue("Stitched fragment should include default custom:setProperty", events.containsKey("custom:setProperty")); + assertTrue("Stitched fragment should include default custom:setProperty", + events.containsKey("custom:setProperty")); } @Test @@ -175,7 +175,8 @@ void testFragmentContainerRulesParallelToEvents() { Map events = fragment.getEvents(); assertNotNull(rules); assertNotNull(events); - assertTrue("Stitched fragment should include root-level rules from referenced fragment container (parallel to events)", + assertTrue( + "Stitched fragment should include root-level rules from referenced fragment container (parallel to events)", rules.containsKey("visible")); assertEquals("fragmentVisibleRule", rules.get("visible")); assertTrue("Rules and events should both be present at same level", events.containsKey("change")); @@ -194,7 +195,8 @@ void testPlaceholderAndFragmentContainerRulesEventsMerged() { assertTrue("Merged rules should include placeholder rule (required)", rules.containsKey("required")); assertEquals("placeholderRequired", rules.get("required")); - assertTrue("Merged rules should include visible; panel has priority over fragment container", rules.containsKey("visible")); + assertTrue("Merged rules should include visible; panel has priority over fragment container", + rules.containsKey("visible")); assertEquals("panelVisibleRule", rules.get("visible")); assertTrue("Merged events should include placeholder event (click)", events.containsKey("click")); @@ -202,8 +204,8 @@ void testPlaceholderAndFragmentContainerRulesEventsMerged() { assertTrue("Merged events should include fragment container event (change)", events.containsKey("change")); Assertions.assertArrayEquals(new String[] { "fragmentChangeHandler" }, events.get("change")); assertTrue("Merged events should include default custom:setProperty", events.containsKey("custom:setProperty")); - assertTrue("Merged events should include initialize with panel handler first, then fragment appended", events.containsKey( - "initialize")); + assertTrue("Merged events should include initialize with panel handler first, then fragment appended", + events.containsKey("initialize")); Assertions.assertArrayEquals(new String[] { "panelInit", "fragInit" }, events.get("initialize")); assertTrue("fd:rules is whitelisted and should not appear in properties", !properties.containsKey("fd:rules")); @@ -215,7 +217,8 @@ void testNoMergeWhenToggleDisabled() throws Exception { String saved = System.getProperty(key); try { System.setProperty(key, "false"); - Fragment fragment = Utils.getComponentUnderTest(PATH_FRAGMENT_WITH_PLACEHOLDER_RULES, Fragment.class, context); + Fragment fragment = Utils.getComponentUnderTest(PATH_FRAGMENT_WITH_PLACEHOLDER_RULES, Fragment.class, + context); Map rules = fragment.getRules(); Map events = fragment.getEvents(); @@ -251,7 +254,8 @@ void testJSONExportWithDamPath() throws Exception { @Test void testJSONExportWithFragmentPath() throws Exception { Fragment fragment = getFragmentWithMergeEnabled(PATH_FRAGMENT_WITH_FRAGMENT_PATH); - Utils.testJSONExport(fragment, Utils.getTestExporterJSONPath(BASE, PATH_FRAGMENT_WITH_FRAGMENT_PATH), Views.Author.class); + Utils.testJSONExport(fragment, Utils.getTestExporterJSONPath(BASE, PATH_FRAGMENT_WITH_FRAGMENT_PATH), + Views.Author.class); } @Test @@ -272,8 +276,7 @@ void testGetChildrenModelsForNullRequest() { Resource resource = context.resourceResolver().getResource(PATH_FRAGMENT); Fragment fragment = resource.adaptTo(Fragment.class); Assertions.assertNotNull(fragment); - Map childrenModels = ((FragmentImpl) fragment).getChildrenModels(null, - TextInput.class); + Map childrenModels = ((FragmentImpl) fragment).getChildrenModels(null, TextInput.class); Assertions.assertEquals(1, childrenModels.size()); Assertions.assertNotNull(childrenModels.get("textinput")); TextInput textInput = childrenModels.get("textinput"); @@ -321,7 +324,8 @@ void testGetFragmentContainerI18n() throws Exception { FragmentImpl fragmentImpl = (FragmentImpl) fragment; // Use reflection to access the private method - Method getFragmentContainerI18nMethod = FragmentImpl.class.getDeclaredMethod("getFragmentContainerI18n", String.class); + Method getFragmentContainerI18nMethod = FragmentImpl.class.getDeclaredMethod("getFragmentContainerI18n", + String.class); getFragmentContainerI18nMethod.setAccessible(true); // Create mocks for the dependencies @@ -350,18 +354,21 @@ void testGetFragmentContainerI18n() throws Exception { // Test case 1: When localeLang is null - should return I18n with null resource bundle I18n result1 = (I18n) getFragmentContainerI18nMethod.invoke(fragmentImpl, (String) null); - Assertions.assertNotNull(result1, "getFragmentContainerI18n should return a non-null I18n object even when localeLang is null"); + Assertions.assertNotNull(result1, + "getFragmentContainerI18n should return a non-null I18n object even when localeLang is null"); - // Test case 2: When localeLang is set and resourceBundleProvider is available - should return I18n with resource bundle + // Test case 2: When localeLang is set and resourceBundleProvider is available - should return I18n with + // resource bundle I18n result2 = (I18n) getFragmentContainerI18nMethod.invoke(fragmentImpl, "en"); - Assertions.assertNotNull(result2, "getFragmentContainerI18n should return a non-null I18n object when localeLang is set"); + Assertions.assertNotNull(result2, + "getFragmentContainerI18n should return a non-null I18n object when localeLang is set"); // Verify that the method called the expected dependencies Mockito.verify(mockFragmentContainer, Mockito.atLeastOnce()).getResourceResolver(); Mockito.verify(mockFragmentContainer, Mockito.atLeastOnce()).getPath(); Mockito.verify(mockResourceResolver, Mockito.atLeastOnce()).getResource(Mockito.anyString()); - Mockito.verify(mockResourceBundleProvider, Mockito.atLeastOnce()) - .getResourceBundle(Mockito.anyString(), Mockito.any(Locale.class)); + Mockito.verify(mockResourceBundleProvider, Mockito.atLeastOnce()).getResourceBundle(Mockito.anyString(), + Mockito.any(Locale.class)); // Test case 3: When resourceBundleProvider is null - should still return I18n object resourceBundleProviderField.set(fragmentImpl, null); @@ -393,24 +400,28 @@ void testNullFragmentContainerHandling() throws Exception { // Test that getChildrenModels returns empty map instead of throwing NPE Map childrenModels = fragmentImpl.getChildrenModels(context.request(), ComponentExporter.class); - Assertions.assertNotNull(childrenModels, "getChildrenModels should return non-null map even with null fragmentContainer"); + Assertions.assertNotNull(childrenModels, + "getChildrenModels should return non-null map even with null fragmentContainer"); Assertions.assertTrue(childrenModels.isEmpty(), "getChildrenModels should return empty map when fragmentContainer is null"); // Test that getExportedItems doesn't throw NPE Map exportedItems = fragmentImpl.getExportedItems(); - Assertions.assertNotNull(exportedItems, "getExportedItems should return non-null map even with null fragmentContainer"); + Assertions.assertNotNull(exportedItems, + "getExportedItems should return non-null map even with null fragmentContainer"); Assertions.assertTrue(exportedItems.isEmpty(), "getExportedItems should return empty map when fragmentContainer is null"); // Test that getExportedItemsOrder doesn't throw NPE String[] exportedItemsOrder = fragmentImpl.getExportedItemsOrder(); - Assertions.assertNotNull(exportedItemsOrder, "getExportedItemsOrder should return non-null array even with null fragmentContainer"); + Assertions.assertNotNull(exportedItemsOrder, + "getExportedItemsOrder should return non-null array even with null fragmentContainer"); Assertions.assertEquals(0, exportedItemsOrder.length, "getExportedItemsOrder should return empty array when fragmentContainer is null"); // Test getFragmentContainerI18n with null fragmentContainer - Method getFragmentContainerI18nMethod = FragmentImpl.class.getDeclaredMethod("getFragmentContainerI18n", String.class); + Method getFragmentContainerI18nMethod = FragmentImpl.class.getDeclaredMethod("getFragmentContainerI18n", + String.class); getFragmentContainerI18nMethod.setAccessible(true); // Should not throw NPE and should return non-null I18n object @@ -443,8 +454,7 @@ void testNullFragmentContainerWithNullRequest() throws Exception { @Test void testLazyFragmentDoesNotResolveContainer() { Fragment fragment = Utils.getComponentUnderTest(PATH_FRAGMENT_LAZY, Fragment.class, context); - Assertions.assertNull(fragment.getFragmentContainer(), - "Fragment container should be null when lazy is true"); + Assertions.assertNull(fragment.getFragmentContainer(), "Fragment container should be null when lazy is true"); } @Test @@ -461,15 +471,13 @@ void testLazyFragmentExportedItemsEmpty() { Fragment fragment = Utils.getComponentUnderTest(PATH_FRAGMENT_LAZY, Fragment.class, context); Map items = fragment.getExportedItems(); Assertions.assertNotNull(items); - Assertions.assertTrue(items.isEmpty(), - "Lazy fragment should export no items since container is not resolved"); + Assertions.assertTrue(items.isEmpty(), "Lazy fragment should export no items since container is not resolved"); } @Test void testLazyFragmentHasLazyProperty() { FragmentImpl fragment = (FragmentImpl) Utils.getComponentUnderTest(PATH_FRAGMENT_LAZY, Fragment.class, context); - Assertions.assertTrue(fragment.getLazy(), - "getLazy() should return true when lazy is set"); + Assertions.assertTrue(fragment.getLazy(), "getLazy() should return true when lazy is set"); Map properties = fragment.getProperties(); Assertions.assertFalse(properties.containsKey("fd:loadLazily"), "fd:loadLazily should not be in properties map"); @@ -495,10 +503,8 @@ void testLazyFragmentJSONExport() throws Exception { @Test void testNonLazyFragmentDoesNotHaveLazyProperty() { FragmentImpl fragment = (FragmentImpl) Utils.getComponentUnderTest(PATH_FRAGMENT, Fragment.class, context); - Assertions.assertFalse(fragment.getLazy(), - "Non-lazy fragment should return false for getLazy()"); - Assertions.assertNotNull(fragment.getFragmentContainer(), - "Non-lazy fragment should have resolved container"); + Assertions.assertFalse(fragment.getLazy(), "Non-lazy fragment should return false for getLazy()"); + Assertions.assertNotNull(fragment.getFragmentContainer(), "Non-lazy fragment should have resolved container"); Assertions.assertEquals("/content/affragment", fragment.getFragmentPath(), "fragmentPath should always be accessible via getter"); } @@ -521,11 +527,9 @@ void testFragmentExportedItemsEmptyWhenToggleEnabled() { Fragment fragment = Utils.getComponentUnderTest(PATH_FRAGMENT, Fragment.class, context); Map exportedItems = fragment.getExportedItems(); Assertions.assertNotNull(exportedItems); - Assertions.assertTrue(exportedItems.isEmpty(), - "getExportedItems should return empty map when toggle is ON"); + Assertions.assertTrue(exportedItems.isEmpty(), "getExportedItems should return empty map when toggle is ON"); String[] order = fragment.getExportedItemsOrder(); - Assertions.assertEquals(0, order.length, - "getExportedItemsOrder should return empty array when toggle is ON"); + Assertions.assertEquals(0, order.length, "getExportedItemsOrder should return empty array when toggle is ON"); } @Test diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HtlUtilTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HtlUtilTest.java index 1bce5efac9..096c8b71cb 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HtlUtilTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/HtlUtilTest.java @@ -66,10 +66,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/JcrAuthoringSchemaValidationTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/JcrAuthoringSchemaValidationTest.java new file mode 100644 index 0000000000..56adde31cc --- /dev/null +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/JcrAuthoringSchemaValidationTest.java @@ -0,0 +1,154 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Copyright 2026 Adobe + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +package com.adobe.cq.forms.core.components.internal.models.v1.form; + +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import com.adobe.cq.forms.core.Utils; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.networknt.schema.JsonSchema; +import com.networknt.schema.ValidationMessage; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Validates that well-formed JCR property maps (as JSON) conform to the YAML authoring schemas. + * + * The schemas live in docs/authoring-schema/ and are mirrored into src/test/resources/authoring-schema/ so they are + * accessible on the classpath. + * + * Strategy: during test setup we convert each YAML schema to JSON and write it to a temp directory on disk. We then + * load schemas via file: URIs so networknt can resolve relative $refs (../field.authoring.schema.yaml) naturally using + * standard URI resolution — no custom fetchers or URI factories are required. + * + * This is the JCR analog to the af2-docs runtime schema validation: instead of validating the exported JSON model, we + * validate the JCR ValueMap (what you author in the dialog and what Sling reads via @ValueMapValue) against the schema + * that documents those properties. + */ +public class JcrAuthoringSchemaValidationTest { + + private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); + + private JsonSchema loadSchema(String classpathPath) { + return Utils.loadAuthoringSchema(classpathPath); + } + + // ----------------------------------------------------------------------- + // TextInput + // ----------------------------------------------------------------------- + + @Test + void minimalTextInputNodeConformsToAuthoringSchema() throws Exception { + JsonSchema schema = loadSchema("/authoring-schema/components/textinput.authoring.schema.yaml"); + + // Minimal valid textinput JCR node (matches the "textinput" fixture in test-content.json) + String fixtureJson = "{\"name\": \"abc\", \"fieldType\": \"text-input\"}"; + JsonNode fixture = JSON_MAPPER.readTree(fixtureJson); + + Set errors = schema.validate(fixture); + assertTrue(errors.isEmpty(), + "Minimal textinput JCR node should conform to authoring schema but got: " + errors); + } + + @Test + void fullTextInputNodeConformsToAuthoringSchema() throws Exception { + JsonSchema schema = loadSchema("/authoring-schema/components/textinput.authoring.schema.yaml"); + + // Full customized textinput — mirrors "textinput-customized" from test-content.json + String fixtureJson = "{" + "\"name\": \"abc\"," + "\"jcr:title\": \"def\"," + "\"hideTitle\": false," + + "\"dorExclusion\": true," + "\"dorColspan\": \"4\"," + "\"description\": \"dummy\"," + + "\"visible\": false," + "\"readOnly\": false," + "\"enabled\": true," + "\"required\": true," + + "\"assistPriority\": \"custom\"," + "\"dataRef\": \"a.b\"," + + "\"custom\": \"Custom screen reader text\"," + "\"tooltip\": \"test-short-description\"," + + "\"fieldType\": \"text-input\"" + "}"; + JsonNode fixture = JSON_MAPPER.readTree(fixtureJson); + + Set errors = schema.validate(fixture); + assertTrue(errors.isEmpty(), "Full textinput JCR node should conform to authoring schema but got: " + errors); + } + + // ----------------------------------------------------------------------- + // Dropdown + // ----------------------------------------------------------------------- + + @Test + void minimalDropdownNodeConformsToAuthoringSchema() throws Exception { + JsonSchema schema = loadSchema("/authoring-schema/components/dropdown.authoring.schema.yaml"); + + // Mirrors the "dropdown" fixture from dropdown/test-content.json + String fixtureJson = "{" + "\"name\": \"abc\"," + "\"jcr:title\": \"def\"," + "\"fieldType\": \"drop-down\"," + + "\"enum\": [0, 1, 2]," + "\"enumNames\": [\"m\", \"f\", \"o\"]" + "}"; + JsonNode fixture = JSON_MAPPER.readTree(fixtureJson); + + Set errors = schema.validate(fixture); + assertTrue(errors.isEmpty(), "Minimal dropdown JCR node should conform to authoring schema but got: " + errors); + } + + @Test + void multiselectDropdownNodeConformsToAuthoringSchema() throws Exception { + JsonSchema schema = loadSchema("/authoring-schema/components/dropdown.authoring.schema.yaml"); + + // Mirrors the "multiselect-dropdown" fixture from dropdown/test-content.json + String fixtureJson = "{" + "\"name\": \"abc\"," + "\"jcr:title\": \"def\"," + "\"hideTitle\": true," + + "\"description\": \"dummy\"," + "\"visible\": false," + "\"fieldType\": \"drop-down\"," + + "\"type\": \"number[]\"," + "\"multiSelect\": true," + "\"enum\": [0, 1, 2]," + + "\"enumNames\": [\"m\", \"f\", \"o\"]" + "}"; + JsonNode fixture = JSON_MAPPER.readTree(fixtureJson); + + Set errors = schema.validate(fixture); + assertTrue(errors.isEmpty(), + "Multiselect dropdown JCR node should conform to authoring schema but got: " + errors); + } + + // ----------------------------------------------------------------------- + // PanelContainer + // ----------------------------------------------------------------------- + + @Test + void minimalPanelContainerNodeConformsToAuthoringSchema() throws Exception { + JsonSchema schema = loadSchema("/authoring-schema/components/panelcontainer.authoring.schema.yaml"); + + // Mirrors the "panelcontainer" fixture from panelcontainer/test-content.json + String fixtureJson = "{" + "\"name\": \"abc\"," + "\"jcr:title\": \"dependent names\"," + + "\"fieldType\": \"panel\"" + "}"; + JsonNode fixture = JSON_MAPPER.readTree(fixtureJson); + + Set errors = schema.validate(fixture); + assertTrue(errors.isEmpty(), + "Minimal panelcontainer JCR node should conform to authoring schema but got: " + errors); + } + + @Test + void customizedPanelContainerNodeConformsToAuthoringSchema() throws Exception { + JsonSchema schema = loadSchema("/authoring-schema/components/panelcontainer.authoring.schema.yaml"); + + // Mirrors the "panelcontainer-customized" fixture (flat properties only, no child nodes) + String fixtureJson = "{" + "\"name\": \"abc\"," + "\"jcr:title\": \"dependent names\"," + + "\"description\": \"dependent names description\"," + "\"tooltip\": \"dependent names tooltip\"," + + "\"fieldType\": \"panel\"," + "\"dorExclusion\": true," + "\"dorExcludeTitle\": false," + + "\"dorExcludeDescription\": false," + "\"visible\": false," + "\"enabled\": false," + + "\"required\": true," + "\"readOnly\": true," + "\"breakBeforeText\": \"Following Previous\"," + + "\"breakAfterText\": \"Continue Filling Parent\"," + "\"overflowText\": \"None\"" + "}"; + JsonNode fixture = JSON_MAPPER.readTree(fixtureJson); + + Set errors = schema.validate(fixture); + assertTrue(errors.isEmpty(), + "Customized panelcontainer JCR node should conform to authoring schema but got: " + errors); + } +} diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java index 97c1509fb1..904ee0485b 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/NumberInputImplTest.java @@ -52,16 +52,23 @@ public class NumberInputImplTest { private static final String PATH_NUMBER_INPUT_CUSTOMIZED = CONTENT_ROOT + "/numberinput-customized"; private static final String PATH_NUMBER_INPUT_INTEGER_TYPE = CONTENT_ROOT + "/numberinput-integer-type"; private static final String PATH_NUMBER_INPUT_CONSTRAINTS = CONTENT_ROOT + "/numberinput-exclusive"; - private static final String PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE = CONTENT_ROOT + "/numberinput-backwardcompatible"; - private static final String PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_2 = CONTENT_ROOT + "/numberinput-backwardcompatible-2"; - private static final String PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING = CONTENT_ROOT + "/numberinput-backwardcompatible-string"; + private static final String PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE = CONTENT_ROOT + + "/numberinput-backwardcompatible"; + private static final String PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_2 = CONTENT_ROOT + + "/numberinput-backwardcompatible-2"; + private static final String PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING = CONTENT_ROOT + + "/numberinput-backwardcompatible-string"; private static final String PATH_NUMBER_INPUT = CONTENT_ROOT + "/numberinput"; private static final String PATH_NUMBER_INPUT_DATALAYER = CONTENT_ROOT + "/numberinput-datalayer"; - private static final String PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION = CONTENT_ROOT + "/numberinput-displayvalueExpression"; + private static final String PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION = CONTENT_ROOT + + "/numberinput-displayvalueExpression"; private static final String PATH_NUMBER_INPUT_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/numberinput-without-fieldtype"; - private static final String PATH_NUMBER_INPUT_WITH_DISPLAY_FORMAT = CONTENT_ROOT + "/numberinput-with-display-format"; - private static final String PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT = CONTENT_ROOT + "/numberinput-with-custom-display-format"; - private static final String PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS = CONTENT_ROOT + "/numberinput-with-both-display-formats"; + private static final String PATH_NUMBER_INPUT_WITH_DISPLAY_FORMAT = CONTENT_ROOT + + "/numberinput-with-display-format"; + private static final String PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT = CONTENT_ROOT + + "/numberinput-with-custom-display-format"; + private static final String PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS = CONTENT_ROOT + + "/numberinput-with-both-display-formats"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -212,13 +219,15 @@ void testGetDisplayFormat() { @Test void testGetDisplayFormatWithCustomDisplayFormat() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT, + NumberInput.class, context); assertEquals("customCurrency", numberInput.getDisplayFormat()); } @Test void testGetDisplayFormatWithBothFormats() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS, + NumberInput.class, context); // customDisplayFormat should take priority over displayFormat assertEquals("customCurrency", numberInput.getDisplayFormat()); } @@ -262,7 +271,8 @@ void testGetConstraintMessages() { @Test void testGetConstraintMessagesTypeInteger() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_INTEGER_TYPE, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_INTEGER_TYPE, NumberInput.class, + context); Map constraintsMessages = numberInput.getConstraintMessages(); assertEquals(constraintsMessages.get(ConstraintType.MAXIMUM), "Please enter a valid Number"); assertEquals(constraintsMessages.get(ConstraintType.MINIMUM), "Please enter a valid Number"); @@ -282,13 +292,15 @@ void testJSONExport() throws Exception { @Test void testJSONExportBackwardCompatible() throws Exception { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE, NumberInput.class, + context); Utils.testJSONExport(numberInput, Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE)); } @Test void testJSONExportBackwardCompatible2() throws Exception { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_2, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_2, + NumberInput.class, context); Utils.testJSONExport(numberInput, Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_2)); } @@ -351,7 +363,8 @@ void testGetMaximum() { @Test void testGetExclusiveMinimum() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, + context); assertEquals(10002L, numberInput.getExclusiveMinimumNumber().longValue()); NumberConstraint numberInputConstraintMock = Mockito.mock(NumberConstraint.class); NumberConstraintV2 numberInputConstraintMock2 = Mockito.mock(NumberConstraintV2.class); @@ -364,7 +377,8 @@ void testGetExclusiveMinimum() { @Test void testGetExclusiveMaximum() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_CONSTRAINTS, NumberInput.class, + context); assertEquals(2000002, numberInput.getExclusiveMaximum().longValue()); assertEquals(2000002, numberInput.getExclusiveMaximumNumber().longValue()); NumberConstraint numberInputConstraintMock = Mockito.mock(NumberConstraint.class); @@ -377,7 +391,8 @@ void testGetExclusiveMaximum() { @Test void testGetExclusiveMinimum_BC() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING, + NumberInput.class, context); assertNull(numberInput.getMinimum()); assertEquals(10002L, numberInput.getExclusiveMinimum().longValue()); assertEquals(10002L, numberInput.getExclusiveMinimumNumber().longValue()); @@ -385,7 +400,8 @@ void testGetExclusiveMinimum_BC() { @Test void testGetExclusiveMaximum_BC() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_BACKWARD_COMPATIBLE_STRING, + NumberInput.class, context); assertNull(numberInput.getMaximum()); assertEquals(2000002, numberInput.getExclusiveMaximum().longValue()); assertEquals(2000002, numberInput.getExclusiveMaximumNumber().longValue()); @@ -429,32 +445,40 @@ void testGetDisplayValueExpression() throws Exception { NumberInput numberInputMock = Mockito.mock(NumberInput.class); Mockito.when(numberInputMock.getDisplayValueExpression()).thenCallRealMethod(); assertEquals(null, numberInputMock.getDisplayValueExpression()); - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION, + NumberInput.class, context); assertEquals("($field.$value & abc)", numberInput.getDisplayValueExpression()); } @Test void testJSONExportForDisplayValueExpression() throws Exception { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION, NumberInput.class, context); - Utils.testJSONExport(numberInput, Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION)); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION, + NumberInput.class, context); + Utils.testJSONExport(numberInput, + Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_DISPLAY_VALUE_EXPRESSION)); } @Test void testNoFieldType() { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITHOUT_FIELDTYPE, NumberInput.class, context); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITHOUT_FIELDTYPE, NumberInput.class, + context); assertEquals(FieldType.NUMBER_INPUT.getValue(), numberInput.getFieldType()); } @Test void testJSONExportWithCustomDisplayFormat() throws Exception { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT, NumberInput.class, context); - Utils.testJSONExport(numberInput, Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT)); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT, + NumberInput.class, context); + Utils.testJSONExport(numberInput, + Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_WITH_CUSTOM_DISPLAY_FORMAT)); } @Test void testJSONExportWithBothDisplayFormats() throws Exception { - NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS, NumberInput.class, context); - Utils.testJSONExport(numberInput, Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS)); + NumberInput numberInput = Utils.getComponentUnderTest(PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS, + NumberInput.class, context); + Utils.testJSONExport(numberInput, + Utils.getTestExporterJSONPath(BASE, PATH_NUMBER_INPUT_WITH_BOTH_DISPLAY_FORMATS)); } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelContainerImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelContainerImplTest.java index 27824d5704..284c94a93f 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelContainerImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelContainerImplTest.java @@ -74,10 +74,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImplTest.java index 37142ca4be..468651815f 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/PanelImplTest.java @@ -79,10 +79,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -173,8 +171,7 @@ void tearDown() { void testExportedItemsMapByDefault() { Panel panel = Utils.getComponentUnderTest(PATH_PANEL, Panel.class, context); Map exportedItems = panel.getExportedItems(); - assertFalse(exportedItems.isEmpty(), - "getExportedItems should return non-empty map when toggle is OFF"); + assertFalse(exportedItems.isEmpty(), "getExportedItems should return non-empty map when toggle is OFF"); assertTrue(exportedItems.containsKey("textinput")); String[] order = panel.getExportedItemsOrder(); assertEquals(1, order.length); @@ -186,14 +183,12 @@ void testExportedItemsArrayWhenToggleEnabled() { System.setProperty(FeatureToggleConstants.FT_SKIP_ITEMS_MAP, "true"); Panel panel = Utils.getComponentUnderTest(PATH_PANEL, Panel.class, context); Map exportedItems = panel.getExportedItems(); - assertTrue(exportedItems.isEmpty(), - "getExportedItems should return empty map when toggle is ON"); + assertTrue(exportedItems.isEmpty(), "getExportedItems should return empty map when toggle is ON"); String[] order = panel.getExportedItemsOrder(); assertEquals(0, order.length); PanelImpl panelImpl = (PanelImpl) panel; List itemsArray = panelImpl.getExportedItemsArray(); - assertFalse(itemsArray.isEmpty(), - "getExportedItemsArray should return non-empty list when toggle is ON"); + assertFalse(itemsArray.isEmpty(), "getExportedItemsArray should return non-empty list when toggle is ON"); assertEquals(1, itemsArray.size()); } @@ -202,8 +197,7 @@ void testExportedItemsArrayEmptyWhenToggleDisabled() { Panel panel = Utils.getComponentUnderTest(PATH_PANEL, Panel.class, context); PanelImpl panelImpl = (PanelImpl) panel; List itemsArray = panelImpl.getExportedItemsArray(); - assertTrue(itemsArray.isEmpty(), - "getExportedItemsArray should return empty list when toggle is OFF"); + assertTrue(itemsArray.isEmpty(), "getExportedItemsArray should return empty list when toggle is OFF"); } @Test diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/RadioButtonImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/RadioButtonImplTest.java index db907d4705..512926dc2c 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/RadioButtonImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/RadioButtonImplTest.java @@ -45,16 +45,20 @@ public class RadioButtonImplTest { private static final String BASE = "/form/radiobutton"; private static final String CONTENT_ROOT = "/content"; private static final String PATH_RADIOBUTTON_CUSTOMIZED = CONTENT_ROOT + "/radiobutton-customized"; - private static final String PATH_RADIOBUTTON_CUSTOMIZED_WITH_LABEL = CONTENT_ROOT + "/radiobutton-customized-withLabel"; - private static final String PATH_RADIOBUTTON_CUSTOMIZED_WITH_NAME = CONTENT_ROOT + "/radiobutton-customized-withName"; - private static final String PATH_RADIOBUTTON_CUSTOMIZED_WITH_DESC = CONTENT_ROOT + "/radiobutton-customized-withDescription"; + private static final String PATH_RADIOBUTTON_CUSTOMIZED_WITH_LABEL = CONTENT_ROOT + + "/radiobutton-customized-withLabel"; + private static final String PATH_RADIOBUTTON_CUSTOMIZED_WITH_NAME = CONTENT_ROOT + + "/radiobutton-customized-withName"; + private static final String PATH_RADIOBUTTON_CUSTOMIZED_WITH_DESC = CONTENT_ROOT + + "/radiobutton-customized-withDescription"; private static final String PATH_RADIOBUTTON = CONTENT_ROOT + "/radiobutton"; private static final String PATH_RADIOBUTTON_DATALAYER = CONTENT_ROOT + "/radiobutton-datalayer"; private static final String PATH_RADIOBUTTON_WITH_DUPLICATE_ENUMS = CONTENT_ROOT + "/radiobutton-duplicate-enum"; private static final String PATH_RADIOBUTTON_FOR_INSERTION_ORDER = CONTENT_ROOT + "/radiobutton-insertion-order"; private static final String PATH_RADIOBUTTON_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/radiobutton-without-fieldtype"; - private static final String PATH_RADIOBUTTON_OPTION_SCREEN_READER_LABEL = CONTENT_ROOT + "/radiobutton-option-screenreader-label"; + private static final String PATH_RADIOBUTTON_OPTION_SCREEN_READER_LABEL = CONTENT_ROOT + + "/radiobutton-option-screenreader-label"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -383,16 +387,17 @@ void testJSONExportDataLayer() throws Exception { @Test void testInsertionOrderForEnums() { RadioButton radioButton = getRadioButtonUnderTest(PATH_RADIOBUTTON_FOR_INSERTION_ORDER); - Set set = new LinkedHashSet<>(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", - "15", "16", "17", "18", "19", "20")); + Set set = new LinkedHashSet<>(Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", + "11", "12", "13", "14", "15", "16", "17", "18", "19", "20")); assertArrayEquals(set.toArray(new Object[0]), radioButton.getEnums()); } @Test void testInsertionOrderForEnumNames() { RadioButton radioButton = getRadioButtonUnderTest(PATH_RADIOBUTTON_FOR_INSERTION_ORDER); - Set set = new LinkedHashSet<>(Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", - "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty")); + Set set = new LinkedHashSet<>(Arrays.asList("Zero", "One", "Two", "Three", "Four", "Five", "Six", + "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", + "Seventeen", "Eighteen", "Nineteen", "Twenty")); assertArrayEquals(set.toArray(new String[0]), radioButton.getEnumNames()); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java index 4b8e902de1..878d819ebd 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/ReviewImplTest.java @@ -54,8 +54,8 @@ void testGetEditAction() { public void testGetLinkedPanelsWithNonNullArray() throws IOException { Review review = Utils.getComponentUnderTest(PATH_REVIEW, ReviewImpl.class, context); String[] linkedPanels = review.getLinkedPanels(); - String[] expectedLinkedPanels = context.resourceResolver().getResource(PATH_REVIEW).getValueMap().get("fd:linkedPanels", - String[].class); + String[] expectedLinkedPanels = context.resourceResolver().getResource(PATH_REVIEW).getValueMap() + .get("fd:linkedPanels", String[].class); assertNotNull(expectedLinkedPanels); assertArrayEquals(expectedLinkedPanels, linkedPanels); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/SwitchImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/SwitchImplTest.java index 8f089b55f2..1a946be2c9 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/SwitchImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/SwitchImplTest.java @@ -47,9 +47,11 @@ public class SwitchImplTest { private static final String PATH_SWITCH_ENABLEUNCHECKEDOFF = CONTENT_ROOT + "/switch-enableUncheckedValueFalse"; private static final String PATH_SWITCH_ENABLEUNCHECKED_BOOLEAN = CONTENT_ROOT + "/switch-boolean"; - private static final String PATH_SWITCH_ENABLEUNCHECKEDOFF_BOOLEAN = CONTENT_ROOT + "/switch-enableUncheckedValueFalse-boolean"; + private static final String PATH_SWITCH_ENABLEUNCHECKEDOFF_BOOLEAN = CONTENT_ROOT + + "/switch-enableUncheckedValueFalse-boolean"; private static final String PATH_SWITCH_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/switch-without-fieldtype"; - private static final String PATH_SWITCH_OPTION_SCREEN_READER_LABEL = CONTENT_ROOT + "/switch-option-screenreader-label"; + private static final String PATH_SWITCH_OPTION_SCREEN_READER_LABEL = CONTENT_ROOT + + "/switch-option-screenreader-label"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @BeforeEach diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImplTest.java index 228abc2260..2a3838a3f6 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TermsAndConditionsImplTest.java @@ -74,10 +74,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -128,7 +126,8 @@ void testNoWrap() { @Test void testNoFieldType() { - TermsAndConditions tnc = Utils.getComponentUnderTest(PATH_TNC_WITHOUT_FIELDTYPE, TermsAndConditions.class, context); + TermsAndConditions tnc = Utils.getComponentUnderTest(PATH_TNC_WITHOUT_FIELDTYPE, TermsAndConditions.class, + context); assertEquals(FieldType.PANEL.getValue(), tnc.getFieldType()); } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImplTest.java index 4eaf4c07cc..bce079519f 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextImplTest.java @@ -26,6 +26,7 @@ import com.adobe.cq.forms.core.components.internal.form.FormConstants; import com.adobe.cq.forms.core.components.models.form.*; import com.adobe.cq.forms.core.context.FormsCoreComponentTestContext; +import com.fasterxml.jackson.databind.ObjectMapper; import io.wcm.testing.mock.aem.junit5.AemContext; import io.wcm.testing.mock.aem.junit5.AemContextExtension; @@ -91,6 +92,17 @@ void testIsRichText() { assertEquals(false, textMock.isRichText()); } + @Test + void testRichTextAbsentFromJcr() throws Exception { + // PATH_TEXT has no textIsRich in JCR — isRichText() must return false (interface default), + // and "richText" must be absent from JSON output (not serialized when null). + Text text = Utils.getComponentUnderTest(PATH_TEXT, Text.class, context); + assertEquals(false, text.isRichText()); + String json = new ObjectMapper().writeValueAsString(text); + assertFalse("richText must not appear in JSON when textIsRich is absent from JCR", + json.contains("\"richText\"")); + } + @Test void testGetDataRef() { Text text = Utils.getComponentUnderTest(PATH_TEXT_CUSTOMIZED, Text.class, context); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImplTest.java index 1542522422..9e761b95fe 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TextInputImplTest.java @@ -62,14 +62,18 @@ public class TextInputImplTest { private static final String PATH_FORMAT_TEXTINPUT = CONTENT_ROOT + "/textinput-format"; private static final String PATH_TEXTINPUT_UNBOUNDFORMELEMENT = CONTENT_ROOT + "/textinput_unboundFormElement"; private static final String PATH_TEXTINPUT_BLANK_DATAREF = CONTENT_ROOT + "/textinput-blank-dataref"; - private static final String PATH_TEXTINPUT_BLANK_VALIDATIONEXPRESSION = CONTENT_ROOT + "/textinput-blank-validationExpression"; - private static final String PATH_TEXTINPUT_DISPLAY_VALUE_EXPRESSION = CONTENT_ROOT + "/textinput-displayValueExpression"; - private static final String PATH_TEXTINPUT_PLACEHOLDER_AUTOCOMPLETE = CONTENT_ROOT + "/textinput-placeholder-autocomplete"; + private static final String PATH_TEXTINPUT_BLANK_VALIDATIONEXPRESSION = CONTENT_ROOT + + "/textinput-blank-validationExpression"; + private static final String PATH_TEXTINPUT_DISPLAY_VALUE_EXPRESSION = CONTENT_ROOT + + "/textinput-displayValueExpression"; + private static final String PATH_TEXTINPUT_PLACEHOLDER_AUTOCOMPLETE = CONTENT_ROOT + + "/textinput-placeholder-autocomplete"; private static final String PATH_TEXTINPUT_WITH_VIEWTYPE = CONTENT_ROOT + "/textinput-with-viewtype"; private static final String PATH_TEXTINPUT_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/textinput-without-fieldtype"; private static final String PATH_TEXTINPUT_EMPTYVALUE_NULL = CONTENT_ROOT + "/textinput-emptyvalue-null"; private static final String PATH_TEXTINPUT_EMPTYVALUE_UNDEFINED = CONTENT_ROOT + "/textinput-emptyvalue-undefined"; - private static final String PATH_TEXTINPUT_EMPTYVALUE_EMPTY_STRING = CONTENT_ROOT + "/textinput-emptyvalue-empty-string"; + private static final String PATH_TEXTINPUT_EMPTYVALUE_EMPTY_STRING = CONTENT_ROOT + + "/textinput-emptyvalue-empty-string"; private static final String PATH_TEXTINPUT_EMPTYVALUE_INVALID = CONTENT_ROOT + "/textinput-emptyvalue-invalid"; private static final String PATH_TEXTINPUT_EMPTYVALUE_NOT_SET = CONTENT_ROOT + "/textinput-emptyvalue-not-set"; @@ -324,14 +328,16 @@ void testGetMinimum() { @Test void testGetExclusiveMinimum() { - TextInput numberTextInput = Utils.getComponentUnderTest(PATH_NUMBER_TEXTINPUT_EXCLUSIVE, TextInput.class, context); + TextInput numberTextInput = Utils.getComponentUnderTest(PATH_NUMBER_TEXTINPUT_EXCLUSIVE, TextInput.class, + context); assertNull(numberTextInput.getMinimum()); assertEquals(10L, numberTextInput.getExclusiveMinimum().longValue()); } @Test void testGetExclusiveMaximum() { - TextInput numberTextInput = Utils.getComponentUnderTest(PATH_NUMBER_TEXTINPUT_EXCLUSIVE, TextInput.class, context); + TextInput numberTextInput = Utils.getComponentUnderTest(PATH_NUMBER_TEXTINPUT_EXCLUSIVE, TextInput.class, + context); assertNull(numberTextInput.getMaximum()); assertEquals(100L, numberTextInput.getExclusiveMaximum().longValue()); } @@ -409,30 +415,25 @@ public void testGetCustomProperties() throws Exception { Assertions.assertEquals(45L, result.get("customPropLong")); assertArrayEquals(new Long[] { 345L, 576L }, (Object[]) result.get("customPropLongArray")); Assertions.assertEquals(new BigDecimal("45.67"), (BigDecimal) result.get("customPropDecimal")); - assertArrayEquals(new BigDecimal[] { new BigDecimal("45.67"), new BigDecimal("90.34") }, (BigDecimal[]) result.get( - "customPropDecimalArray")); + assertArrayEquals(new BigDecimal[] { new BigDecimal("45.67"), new BigDecimal("90.34") }, + (BigDecimal[]) result.get("customPropDecimalArray")); Assertions.assertEquals(new GregorianCalendar(2022, Calendar.SEPTEMBER, 13, 9, 0, 0) { { set(Calendar.MILLISECOND, 0); setTimeZone(TimeZone.getTimeZone("UTC")); } }, (Calendar) result.get("customPropDate")); - assertArrayEquals( - new Calendar[] { - new GregorianCalendar(2022, Calendar.SEPTEMBER, 13, 9, 0, 0) { - { - set(Calendar.MILLISECOND, 0); - setTimeZone(TimeZone.getTimeZone("UTC")); - } - }, - new GregorianCalendar(2024, Calendar.JUNE, 22, 14, 0, 0) { - { - set(Calendar.MILLISECOND, 0); - setTimeZone(TimeZone.getTimeZone("UTC")); - } - } - }, - (Calendar[]) result.get("customPropDateArray")); + assertArrayEquals(new Calendar[] { new GregorianCalendar(2022, Calendar.SEPTEMBER, 13, 9, 0, 0) { + { + set(Calendar.MILLISECOND, 0); + setTimeZone(TimeZone.getTimeZone("UTC")); + } + }, new GregorianCalendar(2024, Calendar.JUNE, 22, 14, 0, 0) { + { + set(Calendar.MILLISECOND, 0); + setTimeZone(TimeZone.getTimeZone("UTC")); + } + } }, (Calendar[]) result.get("customPropDateArray")); Assertions.assertNull(result.get("fd:accidentalPrefix")); Assertions.assertNull(result.get("sling:accidentalPrefix")); Assertions.assertNull(result.get("jcr:accidentalPrefix")); @@ -510,13 +511,15 @@ void testJSONExportForBlankDataRef() throws Exception { @Test void testJSONExportForEmptyValidationExpression() throws Exception { - TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_BLANK_VALIDATIONEXPRESSION, TextInput.class, context); + TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_BLANK_VALIDATIONEXPRESSION, TextInput.class, + context); Utils.testJSONExport(textInput, Utils.getTestExporterJSONPath(BASE, PATH_TEXTINPUT_BLANK_VALIDATIONEXPRESSION)); } @Test void testPlaceholderAndAutocomplete() throws Exception { - TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_PLACEHOLDER_AUTOCOMPLETE, TextInput.class, context); + TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_PLACEHOLDER_AUTOCOMPLETE, TextInput.class, + context); Utils.testJSONExport(textInput, Utils.getTestExporterJSONPath(BASE, PATH_TEXTINPUT_PLACEHOLDER_AUTOCOMPLETE)); assertEquals("given-name", textInput.getAutoComplete()); assertEquals("test-placeholder", textInput.getPlaceHolder()); @@ -524,7 +527,8 @@ void testPlaceholderAndAutocomplete() throws Exception { @Test void testJSONExportForDisplayValueExpression() throws Exception { - TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_DISPLAY_VALUE_EXPRESSION, TextInput.class, context); + TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_DISPLAY_VALUE_EXPRESSION, TextInput.class, + context); Utils.testJSONExport(textInput, Utils.getTestExporterJSONPath(BASE, PATH_TEXTINPUT_DISPLAY_VALUE_EXPRESSION)); } @@ -549,13 +553,15 @@ void testEmptyValueNull() { @Test void testEmptyValueUndefined() { - TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_EMPTYVALUE_UNDEFINED, TextInput.class, context); + TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_EMPTYVALUE_UNDEFINED, TextInput.class, + context); assertEquals("undefined", textInput.getEmptyValue()); } @Test void testEmptyValueEmptyString() { - TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_EMPTYVALUE_EMPTY_STRING, TextInput.class, context); + TextInput textInput = Utils.getComponentUnderTest(PATH_TEXTINPUT_EMPTYVALUE_EMPTY_STRING, TextInput.class, + context); assertEquals("", textInput.getEmptyValue()); } @@ -574,16 +580,12 @@ void testEmptyValueNotSet() { @Test void testEmptyValueEnumFromString() { // Test the enum's fromString method directly - assertEquals(AbstractFieldImpl.EmptyValue.NULL, - AbstractFieldImpl.EmptyValue.fromString("null")); - assertEquals(AbstractFieldImpl.EmptyValue.UNDEFINED, - AbstractFieldImpl.EmptyValue.fromString("undefined")); - assertEquals(AbstractFieldImpl.EmptyValue.EMPTY_STRING, - AbstractFieldImpl.EmptyValue.fromString("")); + assertEquals(AbstractFieldImpl.EmptyValue.NULL, AbstractFieldImpl.EmptyValue.fromString("null")); + assertEquals(AbstractFieldImpl.EmptyValue.UNDEFINED, AbstractFieldImpl.EmptyValue.fromString("undefined")); + assertEquals(AbstractFieldImpl.EmptyValue.EMPTY_STRING, AbstractFieldImpl.EmptyValue.fromString("")); assertEquals(AbstractFieldImpl.EmptyValue.EMPTY_STRING, AbstractFieldImpl.EmptyValue.fromString("invalid-value")); - assertEquals(null, - AbstractFieldImpl.EmptyValue.fromString(null)); + assertEquals(null, AbstractFieldImpl.EmptyValue.fromString(null)); } @Test @@ -616,4 +618,11 @@ void testGetEventsOmitsSetPropertyWhenToggleEnabled() { assertFalse("getEvents should NOT include custom:setProperty when toggle is ON", events.containsKey("custom:setProperty")); } + + @Test + void testJcrAuthoringSchemaCompliance() { + context.currentResource(PATH_TEXTINPUT); + Resource resource = context.currentResource(); + Utils.testJcrSchemaValidation(resource, "/authoring-schema/components/textinput.authoring.schema.yaml"); + } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImplTest.java index 405ec23c99..68ae677163 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TitleImplTest.java @@ -155,12 +155,13 @@ void testTitleWithWcmEditMode() throws Exception { void testTitleWithLocale() throws Exception { context.currentResource(PATH_TITLE); // added this since AF API expects this to be present - GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, Mockito.mock( - GuideLocalizationService.class)); + GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, + Mockito.mock(GuideLocalizationService.class)); Mockito.when(guideLocalizationService.getSupportedLocales()).thenReturn(new String[] { "en", "de" }); - MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context.getService(ResourceBundleProvider.class); - MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider.getResourceBundle( - "/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); + MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context + .getService(ResourceBundleProvider.class); + MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider + .getResourceBundle("/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); resourceBundle.putAll(new HashMap() { { put("guideContainer##title##text##5648", "Title"); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImplTest.java index d54786385b..82b4f8fb37 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/TurnstileImplTest.java @@ -141,7 +141,8 @@ void testIsEnabled() { void testJSONExport() throws Exception { Mockito.when(turnstileConfig.getSiteKey()).thenReturn("siteKey"); Mockito.when(turnstileConfig.getWidgetType()).thenReturn("invisible"); - Mockito.when(turnstileConfig.getClientSideJsUrl()).thenReturn("https://challenges.cloudflare.com/turnstile/v0/api.js"); + Mockito.when(turnstileConfig.getClientSideJsUrl()) + .thenReturn("https://challenges.cloudflare.com/turnstile/v0/api.js"); Turnstile turnstile = Utils.getComponentUnderTest(PATH_TURNSTILE, Turnstile.class, context); Utils.testJSONExport(turnstile, Utils.getTestExporterJSONPath(BASE, PATH_TURNSTILE)); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/WizardImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/WizardImplTest.java index d4b501c07b..e6a6a85370 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/WizardImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v1/form/WizardImplTest.java @@ -68,10 +68,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationTest.java index 71037f4131..50c989a868 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/AutoSaveConfigurationTest.java @@ -54,8 +54,8 @@ void testAutoSaveConfigurationForDefaultImplementation() { @Test void testAutoSaveConfigurationForResourceAdaptation() { - final AutoSaveConfiguration autoSaveConfiguration = context.currentResource(GUIDE_CONTAINER_ROOT).adaptTo( - AutoSaveConfiguration.class); + final AutoSaveConfiguration autoSaveConfiguration = context.currentResource(GUIDE_CONTAINER_ROOT) + .adaptTo(AutoSaveConfiguration.class); assertEquals(true, autoSaveConfiguration.isEnableAutoSave()); assertEquals(AutoSaveConfiguration.AutoSaveStrategyType.TIME, autoSaveConfiguration.getAutoSaveStrategyType()); assertEquals((Integer) 2, autoSaveConfiguration.getAutoSaveInterval()); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FileInputImplV2Test.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FileInputImplV2Test.java index ba4f0e6b41..9e0993b8cc 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FileInputImplV2Test.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FileInputImplV2Test.java @@ -58,7 +58,8 @@ public class FileInputImplV2Test { private static final String PATH_FILEINPUT = CONTENT_ROOT + "/fileinput"; private static final String PATH_FILEINPUT_DATALAYER = CONTENT_ROOT + "/fileinput-datalayer"; private static final String PATH_MULTISELECT_FILEINPUT = CONTENT_ROOT + "/multiselect-fileinput"; - private static final String PATH_MULTISELECT_FILEINPUT_WITHNOTYPE = CONTENT_ROOT + "/multiselect-fileinput-withNoType"; + private static final String PATH_MULTISELECT_FILEINPUT_WITHNOTYPE = CONTENT_ROOT + + "/multiselect-fileinput-withNoType"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -84,7 +85,8 @@ void testFieldType() { @Test void testType() { - FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITHNOTYPE, FileInput.class, context); + FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITHNOTYPE, FileInput.class, + context); assertEquals(fileInput.getType(), fileInput.getType()); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImplTest.java index 53f74a3293..545401900d 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/FormContainerImplTest.java @@ -97,25 +97,27 @@ public class FormContainerImplTest { private static final String PATH_FORM_SUBMISSION_VIEW = CONTENT_ROOT + "/formcontainer-submissionView"; private static final String PATH_UE_FORM_WITH_SPREADSHEET_SUBMISSION = CONTENT_ROOT + "/formContainer-ue-form-spreadsheet-submission"; - private static final String PATH_UE_FORM_REST_SUBMISSION = CONTENT_ROOT - + "/formContainer-ue-form-rest-submission"; + private static final String PATH_UE_FORM_REST_SUBMISSION = CONTENT_ROOT + "/formContainer-ue-form-rest-submission"; private static final String PATH_CC_FORM_SPREADSHEET_SUBMISSION = CONTENT_ROOT + "/formContainer-cc-form-spreadsheet-submission"; - private static final String PATH_CC_FORM_REST_SUBMISSION = CONTENT_ROOT - + "/formContainer-cc-form-rest-submission"; + private static final String PATH_CC_FORM_REST_SUBMISSION = CONTENT_ROOT + "/formContainer-cc-form-rest-submission"; private static final String PATH_FORM_WITH_FRAGMENT = CONTENT_ROOT + "/formcontainerv2-with-fragment"; private static final String PATH_FORM_WITHOUT_FIELDTYPE = CONTENT_ROOT + "/formcontainerv2-without-fieldtype"; private static final String PATH_FORM_WITH_AUTO_SAVE = CONTENT_ROOT + "/formcontainerv2WithAutoSave"; private static final String PATH_FORM_1_WITHOUT_REDIRECT = CONTENT_ROOT + "/formcontainerv2WithoutRedirect"; private static final String CONTENT_FORM_WITHOUT_PREFILL_ROOT = "/content/forms/af/formWithoutPrefill"; - private static final String PATH_FORM_WITHOUT_PREFILL = CONTENT_FORM_WITHOUT_PREFILL_ROOT + "/formcontainerv2WithoutPrefill"; - private static final String PATH_FORM_WITH_SPEC = CONTENT_FORM_WITHOUT_PREFILL_ROOT + "/formcontainerv2withspecversion"; + private static final String PATH_FORM_WITHOUT_PREFILL = CONTENT_FORM_WITHOUT_PREFILL_ROOT + + "/formcontainerv2WithoutPrefill"; + private static final String PATH_FORM_WITH_SPEC = CONTENT_FORM_WITHOUT_PREFILL_ROOT + + "/formcontainerv2withspecversion"; + private static final String PATH_FORM_FULL = CONTENT_FORM_WITHOUT_PREFILL_ROOT + "/formcontainerv2-full"; private static final String LIB_FORM_CONTAINER = "/libs/core/fd/components/form/container/v2/container"; protected static final String SITES_PATH = "/content/exampleSite"; protected static final String SITES_LANG_PATH = "/content/th/exampleSite"; - protected static final String FORM_CONTAINER_PATH_IN_SITES = SITES_PATH + "/jcr:content/root/sitecontainer/formcontainer"; + protected static final String FORM_CONTAINER_PATH_IN_SITES = SITES_PATH + + "/jcr:content/root/sitecontainer/formcontainer"; protected static final String FORM_CONTAINER_PATH_WITH_LANGUAGE_IN_SITES = SITES_LANG_PATH + "/jcr:content/root/sitecontainer/formcontainer"; @@ -130,10 +132,13 @@ public class FormContainerImplTest { @BeforeEach void setUp() { context.load().json(BASE + "/test-localization-content.json", CONTENT_DAM_ROOT); // required for localization - context.load().json(BASE + "/test-page-content.json", CONTENT_PAGE_ROOT); // required for localization since we traverse the + context.load().json(BASE + "/test-page-content.json", CONTENT_PAGE_ROOT); // required for localization since we + // traverse the // resource up to find page - context.load().json(BASE + "/test-lib-form-container.json", LIB_FORM_CONTAINER); // required since v2 container resource type should - // be v1 for localization to work + context.load().json(BASE + "/test-lib-form-container.json", LIB_FORM_CONTAINER); // required since v2 container + // resource type should + // be v1 for localization to + // work context.load().json(BASE + "/test-forms-in-sites.json", SITES_PATH); context.load().json(BASE + "/test-forms-in-sites.json", SITES_LANG_PATH); context.load().json(BASE + "/test-content.json", CONTENT_FORM_WITHOUT_PREFILL_ROOT); @@ -155,10 +160,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -181,9 +184,11 @@ void testGetId() throws Exception { @Test void testGetIdForSitePage() throws Exception { - FormContainer formContainer = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_IN_SITES, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_IN_SITES, FormContainer.class, + context); assertNotNull(formContainer.getId()); - assertEquals("L2NvbnRlbnQvZXhhbXBsZVNpdGUvamNyOmNvbnRlbnQvcm9vdC9zaXRlY29udGFpbmVyL2Zvcm1jb250YWluZXI=", formContainer.getId()); + assertEquals("L2NvbnRlbnQvZXhhbXBsZVNpdGUvamNyOmNvbnRlbnQvcm9vdC9zaXRlY29udGFpbmVyL2Zvcm1jb250YWluZXI=", + formContainer.getId()); } @Test @@ -202,7 +207,8 @@ void testGetAdaptiveFormDefaultVersion() throws Exception { @Test void testGetPageLangForSitePage() throws Exception { - FormContainer formContainer = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_WITH_LANGUAGE_IN_SITES, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_WITH_LANGUAGE_IN_SITES, + FormContainer.class, context); assertNotNull(formContainer.getContainingPageLang()); assertEquals("th", formContainer.getContainingPageLang()); } @@ -215,16 +221,17 @@ void testGetAction() throws Exception { @Test void testGetActionForSitePage() throws Exception { - FormContainer formContainer = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_IN_SITES, FormContainer.class, context); - assertEquals("/adobe/forms/af/submit/L2NvbnRlbnQvZXhhbXBsZVNpdGUvamNyOmNvbnRlbnQvcm9vdC9zaXRlY29udGFpbmVyL2Zvcm1jb250YWluZXI=", + FormContainer formContainer = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_IN_SITES, FormContainer.class, + context); + assertEquals( + "/adobe/forms/af/submit/L2NvbnRlbnQvZXhhbXBsZVNpdGUvamNyOmNvbnRlbnQvcm9vdC9zaXRlY29udGFpbmVyL2Zvcm1jb250YWluZXI=", formContainer.getAction()); } @Test void testGetDataUrl() throws Exception { FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); - assertEquals("/adobe/forms/af/data/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==", formContainer - .getDataUrl()); + assertEquals("/adobe/forms/af/data/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==", formContainer.getDataUrl()); } @Test @@ -235,7 +242,8 @@ void testGetActionWithResourceResolverMapping() throws Exception { // Mock the map method to return a mapped path String originalPath = "/adobe/forms/af/submit/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="; String mappedPath = "/content/adobe/forms/af/submit/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="; - Mockito.when(resourceResolver.map("/adobe/forms/af/submit/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==")).thenReturn(mappedPath); + Mockito.when(resourceResolver.map("/adobe/forms/af/submit/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==")) + .thenReturn(mappedPath); // Set the mocked resource resolver in the context context.registerService(org.apache.sling.api.resource.ResourceResolver.class, resourceResolver); @@ -258,7 +266,8 @@ void testGetDataUrlWithResourceResolverMapping() throws Exception { // Mock the map method to return a mapped path String originalPath = "/adobe/forms/af/data/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="; String mappedPath = "/content/adobe/forms/af/data/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="; - Mockito.when(resourceResolver.map("/adobe/forms/af/data/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==")).thenReturn(mappedPath); + Mockito.when(resourceResolver.map("/adobe/forms/af/data/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==")) + .thenReturn(mappedPath); // Set the mocked resource resolver in the context context.registerService(org.apache.sling.api.resource.ResourceResolver.class, resourceResolver); @@ -303,9 +312,7 @@ void testGetIdWithFormRenderingInsideEmbedContainer() throws Exception { @Test void testGetLocalizedValue() throws Exception { FormContainer formContainer = getFormContainerWithLocaleUnderTest(PATH_FORM_1); - TextInput textInput = (TextInput) formContainer.getItems().stream() - .filter(Objects::nonNull) - .findFirst() + TextInput textInput = (TextInput) formContainer.getItems().stream().filter(Objects::nonNull).findFirst() .orElse(null); // assertEquals("dummy 1", textInput.getDescription()); } @@ -313,9 +320,10 @@ void testGetLocalizedValue() throws Exception { @Test void testFormContainerWithI18nSetter() throws Exception { FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); - MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context.getService(ResourceBundleProvider.class); - MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider.getResourceBundle( - "/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); + MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context + .getService(ResourceBundleProvider.class); + MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider + .getResourceBundle("/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); resourceBundle.putAll(new HashMap() { { put("guideContainer##textinput##description##5648", "dummy 1"); @@ -323,11 +331,10 @@ void testFormContainerWithI18nSetter() throws Exception { }); I18n i18n = new I18n(resourceBundle); formContainer.setI18n(i18n); - TextInput textInput = (TextInput) formContainer.getItems().stream() - .filter(Objects::nonNull) - .findFirst() + TextInput textInput = (TextInput) formContainer.getItems().stream().filter(Objects::nonNull).findFirst() .orElse(null); - assertEquals("dummy", textInput.getDescription()); // just a dummy test to make sure i18n is set correctly in the resource hierarchy + assertEquals("dummy", textInput.getDescription()); // just a dummy test to make sure i18n is set correctly in + // the resource hierarchy } @Test @@ -339,8 +346,8 @@ void testJSONExport() throws Exception { @Test void testJSONExportWithAutoSaveEnable() throws Exception { context.load().json(BASE + "/test-content-auto-save.json", PATH_FORM_WITH_AUTO_SAVE); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITH_AUTO_SAVE, - FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITH_AUTO_SAVE, FormContainer.class, + context); Utils.testJSONExport(formContainer, Utils.getTestExporterJSONPath(BASE, PATH_FORM_WITH_AUTO_SAVE)); } @@ -389,7 +396,8 @@ void testGetContextPath() throws Exception { @Test void testGetContextPathWithDefaultRedirect() throws Exception { - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1_WITHOUT_REDIRECT, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1_WITHOUT_REDIRECT, FormContainer.class, + context); assertEquals(formContainer.getRedirectUrl(), "/content/forms/af/demo/jcr:content/formcontainerv2WithoutRedirect.guideThankYouPage.html"); // Test with contextPath set @@ -436,7 +444,8 @@ void testGetParentPagePathForForm() throws Exception { @Test void testGetParentPagePathInSites() throws Exception { - FormContainer formContainerInSites = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_IN_SITES, FormContainer.class, context); + FormContainer formContainerInSites = Utils.getComponentUnderTest(FORM_CONTAINER_PATH_IN_SITES, + FormContainer.class, context); assertEquals(formContainerInSites.getParentPagePath(), SITES_PATH); } @@ -461,9 +470,10 @@ private FormContainer getFormContainerWithLocaleUnderTest(String resourcePath) t GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, mock(GuideLocalizationService.class)); Mockito.when(guideLocalizationService.getSupportedLocales()).thenReturn(new String[] { "en", "de" }); - MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context.getService(ResourceBundleProvider.class); - MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider.getResourceBundle( - "/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); + MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context + .getService(ResourceBundleProvider.class); + MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider + .getResourceBundle("/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); resourceBundle.putAll(new HashMap() { { put("guideContainer##textinput##description##5648", "dummy 1"); @@ -484,9 +494,10 @@ private FormContainer getFormContainerWithRTLLocaleUnderTest(String resourcePath GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, mock(GuideLocalizationService.class)); Mockito.when(guideLocalizationService.getSupportedLocales()).thenReturn(new String[] { "en", "ar-ae" }); - MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context.getService(ResourceBundleProvider.class); - MockResourceBundle resourceBundleRTL = (MockResourceBundle) bundleProvider.getResourceBundle( - "/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("ar-ae")); + MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context + .getService(ResourceBundleProvider.class); + MockResourceBundle resourceBundleRTL = (MockResourceBundle) bundleProvider + .getResourceBundle("/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("ar-ae")); resourceBundleRTL.putAll(new HashMap() { { put("guideContainer##textinput##description##5648", "dummy 1"); @@ -542,7 +553,8 @@ public void testRequestAttributeIfContainerPageDifferent() { @Test void testGetFormDataEnabledWhenPrefillServiceIsSet() throws Exception { FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); - assertTrue(Boolean.valueOf(formContainer.getProperties().get(FormContainerImpl.FD_FORM_DATA_ENABLED).toString())); + assertTrue( + Boolean.valueOf(formContainer.getProperties().get(FormContainerImpl.FD_FORM_DATA_ENABLED).toString())); } @Test @@ -551,8 +563,10 @@ void testGetFormDataEnabledWhenDataRefIsSet() throws Exception { Map tempMap = new HashMap<>(); tempMap.put(GuideConstants.AF_DATA_REF, "abc"); request.setParameterMap(tempMap); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, context); - assertTrue(Boolean.valueOf(formContainer.getProperties().get(FormContainerImpl.FD_FORM_DATA_ENABLED).toString())); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, + context); + assertTrue( + Boolean.valueOf(formContainer.getProperties().get(FormContainerImpl.FD_FORM_DATA_ENABLED).toString())); // reset the parameter map request.setParameterMap(new HashMap<>()); } @@ -563,7 +577,8 @@ void testDraftIdPropertyWhenDataRefIsSet() throws Exception { Map tempMap = new HashMap<>(); tempMap.put(GuideConstants.AF_DATA_REF, "service://FP/draft/KH5DOFY2RMWVOOVREE324MRXIY"); request.setParameterMap(tempMap); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, + context); assertEquals("KH5DOFY2RMWVOOVREE324MRXIY", formContainer.getProperties().get(ReservedProperties.FD_DRAFT_ID)); // reset the parameter map request.setParameterMap(new HashMap<>()); @@ -575,7 +590,8 @@ void testDraftIdPropertyWhenDraftIdIsNotPresentInDataRef() throws Exception { Map tempMap = new HashMap<>(); tempMap.put(GuideConstants.AF_DATA_REF, "service://FP/draft"); request.setParameterMap(tempMap); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, + context); assertNull(formContainer.getProperties().get(ReservedProperties.FD_DRAFT_ID)); // reset the parameter map request.setParameterMap(new HashMap<>()); @@ -583,14 +599,15 @@ void testDraftIdPropertyWhenDraftIdIsNotPresentInDataRef() throws Exception { @Test void testGetFormDataDisabled() throws Exception { - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, context); - assertFalse(Boolean.valueOf(formContainer.getProperties().get(FormContainerImpl.FD_FORM_DATA_ENABLED).toString())); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_PREFILL, FormContainer.class, + context); + assertFalse( + Boolean.valueOf(formContainer.getProperties().get(FormContainerImpl.FD_FORM_DATA_ENABLED).toString())); } @Test public void testAddClientLibRef() { - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, - FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); FormClientLibManager formClientLibManager = context.request().adaptTo(FormClientLibManager.class); List clientLibs = formClientLibManager.getClientLibRefList(); assertEquals(1, clientLibs.size()); @@ -608,7 +625,8 @@ public void testGetLanguageDirection() throws Exception { @Test void testNoFieldType() { - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_FIELDTYPE, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITHOUT_FIELDTYPE, FormContainer.class, + context); assertEquals(FieldType.FORM.getValue(), formContainer.getFieldType()); } @@ -619,18 +637,19 @@ public void testGetIsHamburgerMenuEnabled() { } /** - * Test to check if the properties are fetched from the CoreComponentCustomPropertiesProvider are part of form container properties or - * not - * Also, if same properties is set in form container, then it should override the properties from CoreComponentCustomPropertiesProvider + * Test to check if the properties are fetched from the CoreComponentCustomPropertiesProvider are part of form + * container properties or not Also, if same properties is set in form container, then it should override the + * properties from CoreComponentCustomPropertiesProvider * * @throws Exception */ @Test void testGetPropertiesForCoreComponentCustomPropertiesProvider() throws Exception { - CoreComponentCustomPropertiesProvider coreComponentCustomPropertiesProvider = Mockito.mock( - CoreComponentCustomPropertiesProvider.class); + CoreComponentCustomPropertiesProvider coreComponentCustomPropertiesProvider = Mockito + .mock(CoreComponentCustomPropertiesProvider.class); FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); - Utils.setInternalState(formContainer, "coreComponentCustomPropertiesProvider", coreComponentCustomPropertiesProvider); + Utils.setInternalState(formContainer, "coreComponentCustomPropertiesProvider", + coreComponentCustomPropertiesProvider); Mockito.when(coreComponentCustomPropertiesProvider.getProperties()).thenReturn(new HashMap() { { put("fd:changeEventBehaviour", "deps"); @@ -643,10 +662,11 @@ void testGetPropertiesForCoreComponentCustomPropertiesProvider() throws Exceptio @Test void testGetPropertiesForCoreComponentCustomPropertiesProviderForNull() throws Exception { - CoreComponentCustomPropertiesProvider coreComponentCustomPropertiesProvider = Mockito.mock( - CoreComponentCustomPropertiesProvider.class); + CoreComponentCustomPropertiesProvider coreComponentCustomPropertiesProvider = Mockito + .mock(CoreComponentCustomPropertiesProvider.class); FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); - Utils.setInternalState(formContainer, "coreComponentCustomPropertiesProvider", coreComponentCustomPropertiesProvider); + Utils.setInternalState(formContainer, "coreComponentCustomPropertiesProvider", + coreComponentCustomPropertiesProvider); Mockito.when(coreComponentCustomPropertiesProvider.getProperties()).thenReturn(null); assertEquals("customPropValue", formContainer.getProperties().get("customProp")); } @@ -654,7 +674,8 @@ void testGetPropertiesForCoreComponentCustomPropertiesProviderForNull() throws E @Test void testCustomFunctionUrl() throws Exception { FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_1, FormContainer.class, context); - assertEquals("/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==", formContainer.getCustomFunctionUrl()); + assertEquals("/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==", + formContainer.getCustomFunctionUrl()); } @Test @@ -665,7 +686,8 @@ void testGetCustomFunctionUrlWithResourceResolverMapping() throws Exception { // Mock the map method to return a mapped path String originalPath = "/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="; String mappedPath = "/content/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="; - Mockito.when(resourceResolver.map("/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==")).thenReturn(mappedPath); + Mockito.when(resourceResolver.map("/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw==")) + .thenReturn(mappedPath); // Set the mocked resource resolver in the context context.registerService(org.apache.sling.api.resource.ResourceResolver.class, resourceResolver); @@ -678,17 +700,19 @@ void testGetCustomFunctionUrlWithResourceResolverMapping() throws Exception { assertEquals(mappedPath, customFunctionUrl); // Verify that the map method was called with the correct path (called during mock setup + actual execution) - Mockito.verify(resourceResolver, times(2)).map("/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="); + Mockito.verify(resourceResolver, times(2)) + .map("/adobe/forms/af/customfunctions/L2NvbnRlbnQvZm9ybXMvYWYvZGVtbw=="); } @Test public void testGetAutoSaveProperties() throws Exception { context.load().json(BASE + "/test-content-auto-save.json", PATH_FORM_WITH_AUTO_SAVE); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITH_AUTO_SAVE, - FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITH_AUTO_SAVE, FormContainer.class, + context); assertNotNull(formContainer.getAutoSaveConfig()); assertTrue(formContainer.getAutoSaveConfig().isEnableAutoSave()); - assertEquals(AutoSaveConfiguration.AutoSaveStrategyType.TIME, formContainer.getAutoSaveConfig().getAutoSaveStrategyType()); + assertEquals(AutoSaveConfiguration.AutoSaveStrategyType.TIME, + formContainer.getAutoSaveConfig().getAutoSaveStrategyType()); } @Test @@ -764,7 +788,8 @@ private void setMockClientBuilderFactory(FormContainerImpl formContainer) { @Test public void testJSONExportWithSubmissionAttribute() throws Exception { - FormContainerImpl formContainer = Utils.getComponentUnderTest(PATH_FORM_SUBMISSION_VIEW, FormContainerImpl.class, context); + FormContainerImpl formContainer = Utils.getComponentUnderTest(PATH_FORM_SUBMISSION_VIEW, + FormContainerImpl.class, context); setMockClientBuilderFactory(formContainer); context.request().setAttribute(FormConstants.X_ADOBE_FORM_DEFINITION, FormConstants.FORM_DEFINITION_SUBMISSION); ObjectMapper mapper = new ObjectMapper(); @@ -779,8 +804,7 @@ public void testJSONExportWithSubmissionAttribute() throws Exception { assertEquals("spreadsheet", submitJson.get("actionName").asText()); assertEquals("http://localhost/testurl", submitJson.get(SS_SPREADSHEET).get("spreadsheetUrl").asText()); - Utils.testJSONExport(formContainer, - Utils.getTestExporterJSONPath(BASE, "withSubmissionAttribute")); + Utils.testJSONExport(formContainer, Utils.getTestExporterJSONPath(BASE, "withSubmissionAttribute")); } @Test @@ -801,8 +825,7 @@ public void testJSONExportWithSubmissionHeader() throws Exception { assertEquals("spreadsheet", submitJson.get("actionName").asText()); assertEquals("http://localhost/testurl", submitJson.get(SS_SPREADSHEET).get("spreadsheetUrl").asText()); - Utils.testJSONExport(formContainer, - Utils.getTestExporterJSONPath(BASE, "withSubmissionAttribute")); + Utils.testJSONExport(formContainer, Utils.getTestExporterJSONPath(BASE, "withSubmissionAttribute")); } @Test @@ -814,8 +837,7 @@ public void testJSONExportWithoutSubmissionAttribute() throws Exception { String json = mapper.writerWithView(Views.Publish.class).writeValueAsString(formContainer); JsonNode formJson = mapper.readTree(json); assertNull("Should not have fd:submit at top level", formJson.get("properties").get("fd:submit")); - Utils.testJSONExport(formContainer, - Utils.getTestExporterJSONPath(BASE, "withoutSubmissionAttribute")); + Utils.testJSONExport(formContainer, Utils.getTestExporterJSONPath(BASE, "withoutSubmissionAttribute")); } @Test @@ -884,12 +906,13 @@ public void testActionForCCFormRestSubmission() throws Exception { @Test void testExcludeFromDoRIfHiddenFromViewPrint() throws Exception { // Setup: create a resource structure with fd:view/print child and excludeFromDoRIfHidden property - context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, - "sling:resourceType", "core/fd/components/form/container/v2/container"); - context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN + "/fd:view/print", - "excludeFromDoRIfHidden", true); + context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, "sling:resourceType", + "core/fd/components/form/container/v2/container"); + context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN + "/fd:view/print", "excludeFromDoRIfHidden", + true); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, + FormContainer.class, context); Map dorProperties = ((FormContainerImpl) formContainer).getDorProperties(); assertTrue(dorProperties.containsKey("fd:excludeFromDoRIfHidden")); assertEquals(true, dorProperties.get("fd:excludeFromDoRIfHidden")); @@ -898,12 +921,13 @@ void testExcludeFromDoRIfHiddenFromViewPrint() throws Exception { @Test void testExcludeFromDoRIfHiddenFromViewPrintFalse() throws Exception { // Setup: create a resource structure with fd:view/print child and excludeFromDoRIfHidden property set to false - context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, - "sling:resourceType", "core/fd/components/form/container/v2/container"); - context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN + "/fd:view/print", - "excludeFromDoRIfHidden", false); + context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, "sling:resourceType", + "core/fd/components/form/container/v2/container"); + context.create().resource(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN + "/fd:view/print", "excludeFromDoRIfHidden", + false); - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, FormContainer.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_EXCLUDE_FROM_DOR_IF_HIDDEN, + FormContainer.class, context); Map dorProperties = ((FormContainerImpl) formContainer).getDorProperties(); assertTrue(dorProperties.containsKey("fd:excludeFromDoRIfHidden")); assertEquals(false, dorProperties.get("fd:excludeFromDoRIfHidden")); @@ -911,7 +935,8 @@ void testExcludeFromDoRIfHiddenFromViewPrintFalse() throws Exception { @Test void testJSONExportWithFragment() throws Exception { - FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITH_FRAGMENT, FormContainerImpl.class, context); + FormContainer formContainer = Utils.getComponentUnderTest(PATH_FORM_WITH_FRAGMENT, FormContainerImpl.class, + context); Utils.testJSONExport(formContainer, Utils.getTestExporterJSONPath(BASE, PATH_FORM_WITH_FRAGMENT)); } @@ -931,4 +956,12 @@ void testSetLang() throws Exception { formContainer.setLang(null); assertEquals(formContainer.getLang(), "en"); } + + @Test + void testJcrAuthoringSchemaCompliance() { + context.currentResource(PATH_FORM_FULL); + Resource resource = context.currentResource(); + assertNotNull("Full formcontainer fixture must exist at " + PATH_FORM_FULL, resource); + Utils.testJcrSchemaValidation(resource, "/authoring-schema/components/formcontainer.authoring.schema.yaml"); + } } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java index e62908a127..9a44c4dbbc 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v2/form/TitleImplV2Test.java @@ -182,12 +182,13 @@ void testTitleWithWcmEditMode() throws Exception { void testTitleWithLocale() throws Exception { context.currentResource(PATH_TITLE); // added this since AF API expects this to be present - GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, Mockito.mock( - GuideLocalizationService.class)); + GuideLocalizationService guideLocalizationService = context.registerService(GuideLocalizationService.class, + Mockito.mock(GuideLocalizationService.class)); Mockito.when(guideLocalizationService.getSupportedLocales()).thenReturn(new String[] { "en", "de" }); - MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context.getService(ResourceBundleProvider.class); - MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider.getResourceBundle( - "/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); + MockResourceBundleProvider bundleProvider = (MockResourceBundleProvider) context + .getService(ResourceBundleProvider.class); + MockResourceBundle resourceBundle = (MockResourceBundle) bundleProvider + .getResourceBundle("/content/dam/formsanddocuments/demo/jcr:content/dictionary", new Locale("de")); resourceBundle.putAll(new HashMap() { { put("guideContainer##title##text##5648", "Title"); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java index 30aff48d5c..4f5fdf9c1f 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/models/v3/form/FileInputImplV3Test.java @@ -59,7 +59,8 @@ public class FileInputImplV3Test { private static final String PATH_FILEINPUT = CONTENT_ROOT + "/fileinput"; private static final String PATH_FILEINPUT_DATALAYER = CONTENT_ROOT + "/fileinput-datalayer"; private static final String PATH_MULTISELECT_FILEINPUT = CONTENT_ROOT + "/multiselect-fileinput"; - private static final String PATH_MULTISELECT_FILEINPUT_WITHNOTYPE = CONTENT_ROOT + "/multiselect-fileinput-withNoType"; + private static final String PATH_MULTISELECT_FILEINPUT_WITHNOTYPE = CONTENT_ROOT + + "/multiselect-fileinput-withNoType"; private final AemContext context = FormsCoreComponentTestContext.newAemContext(); @@ -85,7 +86,8 @@ void testFieldType() { @Test void testType() { - FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITHNOTYPE, FileInput.class, context); + FileInput fileInput = Utils.getComponentUnderTest(PATH_MULTISELECT_FILEINPUT_WITHNOTYPE, FileInput.class, + context); assertEquals(fileInput.getType(), fileInput.getType()); } diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServletTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServletTest.java index 92172d7133..39aea621f6 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServletTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/FormMetaDataDataSourceServletTest.java @@ -95,8 +95,8 @@ public void testDataSource() throws Exception { // set expression resolver mock Utils.setInternalState(dataSourceServlet, "expressionResolver", expressionResolver); dataSourceServlet.doGet(context.request(), context.response()); - DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request().getAttribute( - DataSource.class.getName()); + DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request() + .getAttribute(DataSource.class.getName()); assertNotNull(dataSource); Resource resource = dataSource.iterator().next(); assertEquals("Form Action", resource.getValueMap().get(PN_TEXT, String.class)); @@ -118,8 +118,8 @@ public void testDataSourceForPrefillActionsAddsDefaultNoneOption() throws Except // set expression resolver mock Utils.setInternalState(dataSourceServlet, "expressionResolver", expressionResolver); dataSourceServlet.doGet(context.request(), context.response()); - DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request().getAttribute( - DataSource.class.getName()); + DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request() + .getAttribute(DataSource.class.getName()); assertNotNull(dataSource); Iterator iterator = dataSource.iterator(); Resource defaultNoneOption = iterator.next(); @@ -136,16 +136,16 @@ public void testDataSourceForFormattersForNumberInput() throws Exception { context.currentResource("/apps/formattertypedatasourcenumberinput"); when(expressionResolver.resolve(any(), any(), any(), any(SlingHttpServletRequest.class))) .then(returnsFirstArg()); - ContentPolicy contentPolicyMock = new MockContentPolicy(context.resourceResolver().getResource( - "/apps/formattertypedatasourcenumberinputPolicy")); + ContentPolicy contentPolicyMock = new MockContentPolicy( + context.resourceResolver().getResource("/apps/formattertypedatasourcenumberinputPolicy")); when(contentPolicyManagerMock.getPolicy(any(Resource.class))).thenReturn(contentPolicyMock); context.request().setAttribute(Value.CONTENTPATH_ATTRIBUTE, "/apps/formattertypedatasourcenumberinput"); FormMetaDataDataSourceServlet dataSourceServlet = new FormMetaDataDataSourceServlet(); // set expression resolver mock Utils.setInternalState(dataSourceServlet, "expressionResolver", expressionResolver); dataSourceServlet.doGet(context.request(), context.response()); - DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request().getAttribute( - DataSource.class.getName()); + DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request() + .getAttribute(DataSource.class.getName()); assertNotNull(dataSource); int size = 0; Iterator iterator = dataSource.iterator(); @@ -162,16 +162,16 @@ public void testDataSourceForLangForNumberInput() throws Exception { context.currentResource("/apps/langtypedatasourcenumberinput"); when(expressionResolver.resolve(any(), any(), any(), any(SlingHttpServletRequest.class))) .then(returnsFirstArg()); - ContentPolicy contentPolicyMock = new MockContentPolicy(context.resourceResolver().getResource( - "/apps/langtypedatasourcenumberinputPolicy")); + ContentPolicy contentPolicyMock = new MockContentPolicy( + context.resourceResolver().getResource("/apps/langtypedatasourcenumberinputPolicy")); when(contentPolicyManagerMock.getPolicy(any(Resource.class))).thenReturn(contentPolicyMock); context.request().setAttribute(Value.CONTENTPATH_ATTRIBUTE, "/apps/langtypedatasourcenumberinput"); FormMetaDataDataSourceServlet dataSourceServlet = new FormMetaDataDataSourceServlet(); // set expression resolver mock Utils.setInternalState(dataSourceServlet, "expressionResolver", expressionResolver); dataSourceServlet.doGet(context.request(), context.response()); - DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request().getAttribute( - DataSource.class.getName()); + DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) context.request() + .getAttribute(DataSource.class.getName()); assertNotNull(dataSource); int size = 0; Iterator iterator = dataSource.iterator(); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServletTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServletTest.java index 2bcc46b70d..b8c009d1c5 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServletTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/internal/servlets/ReviewDataSourceServletTest.java @@ -74,10 +74,8 @@ public Map filterProperties(Map map) { @Override public Iterable filterChildResources(Iterable childResources) { - return StreamSupport - .stream(childResources.spliterator(), false) - .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())) - .collect(Collectors.toList()); + return StreamSupport.stream(childResources.spliterator(), false) + .filter(r -> !IGNORED_NODE_NAMES.contains(r.getName())).collect(Collectors.toList()); } }); } @@ -92,7 +90,8 @@ public void testDoGet() { MockRequestPathInfo mockRequestPathInfo = (MockRequestPathInfo) request.getRequestPathInfo(); mockRequestPathInfo.setSuffix(componentInstancePath); reviewDataSourceServlet.doGet(request, response); - DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) request.getAttribute(DataSource.class.getName()); + DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) request + .getAttribute(DataSource.class.getName()); assertNotNull(dataSource); Resource resource = dataSource.iterator().next(); assertEquals("Item 1", resource.getValueMap().get("text", String.class)); @@ -110,7 +109,8 @@ public void testFormContainerNull() { MockRequestPathInfo mockRequestPathInfo = (MockRequestPathInfo) request.getRequestPathInfo(); mockRequestPathInfo.setSuffix(componentInstancePath2); reviewDataSourceServlet.doGet(request, response); - DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) request.getAttribute(DataSource.class.getName()); + DataSource dataSource = (com.adobe.granite.ui.components.ds.DataSource) request + .getAttribute(DataSource.class.getName()); assertNotNull(dataSource); assertFalse(dataSource.iterator().hasNext()); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImplTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImplTest.java index e6be355f12..357a8a8a41 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImplTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/AbstractFormComponentImplTest.java @@ -90,21 +90,24 @@ public void testNoRule() { @Test public void testNoValidationStatusRule() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass(PATH_COMPONENT_WITH_NO_VALIDATION_STATUS); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass( + PATH_COMPONENT_WITH_NO_VALIDATION_STATUS); Map properties = abstractFormComponentImpl.getProperties(); assertNull(properties.get("fd:rules")); } @Test public void testInvalidValidationStatusRuleNotInPublish() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass(PATH_COMPONENT_WITH_INVALID_VALIDATION_STATUS); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass( + PATH_COMPONENT_WITH_INVALID_VALIDATION_STATUS); Map properties = abstractFormComponentImpl.getProperties(); assertNull(properties.get("fd:rules"), "fd:rules should not appear in publish mode"); } @Test public void testValidRuleInAuthorMode() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode(PATH_COMPONENT_WITH_VALID_RULE); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode( + PATH_COMPONENT_WITH_VALID_RULE); Map properties = abstractFormComponentImpl.getProperties(); Map rulesProperties = (Map) properties.get("fd:rules"); assertNotNull(rulesProperties, "fd:rules should appear in author mode"); @@ -113,7 +116,8 @@ public void testValidRuleInAuthorMode() { @Test public void testInvalidRuleInAuthorMode() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode(PATH_COMPONENT_WITH_INVALID_RULE); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode( + PATH_COMPONENT_WITH_INVALID_RULE); Map properties = abstractFormComponentImpl.getProperties(); Map rulesProperties = (Map) properties.get("fd:rules"); assertNotNull(rulesProperties, "fd:rules should appear in author mode"); @@ -122,14 +126,16 @@ public void testInvalidRuleInAuthorMode() { @Test public void testNoRuleInAuthorMode() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode(PATH_COMPONENT_WITH_NO_RULE); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode( + PATH_COMPONENT_WITH_NO_RULE); Map properties = abstractFormComponentImpl.getProperties(); assertNull(properties.get("fd:rules"), "fd:rules should not appear when no fd:rules node exists"); } @Test public void testInvalidValidationStatusInAuthorMode() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode(PATH_COMPONENT_WITH_INVALID_VALIDATION_STATUS); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode( + PATH_COMPONENT_WITH_INVALID_VALIDATION_STATUS); Map properties = abstractFormComponentImpl.getProperties(); Map rulesProperties = (Map) properties.get("fd:rules"); assertNotNull(rulesProperties, "fd:rules should appear in author mode even with invalid status"); @@ -138,7 +144,8 @@ public void testInvalidValidationStatusInAuthorMode() { @Test public void testRulesExcludedWhenPublishViewAttributeSetOnAuthor() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode(PATH_COMPONENT_WITH_VALID_RULE); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClassWithAuthorMode( + PATH_COMPONENT_WITH_VALID_RULE); context.request().setAttribute(FormConstants.REQ_ATTR_PUBLISH_VIEW, Boolean.TRUE); Map properties = abstractFormComponentImpl.getProperties(); assertNull(properties.get("fd:rules"), @@ -152,13 +159,13 @@ public void testIsAuthorModeUtility() { WCMMode.EDIT.toRequest(context.request()); assertTrue(ComponentUtils.isAuthorMode(context.request()), "EDIT mode should be author mode"); context.request().setAttribute(FormConstants.REQ_ATTR_PUBLISH_VIEW, Boolean.TRUE); - assertFalse(ComponentUtils.isAuthorMode(context.request()), - "publish view attribute should override WCMMode"); + assertFalse(ComponentUtils.isAuthorMode(context.request()), "publish view attribute should override WCMMode"); } @Test public void testDisabledXFAScripts() { - AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass(PATH_COMPONENT_WITH_DISABLED_XFA_SCRIPTS); + AbstractFormComponentImpl abstractFormComponentImpl = prepareTestClass( + PATH_COMPONENT_WITH_DISABLED_XFA_SCRIPTS); Map properties = abstractFormComponentImpl.getProperties(); List disabledScripts = (List) properties.get("fd:disabledXfaScripts"); assertNotNull(disabledScripts); @@ -216,7 +223,8 @@ public Page getCurrentPageToTest() { request.setAttribute(FormConstants.REQ_ATTR_REFERENCED_PATH, AF_PATH); initMethod.invoke(abstractComponentImpl); Page newCurrentPage = abstractComponentImpl.getCurrentPageToTest(); - assertEquals(afPage.getPath(), newCurrentPage.getPath(), "Page should be set to AF page instead of sites page."); + assertEquals(afPage.getPath(), newCurrentPage.getPath(), + "Page should be set to AF page instead of sites page."); // If requested page is forms Page page2 = Mockito.mock(Page.class); diff --git a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java index d63329bf16..092f741cd5 100644 --- a/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java +++ b/bundles/af-core/src/test/java/com/adobe/cq/forms/core/components/util/ComponentUtilsTest.java @@ -179,8 +179,7 @@ public void testSubmitActionsCaching() throws Exception { // Configure mock response when(mockStatusLine.getStatusCode()).thenReturn(200); when(mockResponse.getStatusLine()).thenReturn(mockStatusLine); - when(mockResponse.getEntity()).thenReturn( - new StringEntity("{\"supported\":[\"spreadsheet\",\"email\"]}")); + when(mockResponse.getEntity()).thenReturn(new StringEntity("{\"supported\":[\"spreadsheet\",\"email\"]}")); // Wire up mock chain when(mockClientFactory.newBuilder()).thenReturn(mockHttpClientBuilder); diff --git a/bundles/af-core/src/test/resources/form/checkbox/test-content.json b/bundles/af-core/src/test/resources/form/checkbox/test-content.json index 778507bcac..45b872760b 100644 --- a/bundles/af-core/src/test/resources/form/checkbox/test-content.json +++ b/bundles/af-core/src/test/resources/form/checkbox/test-content.json @@ -94,6 +94,16 @@ "jcr:primaryType": "nt:unstructured" } }, + "checkbox-enableUncheckedValueAbsent" : { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType" : "core/fd/components/form/checkbox/v1/checkbox", + "name" : "abc", + "jcr:title" : "def", + "type" : "string", + "checkedValue": "on", + "uncheckedValue": "off", + "fieldType": "checkbox" + }, "checkbox-without-fieldtype" : { "id": "checkbox-wo-fieldtype1", "jcr:primaryType": "nt:unstructured", diff --git a/bundles/af-core/src/test/resources/form/formcontainer/test-content.json b/bundles/af-core/src/test/resources/form/formcontainer/test-content.json index fe619539fb..33bc760557 100644 --- a/bundles/af-core/src/test/resources/form/formcontainer/test-content.json +++ b/bundles/af-core/src/test/resources/form/formcontainer/test-content.json @@ -25,6 +25,38 @@ "customProp": "customPropValue" } }, + "formcontainerv2-full": { + "jcr:primaryType": "nt:unstructured", + "sling:resourceType": "core/fd/components/form/container/v2/container", + "fieldType": "form", + "name": "myForm", + "id": "myForm-id", + "visible": true, + "enabled": true, + "description": "A fully-populated form container for authoring schema validation", + "tooltip": "Fill in all fields", + "tooltipVisible": false, + "lang": "en-US", + "fd:viewType": "form", + "fd:enableAutoSave": true, + "fd:autoSaveStrategyType": "time", + "fd:autoSaveInterval": 30, + "actionType": "com.adobe.aemds.guide.service.impl.actions.SubmitToRestEndPoint", + "actionName": "restEndpoint", + "mailto": "recipient@example.com", + "from": "sender@example.com", + "subject": "Form submission", + "cc": "cc@example.com", + "bcc": "bcc@example.com", + "spreadsheetUrl": "https://example.com/spreadsheet", + "thankYouOption": "message", + "thankYouMessage": "Thank you for your submission", + "thankyouMessage": "Thank you (v1)", + "redirect": "/content/thank-you", + "prefillService": "guideFormPrefillService", + "specVersion": "0.15.2", + "clientLibRef": "myApp.forms.clientlib" + }, "formcontainerv2WithoutPrefill": { "jcr:primaryType": "nt:unstructured", "sling:resourceType" : "core/fd/components/form/container/v2/container", diff --git a/bundles/af-core/src/test/resources/form/termsandconditions/exporter-termsandconditions.json b/bundles/af-core/src/test/resources/form/termsandconditions/exporter-termsandconditions.json index a8017f9c3d..135c166a6d 100644 --- a/bundles/af-core/src/test/resources/form/termsandconditions/exporter-termsandconditions.json +++ b/bundles/af-core/src/test/resources/form/termsandconditions/exporter-termsandconditions.json @@ -26,7 +26,6 @@ "fieldType": "plain-text", "name": "consenttext", "value": "Text related to the terms and conditions come here", - "richText": false, "events": { "custom:setProperty": [ "$event.payload" diff --git a/bundles/af-core/src/test/resources/form/text/exporter-text-datalayer.json b/bundles/af-core/src/test/resources/form/text/exporter-text-datalayer.json index ced8c2ac52..01205ff719 100644 --- a/bundles/af-core/src/test/resources/form/text/exporter-text-datalayer.json +++ b/bundles/af-core/src/test/resources/form/text/exporter-text-datalayer.json @@ -3,7 +3,6 @@ "fieldType": "plain-text", "name": "text1680491190398", "value": "This is an AF", - "richText": false, "events": { "custom:setProperty": [ "$event.payload" diff --git a/bundles/af-core/src/test/resources/form/text/exporter-text-with-viewtype.json b/bundles/af-core/src/test/resources/form/text/exporter-text-with-viewtype.json index c9c338ee3b..30459b8d8b 100644 --- a/bundles/af-core/src/test/resources/form/text/exporter-text-with-viewtype.json +++ b/bundles/af-core/src/test/resources/form/text/exporter-text-with-viewtype.json @@ -2,7 +2,6 @@ "id": "text-2c82909883", "fieldType": "plain-text", "name": "abc", - "richText": false, "properties": { "fd:path": "/content/text-with-viewtype" }, diff --git a/bundles/af-core/src/test/resources/form/text/exporter-text.json b/bundles/af-core/src/test/resources/form/text/exporter-text.json index 4243f7d3dd..1aa1ef4bc7 100644 --- a/bundles/af-core/src/test/resources/form/text/exporter-text.json +++ b/bundles/af-core/src/test/resources/form/text/exporter-text.json @@ -1,7 +1,6 @@ { "id": "text-ac0bcff4f3", "fieldType": "plain-text", - "richText": false, "name": "abc", ":type": "core/fd/components/form/text/v1/text", "properties": { diff --git a/docs/authoring-schema/ADR-001-authoring-schema-rationale.md b/docs/authoring-schema/ADR-001-authoring-schema-rationale.md new file mode 100644 index 0000000000..f5a977fdc3 --- /dev/null +++ b/docs/authoring-schema/ADR-001-authoring-schema-rationale.md @@ -0,0 +1,174 @@ +# ADR-001: JCR Authoring Schema for Adaptive Forms v2 + +**Status:** Accepted +**Date:** 2026-03-19 +**Authors:** AEM Core Forms Components team + +--- + +## Context + +AEM Forms AF2 already has two schema layers: + +1. **CRISPR / Runtime form spec** — the canonical JSON format that AEM Forms' generation + pipelines, GenAI tooling (Forms Experience Builder), and AFCS conversion tools produce and + consume. Owned by the AEM Forms AF2 + GenAI squad. The CRISPR spec validates the final AF2 + JSON model that the runtime reads — it validates _after_ generation/transformation. + +2. **Sling models (AbstractFormComponentImpl, AbstractFieldImpl, …)** — Java classes that read + JCR properties and produce the CRISPR-compatible JSON at request time. They are the bridge + between JCR content and the runtime, but they contain no declarative schema that tooling can + consume. + +There was no schema layer for **what gets written to JCR** by the Edit Dialog, Content API, or +any programmatic content-creation tool. This ADR documents the decision to introduce one. + +--- + +## Decision + +Introduce a set of JSON Schema (Draft-7) YAML files — the **JCR Authoring Schema** — that +describe what properties a valid AF2 component node in JCR may contain. These schemas live in +`docs/authoring-schema/` inside `aem-core-forms-components` and are validated by +`scripts/content_api_forms.py`. + +The JCR Authoring Schema is **complementary to CRISPR, not a replacement**. CRISPR validates the +runtime form spec; the authoring schema validates what is written to JCR at authoring time. +Together they cover the full lifecycle. + +--- + +## Why a New Schema Layer and Not Just CRISPR + +### 1. Different Validation Points in the Lifecycle + +CRISPR/runtime schema validates at **generation / transformation time**: it is the contract that +generation pipelines (XFA → AF2, PDF → AF2) and GenAI tooling must produce. It says nothing +about how that content is stored in JCR or what an Edit Dialog is allowed to write. + +The authoring schema validates at **write time**: when an author saves a dialog, when the +Content API submits a payload, or when a migration script creates component nodes. Without this +layer there is no machine-checkable contract for JCR writes. + +### 2. AEM Sites Embedded Forms (Edit Dialog → JCR) + +When a form is embedded in an AEM Sites page, content authors use the Granite Edit Dialog to +configure each component. The dialog writes directly to JCR. There is no CRISPR pipeline +involved. The authoring schema is the only schema that can validate this authoring path. + +### 3. Content API Validation (`POST /adobe/pages`, `PATCH /content/…`) + +The AEM Content API (`aem-headless-client` / Sites Content API) creates and mutates content by +writing JCR properties directly. The `scripts/content_api_forms.py` tool uses the authoring +schema to: +- validate payloads **before** submitting them, catching bad property names or wrong types + before they reach the server; +- validate round-trip: re-read the node after PATCH and confirm what was written matches the + schema. + +CRISPR cannot serve this role because it models the runtime output (after Sling rendering), not +the raw JCR input. + +### 4. Authoring-Only Properties That Do Not Exist in CRISPR + +Several JCR properties exist only at authoring time and are either filtered out by Sling models +(`@JsonIgnore`) or are never forwarded to the runtime JSON at all. CRISPR has no entry for them. +The authoring schema must document and validate them: + +| JCR Property | Where It Is Used | Why CRISPR Has No Entry | +|---|---|---| +| `fd:channel` | `AbstractComponentImpl` — propagated to children for print vs. web channel selection | `@JsonIgnore`; never appears in runtime JSON | +| `langDisplayValue` | Language display label stored in JCR | No public JSON getter; not serialised | +| `fd:rules/fd:click`, `fd:rules/fd:validate`, `fd:rules/fd:valueCommit`, `fd:rules/fd:formReady`, `fd:rules/fd:layoutReady`, `fd:rules/fd:docReady`, `fd:rules/fd:calc`, `fd:rules/fd:init`, `fd:rules/fd:indexChange` | Visual Rule Editor AST blobs (String[]) — written by the rule editor UI, read back by the rule editor UI | AF2 runtime ignores these keys; only the plain rule expressions (category A) in `fd:rules` reach the runtime `"rules"` key | +| `fd:rules/validationStatus` | Rule editor validity marker (`"none"` / `"valid"` / `"invalid"`) — set by the rule editor UI | Purely an authoring-time UI state flag; never in runtime JSON | +| `textIsRich` (`PN_TEXT_IS_RICH`) | Text component — flags whether static text is HTML rich text | Stored as `textIsRich` in JCR but exposed as `richText` in runtime JSON via `@JsonProperty`; CRISPR knows only `richText`, not `textIsRich` | + +### 5. Two JCR Properties That Derive One Runtime/CRISPR Property + +A concrete example of the authoring ↔ runtime mismatch: the CRISPR/runtime schema defines +`exclusiveMinimum` and `exclusiveMaximum` as a single typed value: + +```yaml +# af2-docs/schema/adaptive-form-data-constraints.schema.yaml (CRISPR / runtime) +exclusiveMinimum: + oneOf: + - type: string + format: date # for DatePicker + - type: number # for NumberInput / TextInput +``` + +At the JCR authoring layer this **one runtime property** is composed from **two separate JCR +properties**: + +| JCR Property | Type | Meaning | +|---|---|---| +| `exclusiveMinimum` | `boolean` (default `false`) | Flag: is the minimum exclusive? | +| `minimum` / `minimumDate` | `number` / `Date` | The actual minimum value | + +The Sling model (`DatePickerImpl`, `TextInputImpl`, `NumberInputImpl`) combines them at request +time via `ComponentUtils.getExclusiveValue(exclusiveMinimum_flag, value, legacyExcludeFlag)` and +emits a single typed `exclusiveMinimum` in the JSON output. The same pattern applies to +`exclusiveMaximum` / `maximum` / `maximumDate`. + +Without the authoring schema there is no documentation or validation of this mapping. A Content +API client writing `"exclusiveMinimum": "2024-01-01"` to JCR would store data in a format the +Sling model cannot read. The authoring schema catches this. + +### 6. JCR Storage Quirks Not Modelled in CRISPR + +CRISPR models clean property names. JCR imposes restrictions that the authoring schema must +document: + +- **Custom events use underscores instead of colons**: the runtime `events` object uses + `"custom:foo"` as the event name, but JCR cannot store a property named `custom:foo`. The + authoring schema documents that `custom_foo` is stored in the `fd:events` child node and + renamed at read time. +- **Boolean / String coercion**: some Granite dialog components write booleans as JCR Strings + (`"true"` / `"false"`). The authoring schema captures both as `type: [boolean, string]` so + validators accept both forms. +- **Child nodes vs. flat properties**: `fd:rules` and `fd:events` are JCR child nodes of the + component node, not flat properties. CRISPR sees only the rendered `rules` and `events` keys in + the JSON output. The authoring schema documents the two-level JCR structure explicitly. + +### 7. Migration and Tooling Safety + +Any script that creates or modifies AF2 component nodes in bulk (content migrations, the Content +API tool, import scripts) can validate its payloads against the authoring schema before applying +them. Running the same payload through CRISPR validation would require a full Sling render cycle; +running it against the authoring schema requires only a JSON Schema check. + +--- + +## Limitations + +### Does Not Apply to Document Authoring (DA) + +Document Authoring uses Microsoft Word / Google Docs as the authoring surface and a different +content model (blocks / UE data attributes). There is no JCR Edit Dialog involved. The authoring +schema does not apply to DA-based forms. + +### Does Not Replace Runtime Validation + +The authoring schema validates JCR-layer content; it does not guarantee the rendered AF2 JSON +model is valid. End-to-end correctness still requires: +1. Authoring schema check (this work) — validates JCR write. +2. Sling model rendering — transforms JCR → JSON. +3. CRISPR / runtime schema check — validates the rendered JSON. + +### Draft-7 `allOf` Limitation + +JSON Schema Draft-7 `additionalProperties` does not traverse `allOf` / `$ref` chains. Strict +`additionalProperties: false` is only enforced in the flattened JSON schemas under +`bundles/af-core/src/test/resources/authoring-schema/`. Upgrading the YAML source files to +Draft-2019-09 and using `unevaluatedProperties: false` is the long-term path to strict-mode +enforcement in the YAML layer. + +--- + +## Consequences + +- Tooling (Content API scripts, migration scripts) can validate JCR payloads before submission. +- Edit Dialog changes must be reflected in the authoring schema to stay in sync. +- The schema serves as living documentation for the JCR ↔ runtime property mapping, including + the two-JCR-property-to-one-runtime-property derivations described above. +- DA-based forms are out of scope and require a separate validation approach if needed in future. diff --git a/docs/authoring-schema/README.md b/docs/authoring-schema/README.md new file mode 100644 index 0000000000..48a3393111 --- /dev/null +++ b/docs/authoring-schema/README.md @@ -0,0 +1,55 @@ +# Authoring Schema + +This directory contains YAML-based JSON Schema Draft 7 files documenting +the JCR properties that the Edit Dialog writes for each Adaptive Form +component and that the corresponding Sling Model consumes. + +## Why separate from af2-docs schema? + +`af2-docs/schema/` describes the **runtime JSON model** that the AF2 runtime +receives. This directory describes the **JCR authoring layer** — what an AEM +author actually stores in the content repository. + +## Structure + +``` +docs/authoring-schema/ +├── base.authoring.schema.yaml # All components (AbstractFormComponentImpl + AbstractBaseImpl) +├── field.authoring.schema.yaml # All field/leaf components (AbstractFieldImpl) +├── container.authoring.schema.yaml # Panel/container components +└── components/ + ├── textinput.authoring.schema.yaml + ├── dropdown.authoring.schema.yaml + └── ... # One file per component +``` + +## Reading the schemas + +Each property entry includes: +- **type** — JSON Schema / JCR type +- **title** — human-readable property name as shown in the dialog +- **description** — behavior notes including JCR property name (e.g. `fd:emptyValue`) +- **default** — value used when the property is absent from the JCR node +- **enum** (where applicable) — allowed values + +## Child nodes + +`fd:rules` and `fd:events` are JCR child nodes, not flat properties. They appear +in the base schema under those keys with documentation of their internal structure. + +- **`fd:rules`**: contains runtime rule expressions (String), visual rule editor AST (String[]), and rule editor metadata (`validationStatus`). The web runtime only reads the plain property-name keys (visible, required, etc.). +- **`fd:events`**: contains event handler expressions. Keys are event names (click, change, etc.); values are String or String[]. Custom events use `custom_eventName` in JCR (renamed to `custom:eventName` at read time). + +## Type mapping + +| JCR Type | JSON Schema type | +|------------|---------------------| +| Boolean | boolean | +| String | string | +| String[] | array of string | +| Long | integer | +| Double | number | +| Date | string (date-time) | + +> **Note**: Legacy JCR content may store Boolean properties (e.g. `required`, `hideTitle`, +> `dorExclusion`) as String `"true"`/`"false"`. Sling auto-coerces these transparently. diff --git a/docs/authoring-schema/adaptive-form-component.authoring.schema.yaml b/docs/authoring-schema/adaptive-form-component.authoring.schema.yaml new file mode 100644 index 0000000000..8a1b55a330 --- /dev/null +++ b/docs/authoring-schema/adaptive-form-component.authoring.schema.yaml @@ -0,0 +1,233 @@ +$id: adaptive-form-component.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Adaptive Form Component JCR Authoring Schema (Root) +description: >- + Root schema for validating any Adaptive Form component's JCR node. + Uses oneOf discriminated by the fieldType property to select the + correct per-component schema for validation. + + Usage: validate any component's JCR ValueMap (as JSON) against this schema. + The correct component schema is selected based on the fieldType value + combined with fd:viewType where needed (e.g. image, signature/scribble). + + NOTE: each branch uses else: false so that non-matching branches fail + (required for oneOf semantics — without else, a false if is trivially valid, + causing all N-1 non-matching branches to also pass and breaking oneOf). + +oneOf: + - title: form (container) + if: + properties: + fieldType: + const: form + then: + $ref: ./components/formcontainer.authoring.schema.yaml + else: false + + - title: text-input + if: + properties: + fieldType: + const: text-input + "fd:viewType": + not: + const: signature + then: + $ref: ./components/textinput.authoring.schema.yaml + else: false + + - title: multiline-input + if: + properties: + fieldType: + const: multiline-input + then: + $ref: ./components/textinput.authoring.schema.yaml + else: false + + - title: email + if: + properties: + fieldType: + const: email + then: + $ref: ./components/emailinput.authoring.schema.yaml + else: false + + - title: tel + if: + properties: + fieldType: + const: tel + then: + $ref: ./components/telephoneinput.authoring.schema.yaml + else: false + + - title: number-input + if: + properties: + fieldType: + const: number-input + then: + $ref: ./components/numberinput.authoring.schema.yaml + else: false + + - title: date-input + if: + properties: + fieldType: + const: date-input + then: + $ref: ./components/datepicker.authoring.schema.yaml + else: false + + - title: datetime-input + if: + properties: + fieldType: + const: datetime-input + then: + $ref: ./components/datetime.authoring.schema.yaml + else: false + + - title: file-input + if: + properties: + fieldType: + const: file-input + "fd:viewType": + not: + const: signature + then: + $ref: ./components/fileinput.authoring.schema.yaml + else: false + + - title: scribble (signature) + if: + required: ["fd:viewType"] + properties: + "fd:viewType": + const: signature + then: + $ref: ./components/scribble.authoring.schema.yaml + else: false + + - title: drop-down + if: + properties: + fieldType: + const: drop-down + then: + $ref: ./components/dropdown.authoring.schema.yaml + else: false + + - title: radio-group + if: + properties: + fieldType: + const: radio-group + then: + $ref: ./components/radiobutton.authoring.schema.yaml + else: false + + - title: checkbox-group + if: + properties: + fieldType: + const: checkbox-group + then: + $ref: ./components/checkboxgroup.authoring.schema.yaml + else: false + + - title: checkbox + if: + properties: + fieldType: + const: checkbox + then: + $ref: ./components/checkbox.authoring.schema.yaml + else: false + + - title: switch + if: + properties: + fieldType: + const: switch + then: + $ref: ./components/switch.authoring.schema.yaml + else: false + + - title: image + if: + properties: + fieldType: + const: image + then: + $ref: ./components/image.authoring.schema.yaml + else: false + + - title: button + if: + properties: + fieldType: + const: button + then: + $ref: ./components/button.authoring.schema.yaml + else: false + + - title: plain-text + if: + properties: + fieldType: + const: plain-text + then: + $ref: ./components/text.authoring.schema.yaml + else: false + + - title: text (alias for plain-text) + description: >- + Legacy/example fieldType="text" — same schema as plain-text. + Used by forms-components-examples and some older component implementations. + if: + properties: + fieldType: + const: text + then: + $ref: ./components/text.authoring.schema.yaml + else: false + + - title: panel + if: + properties: + fieldType: + const: panel + "fd:viewType": + not: + enum: [fragment, ""] + then: + $ref: ./components/panelcontainer.authoring.schema.yaml + else: false + + - title: fragment + if: + required: ["fd:viewType"] + properties: + "fd:viewType": + const: fragment + then: + $ref: ./components/fragment.authoring.schema.yaml + else: false + + - title: captcha + description: >- + All captcha variants (reCAPTCHA, hCaptcha, Turnstile). The captcha type is + determined by sling:resourceType — fd:viewType is NOT written to JCR for any + captcha component. The shared captcha schema covers common properties across + all three implementations. + if: + properties: + fieldType: + const: captcha + then: + $ref: ./components/captcha.authoring.schema.yaml + else: false diff --git a/docs/authoring-schema/base.authoring.schema.yaml b/docs/authoring-schema/base.authoring.schema.yaml new file mode 100644 index 0000000000..421e6257f0 --- /dev/null +++ b/docs/authoring-schema/base.authoring.schema.yaml @@ -0,0 +1,401 @@ +$id: base.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Base JCR Authoring Properties +description: >- + Properties common to ALL adaptive form components, derived from + AbstractFormComponentImpl and AbstractBaseImpl. These are written to + the component's JCR node by the Edit Dialog and consumed by Sling Models. +type: object + +# NOTE on JCR default-value persistence: +# Properties with a runtime default (true or false) do NOT need to be stored in JCR when +# they are at their default value. The Sling models use: +# @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) + @Nullable +# + @JsonInclude(JsonInclude.Include.NON_NULL) +# which means: absent from JCR → injected as null → omitted from JSON output → AF2 runtime +# applies its own built-in default. Persisting the default value bloats the node and the +# JSON model with no effect. +# +# Properties safe to OMIT when at their default: +# visible (default true), enabled (default true), +# hideTitle (default false), isTitleRichText (default false), +# tooltipVisible (default false), required (default false), +# repeatable (default false), unboundFormElement (default false), +# dorExclusion (default false), dorExcludeTitle (default false), +# dorExcludeDescription (default false), +# readOnly (default false — defined in field.authoring.schema.yaml) +# +# @Default properties (computation inputs, NOT serialized to JSON): +# exclusiveMinimum, exclusiveMaximum — @Default(false) in AbstractFieldImpl; used as +# computation inputs in DatePickerImpl.initDatePicker(); no public JSON getter. +# multiSelect — @Default(false) in DropDownImpl; isMultiSelect() is @JsonIgnore. +# multiLine — @Default(false) in TextInputImpl; isMultiLine() is @JsonIgnore. +# excludeMinimum, excludeMaximum — @Default(false) in DatePickerImpl; computation only. +# All of these are safe to omit from JCR when false — they will NOT appear in JSON output +# regardless, because their getters are @JsonIgnore or have no public JSON getter. +# +# Exception that WAS a bug (now fixed): textIsRich in TextImpl previously used +# @Default(false) causing "richText": false to always appear in JSON. Fixed by switching +# to @Nullable Boolean + @JsonInclude(NON_NULL) + separate getRichText() method. +# +# NOTE on additionalProperties enforcement: +# This schema uses draft-07. In draft-07, additionalProperties only considers +# properties/patternProperties defined in the SAME schema object — it does NOT +# "see through" allOf/$ref chains. Adding additionalProperties:false here would +# reject field-specific properties (readOnly, lazy, etc.) when components extend +# base via allOf, because base wouldn't see those in its own `properties` block. +# +# Strict-mode enforcement is implemented in the FLATTENED JSON schemas at: +# bundles/af-core/src/test/resources/authoring-schema/ +# Those schemas have all properties inlined (no allOf chains) and safely use +# additionalProperties:false + patternProperties for JCR-namespaced internals. +# +# To upgrade YAML schemas to strict mode, upgrade to JSON Schema draft-2019-09 +# and use unevaluatedProperties:false, which correctly traverses allOf graphs. +patternProperties: + "^jcr:": {} # jcr:primaryType, jcr:created, jcr:createdBy, jcr:lastModified, etc. + "^sling:": {} # sling:resourceType, sling:resourceSuperType + "^cq:": {} # cq:panelTitle, cq:editConfig, etc. + "^fd:": {} # fd:version, fd:translationIds, fd:rules, fd:events — documented in properties below + +properties: + # --- Identity & binding --- + name: + type: [string, object] + title: Field name / data key + description: >- + Submitted as data key unless overridden by dataRef. + Also accepts object — a JCR child node named "name" appears as an + object in infinity.json (naming collision with this property). + dataRef: + type: ["string", "null"] + title: Data binding JSON-path + description: >- + JSON-path of the data value this field binds to, relative to the parent's + dataRef. Use null to opt out of data binding. + id: + type: [string, object] + title: HTML id override + description: >- + Overrides the auto-generated component id. + Also accepts object — a JCR child node named "id" appears as an + object in infinity.json (naming collision with this property). + fieldType: + type: string + title: Widget field type + description: >- + Maps to the runtime fieldType. Usually hard-coded per component via + getFieldType() in the Sling model. + enum: + - text-input + - number-input + - date-input + - datetime-input + - file-input + - multiline-input + - drop-down + - radio-group + - checkbox-group + - checkbox + - switch + - plain-text + - text + - button + - panel + - image + - email + - captcha + - tel + - form + + # --- Visibility / Interaction --- + visible: + type: [boolean, string] + title: Visible + default: true + description: >- + Whether the field is visible on initial render. When absent from JCR the + Sling model returns null (JsonInclude.NON_NULL) and the AF2 runtime applies + its own default (true). Omit from JCR when true — absent property = runtime + default true. Only persist when explicitly set to false. + Note: some dialogs store as JCR String "true"/"false" — Sling auto-coerces. + enabled: + type: [boolean, string] + title: Enabled + default: true + description: >- + Whether the field is enabled. When absent from JCR the Sling model returns + null (JsonInclude.NON_NULL) and the runtime applies its own default (true). + Omit from JCR when true — absent property = runtime default true. Only + persist when explicitly set to false. + Disabled fields do not participate in rules but can still have custom events. + Note: some dialogs store as JCR String "true"/"false" — Sling auto-coerces. + + # --- Labels & Description --- + "jcr:title": + type: string + title: Field label + description: The visible label rendered next to the field. + hideTitle: + type: [boolean, string] + title: Hide label + default: false + description: >- + When true the label is hidden but still available to screen readers. + Omit from JCR when false — absent property = runtime default false. + isTitleRichText: + type: [boolean, string] + title: Label is rich text + default: false + description: Omit from JCR when false — absent property = runtime default false. + description: + type: [string, object] + title: Long description / help text + description: >- + Rendered as short/long description. Supports rich text. Used as help + text for individual fields or top-level description for panels. + Also accepts object — a JCR child node named "description" appears as + an object in infinity.json (naming collision with this property). + tooltip: + type: string + title: Tooltip text + description: Shown in a popover when the user clicks the question-mark icon. + tooltipVisible: + type: [boolean, string] + title: Show tooltip icon + default: false + description: Omit from JCR when false — absent property = runtime default false. + + # --- Data type --- + type: + title: Data type + description: >- + The data type this field captures. Coerced to this type on submit. + In some JCR content models, a child node may be named "type" — in that + case this property appears as an object in infinity.json output. Plain-text + components may also use heading-level variants ("h1"–"h6") here. + ButtonImpl stores HTML button type in this same JCR property name (PN_BUTTON_TYPE = "type"). + oneOf: + - type: string + enum: + - string + - number + - integer + - boolean + - float + - "string[]" + - "number[]" + - "boolean[]" + - file + - "file[]" + - object + - array + - button + - submit + - reset + - h1 + - h2 + - h3 + - h4 + - h5 + - h6 + - type: object + description: >- + A JCR child node that happens to be named "type" — appears as an object + in infinity.json output. The child node itself is validated separately via + patternProperties in container.authoring.schema.yaml. + + # --- Validation --- + required: + type: [boolean, string] + title: Required + default: false + description: >- + Whether a value is required. JCR may store as Boolean or String "true"/"false" + depending on the dialog component — Sling auto-coerces to Boolean transparently. + Omit from JCR when false — absent property = runtime default false. + mandatoryMessage: + type: string + title: Required constraint message + validationExpression: + type: string + title: Custom validation expression (json-formula) + description: A json-formula expression that returns true when the value is valid. + validateExpMessage: + type: string + title: Custom validation expression error message + + # --- Accessibility --- + assistPriority: + type: string + title: Assistive technology priority + description: Determines which text the screen reader announces for this field. + enum: [description, title, label, name, custom, caption] + custom: + type: string + title: Custom assistive text + description: Used when assistPriority is set to "custom". + + # --- Repeatability --- + repeatable: + type: [boolean, string] + title: Repeatable + default: false + description: Omit from JCR when false — absent property = runtime default false. + minOccur: + type: [integer, string] + title: Minimum occurrences (deprecated; prefer minItems) + description: JCR may store as Integer or String — Sling auto-coerces. + maxOccur: + type: [integer, string] + title: Maximum occurrences (deprecated; prefer maxItems) + description: JCR may store as Integer or String — Sling auto-coerces. + minItems: + type: [integer, string] + title: Minimum instances of a repeatable field/panel + description: JCR may store as Integer or String — Sling auto-coerces. + maxItems: + type: [integer, string] + title: Maximum instances of a repeatable field/panel + description: JCR may store as Integer or String — Sling auto-coerces. + minItemsMessage: + type: string + title: Min items constraint message + maxItemsMessage: + type: string + title: Max items constraint message + uniqueItemsMessage: + type: string + title: Unique items constraint message + + # --- DOR (Document of Record) --- + dorExclusion: + type: [boolean, string] + title: Exclude from DOR + default: false + description: >- + JCR may store as Boolean or String "true"/"false" — Sling auto-coerces. + Omit from JCR when false — absent property = runtime default false. + dorColspan: + type: string + title: DOR column span + description: >- + Stored as JCR String in AbstractFormComponentImpl (PN_DOR_COLSPAN). + dorBindRef: + type: string + title: DOR data binding ref + dorExcludeTitle: + type: [boolean, string] + title: Exclude title from DOR + default: false + description: Omit from JCR when false — absent property = runtime default false. + dorExcludeDescription: + type: [boolean, string] + title: Exclude description from DOR + default: false + description: Omit from JCR when false — absent property = runtime default false. + dorNumCols: + type: [integer, string] + title: DOR number of columns + dorLayoutType: + type: string + title: DOR layout type + dorTemplateRef: + type: string + title: DOR template path + dorType: + type: string + title: DOR type + "fd:formType": + type: string + title: DOR template type + + # --- Localization --- + lang: + type: string + title: Language for field formatting + description: >- + BCP 47 language tag (e.g. "en-US", "de-DE") used for date/number formatting. + langDisplayValue: + type: string + title: Language display value + + # --- Internal rendering --- + "fd:channel": + type: string + title: Rendering channel + description: >- + Internal property injected by AbstractComponentImpl (@JsonIgnore — not in JSON model output). + Propagated to children by AbstractContainerImpl for print vs. web rendering selection. + Authors do not typically set this directly. + + # ----------------------------------------------------------------------- + # CHILD NODES (not flat properties — stored as separate JCR nodes) + # These are read via resource.getChild(...) in AbstractFormComponentImpl + # ----------------------------------------------------------------------- + "fd:rules": + type: object + title: Rules child node + description: >- + A JCR child node named "fd:rules" directly under the component node. + Contains three categories of data: + (A) Runtime rule expressions (String, plain property-name keys) — returned by getRules() + and appear in the JSON model "rules" key. Valid keys: visible, required, enabled, + readOnly, value, label, enum, enumNames, minimum, maximum, exclusiveMinimum, + exclusiveMaximum, description. + (B) Visual rule editor AST (String[], fd:-prefixed keys) — written by the rule editor + UI, ignored by the web runtime model. Keys: fd:click, fd:validate, fd:valueCommit, + fd:format, fd:formReady, fd:layoutReady, fd:docReady, fd:calc, fd:init, fd:indexChange. + Values are arrays of JSON-encoded AST blobs. + (C) Rule editor metadata: validationStatus (String "none"|"valid"|"invalid"). + Do NOT document as a flat property — document as a child node. + properties: + validationStatus: + type: string + enum: ["none", "valid", "invalid"] + description: Internal rule editor validity marker. Written by the rule editor UI. + additionalProperties: + oneOf: + - type: string + description: A json-formula rule expression (category A — runtime rules). + - type: array + items: + type: string + description: JSON-encoded AST blob array (category B — visual rule editor, ignored by runtime). + + "fd:events": + type: object + title: Events child node + description: >- + A JCR child node named "fd:events" directly under the component node. + Each property inside is an event name to handler expression (String or String[]). + Valid event names: click, submit, initialize, load, change, submitSuccess, submitError. + Custom events are stored with underscores instead of colons (JCR restriction): + "custom:foo" is stored as "custom_foo" in JCR, renamed at read time. + Do NOT document as a flat property — document as a child node. + additionalProperties: + oneOf: + - type: string + description: A single json-formula handler expression. + - type: array + items: + type: string + description: Multiple json-formula handler expressions executed in order. + + # --- View type --- + "fd:viewType": + type: string + title: Custom rendering hint + description: >- + Optional. When set, the AF2 runtime uses this value to select an alternate + component renderer. Present in AbstractFormComponentImpl as PN_VIEWTYPE. + + # --- Data binding behavior --- + unboundFormElement: + type: [boolean, string] + title: Unbound form element + default: false + description: >- + When true forces dataRef = null regardless of the dataRef property value. + Present in AbstractFormComponentImpl as PN_UNBOUND_FORM_ELEMENT. + Omit from JCR when false — absent property = runtime default false. diff --git a/docs/authoring-schema/components/accordion.authoring.schema.yaml b/docs/authoring-schema/components/accordion.authoring.schema.yaml new file mode 100644 index 0000000000..b7190d3ae2 --- /dev/null +++ b/docs/authoring-schema/components/accordion.authoring.schema.yaml @@ -0,0 +1,12 @@ +$id: accordion.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Accordion JCR Authoring Properties +description: >- + Properties for the Adaptive Form Accordion component (v1). + All JCR-authored properties for accordion are inherited from PanelImpl + (readOnly, wrapData, breakBeforeText, breakAfterText, overflowText). + See panelimpl.authoring.schema.yaml for the full property set. +allOf: + - $ref: ../panelimpl.authoring.schema.yaml + - type: object + properties: {} diff --git a/docs/authoring-schema/components/button.authoring.schema.yaml b/docs/authoring-schema/components/button.authoring.schema.yaml new file mode 100644 index 0000000000..7deb0661d7 --- /dev/null +++ b/docs/authoring-schema/components/button.authoring.schema.yaml @@ -0,0 +1,21 @@ +$id: button.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Button JCR Authoring Properties +description: >- + Properties for button, submit, and reset button components. + NOTE: Submit action properties (actionType, mailto, spreadsheetUrl, etc.) are + flat JCR properties on the FormContainer node, NOT on the button node. + They appear nested under "fd:submit" in the JSON model output only. +allOf: + - $ref: ../base.authoring.schema.yaml + - type: object + properties: + # NOTE: ButtonImpl stores HTML button type in the JCR property "type" (PN_BUTTON_TYPE = "type"), + # reusing the same property name as the base schema's data-type field. The base schema's + # type enum has been extended to include "button", "submit", "reset" to accommodate this. + icon: + type: string + title: Button icon + description: >- + Icon identifier or path shown alongside the button label. + Actively injected by ButtonImpl (@ValueMapValue, PN_ICON). diff --git a/docs/authoring-schema/components/captcha.authoring.schema.yaml b/docs/authoring-schema/components/captcha.authoring.schema.yaml new file mode 100644 index 0000000000..ff0e9edee8 --- /dev/null +++ b/docs/authoring-schema/components/captcha.authoring.schema.yaml @@ -0,0 +1,51 @@ +$id: captcha.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Captcha JCR Authoring Properties +description: >- + Shared properties for all Adaptive Form captcha components (reCAPTCHA, hCaptcha, + Turnstile). All three have fieldType=captcha and are distinguished at the JCR level + by sling:resourceType — NOT by fd:viewType (which is never written to JCR for any + captcha component). The captcha type surfaces in the runtime JSON via getProvider() + inside the fd:captcha.provider property. + + Property name differences across implementations: + - reCAPTCHA v1: cloud service path = "rcCloudServicePath", size = "recaptchaSize" + - hCaptcha v1: cloud service path = "cloudServicePath", size = "size" + - Turnstile v1: cloud service path = "cloudServicePath", size = "size" + + All three extend AbstractCaptchaImpl → AbstractFieldImpl, so they inherit all + field and base properties. +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + rcCloudServicePath: + type: string + title: reCAPTCHA cloud service configuration path + description: >- + Used by reCAPTCHA v1 only. JCR path to the cloud configuration resource + holding the reCAPTCHA site key, secret key, and version. Injected via + ReservedProperties.PN_RECAPTCHA_CLOUD_SERVICE_PATH ("rcCloudServicePath"). + Note: hCaptcha and Turnstile use "cloudServicePath" instead. + cloudServicePath: + type: string + title: Cloud service configuration path (hCaptcha / Turnstile) + description: >- + Used by hCaptcha v1 and Turnstile v1. JCR path to the cloud configuration + resource. Injected via ReservedProperties.PN_CLOUD_SERVICE_PATH + ("cloudServicePath"). Note: reCAPTCHA v1 uses "rcCloudServicePath" instead. + recaptchaSize: + type: string + title: reCAPTCHA widget size + description: >- + Used by reCAPTCHA v1 only. Controls the visual size of the reCAPTCHA widget. + Injected via ReservedProperties.PN_RECAPTCHA_SIZE ("recaptchaSize"). + enum: + - normal + - compact + size: + type: string + title: Widget size (hCaptcha / Turnstile) + description: >- + Used by hCaptcha v1 and Turnstile v1. Controls the visual size of the + captcha widget. Injected via @Named("size"). diff --git a/docs/authoring-schema/components/checkbox.authoring.schema.yaml b/docs/authoring-schema/components/checkbox.authoring.schema.yaml new file mode 100644 index 0000000000..5ebed211da --- /dev/null +++ b/docs/authoring-schema/components/checkbox.authoring.schema.yaml @@ -0,0 +1,32 @@ +$id: checkbox.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Checkbox JCR Authoring Properties +description: >- + Properties for the Adaptive Form Checkbox component (checkbox field type). +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + checkedValue: + title: Checked value + description: >- + The value submitted when the checkbox is checked. Type matches the field's + `type` property (string, boolean, or number). + oneOf: + - type: string + - type: boolean + - type: number + uncheckedValue: + title: Unchecked value + description: Value submitted when checkbox is unchecked (only when enableUncheckedValue=true). + oneOf: + - type: string + - type: boolean + - type: number + enableUncheckedValue: + type: boolean + title: Submit value when unchecked + default: false + description: >- + When true, uncheckedValue is submitted when the checkbox is unchecked. + Omit from JCR when false — absent property = runtime default false. diff --git a/docs/authoring-schema/components/checkboxgroup.authoring.schema.yaml b/docs/authoring-schema/components/checkboxgroup.authoring.schema.yaml new file mode 100644 index 0000000000..51b240b141 --- /dev/null +++ b/docs/authoring-schema/components/checkboxgroup.authoring.schema.yaml @@ -0,0 +1,45 @@ +$id: checkboxgroup.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: CheckboxGroup JCR Authoring Properties +description: >- + Properties for the Adaptive Form Checkbox Group component (checkbox-group field type). +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + enum: + type: [array, string] + title: Option values + items: + type: ["string", "number", "boolean"] + description: >- + Available checkbox values. + Accepts string when a single value is stored as a scalar (Granite quirk). + enumNames: + type: [array, string] + title: Option display labels + items: + type: string + description: >- + Display text for each enum value. + Accepts string when a single label is stored as a scalar (Granite quirk). + orientation: + type: string + title: Options orientation + description: >- + Layout direction for checkboxes. Injected by CheckBoxGroupImpl (@ValueMapValue). + enum: [horizontal, vertical] + enforceEnum: + type: boolean + title: Enforce enum + default: true + description: Omit from JCR when true — absent property = runtime default true. + enforceEnumMessage: + type: string + title: Enforce enum constraint message + areOptionsRichText: + type: [boolean, string] + title: Options are rich text + description: >- + When true, enumNames are rendered as rich text HTML. + Reserved in ReservedProperties but not currently injected via @ValueMapValue. diff --git a/docs/authoring-schema/components/datepicker.authoring.schema.yaml b/docs/authoring-schema/components/datepicker.authoring.schema.yaml new file mode 100644 index 0000000000..b811628b21 --- /dev/null +++ b/docs/authoring-schema/components/datepicker.authoring.schema.yaml @@ -0,0 +1,31 @@ +$id: datepicker.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: DatePicker JCR Authoring Properties +description: >- + DatePicker-specific authoring properties. Constraint properties (minimumDate, + maximumDate, exclusiveMinimum, exclusiveMaximum, minimumMessage, maximumMessage) + are inherited from field.authoring.schema. + IMPORTANT: minimumDate/maximumDate are stored as JCR Date properties (not String) + and Sling auto-coerces them to java.util.Date via @ValueMapValue. +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + excludeMinimum: + type: boolean + title: Exclude minimum (backward compat) + default: false + description: >- + Actively injected by DatePickerImpl (@ValueMapValue, @Default false). + Legacy XFA-era property; use exclusiveMinimum for new content. + Omit from JCR when false — absent property = false (via @Default). + Computation input only in initDatePicker(); NOT serialized to JSON directly. + excludeMaximum: + type: boolean + title: Exclude maximum (backward compat) + default: false + description: >- + Actively injected by DatePickerImpl (@ValueMapValue, @Default false). + Legacy XFA-era property; use exclusiveMaximum for new content. + Omit from JCR when false — absent property = false (via @Default). + Computation input only in initDatePicker(); NOT serialized to JSON directly. diff --git a/docs/authoring-schema/components/datetime.authoring.schema.yaml b/docs/authoring-schema/components/datetime.authoring.schema.yaml new file mode 100644 index 0000000000..5818e87005 --- /dev/null +++ b/docs/authoring-schema/components/datetime.authoring.schema.yaml @@ -0,0 +1,27 @@ +$id: datetime.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: DateTime JCR Authoring Properties +description: >- + DateTime-specific authoring properties. DateTimeImpl extends AbstractFieldImpl + directly (not DatePickerImpl), so it does NOT have excludeMinimum/excludeMaximum. + Constraint properties (minimumDateTime, maximumDateTime, minimumMessage, + maximumMessage) are inherited from field.authoring.schema. + IMPORTANT: minimumDateTime/maximumDateTime are stored as JCR String properties + (ISO-8601 offset format), unlike DatePicker's minimumDate/maximumDate which are + JCR Date properties. The model formats them to "yyyy-MM-dd'T'HH:mm" on export. +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + pattern: + type: string + title: DateTime pattern + description: >- + Injected via @ValueMapValue (optional). Internal pattern used for + datetime formatting. Not exposed as a dialog field in v1 but + available as a JCR property. + NOTE: This shadows the `pattern` property in field.authoring.schema.yaml + (which is a regex validation pattern). For datetime, `pattern` stores an + internal date formatting string. These are the same JCR property name with + different semantics depending on component. Do not confuse with the validation + pattern used in text-type fields. diff --git a/docs/authoring-schema/components/dropdown.authoring.schema.yaml b/docs/authoring-schema/components/dropdown.authoring.schema.yaml new file mode 100644 index 0000000000..1f4a624273 --- /dev/null +++ b/docs/authoring-schema/components/dropdown.authoring.schema.yaml @@ -0,0 +1,53 @@ +$id: dropdown.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Dropdown JCR Authoring Properties +description: >- + Properties for the Adaptive Form Dropdown component (drop-down field type). + Enum/options properties come from AbstractOptionsFieldImpl. +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + enum: + type: [array, string] + title: Option values + items: + type: ["string", "number", "boolean"] + description: >- + Available values. Type must match the field's `type` property. + Accepts string when a single value is stored as a scalar (Granite quirk). + enumNames: + type: [array, string] + title: Option display labels + items: + type: string + description: >- + Display text for each enum value. Length must match enum array. + Accepts string when a single label is stored as a scalar (Granite quirk). + multiSelect: + type: boolean + title: Multi-select + default: false + description: >- + When true the type becomes an array type (e.g. string[]) automatically. + Stored as JCR Boolean; @Default(booleanValues=false) in DropDownImpl. + Omit from JCR when false — absent property = false (via @Default). + isMultiSelect() is @JsonIgnore — NOT serialized to JSON output directly; + used only to compute the array type suffix in getType(). + enforceEnum: + type: boolean + title: Enforce enum + default: true + description: >- + When false, users can type values not in the enum list (enum acts as suggestions only). + Omit from JCR when true — absent property = runtime default true. + enforceEnumMessage: + type: string + title: Enforce enum constraint message + areOptionsRichText: + type: [boolean, string] + title: Options are rich text + description: >- + When true, enumNames are rendered as rich text HTML. + Reserved in ReservedProperties but not currently injected via @ValueMapValue — + consumed by client-side rendering. diff --git a/docs/authoring-schema/components/emailinput.authoring.schema.yaml b/docs/authoring-schema/components/emailinput.authoring.schema.yaml new file mode 100644 index 0000000000..4df496ce20 --- /dev/null +++ b/docs/authoring-schema/components/emailinput.authoring.schema.yaml @@ -0,0 +1,13 @@ +$id: emailinput.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: EmailInput JCR Authoring Properties +description: >- + Email Input has no component-specific JCR properties beyond field.authoring.schema. + The fieldType is hard-coded to "email" in EmailInputImpl.getFieldType(). +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + description: >- + No additional JCR properties beyond field.authoring.schema.yaml. + EmailImpl/TelephoneImpl inject no extra @ValueMapValue fields. + properties: {} diff --git a/docs/authoring-schema/components/fileinput.authoring.schema.yaml b/docs/authoring-schema/components/fileinput.authoring.schema.yaml new file mode 100644 index 0000000000..497dfc827f --- /dev/null +++ b/docs/authoring-schema/components/fileinput.authoring.schema.yaml @@ -0,0 +1,67 @@ +$id: fileinput.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: FileInput JCR Authoring Properties +description: >- + Properties for the Adaptive Form File Input component (file-input field type). +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + multiSelection: + type: [boolean, string] + title: Allow multiple attachments + default: false + description: >- + When true the widget allows selecting or uploading multiple files. + Stored as JCR Boolean. Injected by FileInputImpl as PN_MULTISELECTION. + Omit from JCR when false — absent property = runtime default false. + accept: + type: array + items: + type: string + title: Accepted MIME types + description: >- + IANA media types accepted (e.g. ["application/pdf", "image/*"]). + Stored as JCR String[] (multi-value). Injected by FileInputImpl as PN_FILE_ACCEPT. + "fd:acceptExtensions": + type: array + items: + type: string + title: Accepted file extensions + description: >- + Additional accepted file extensions beyond MIME types. + Stored as JCR String[]. Injected by FileInputImpl as FD_FILE_ACCEPT_EXTENSIONS. + maxFileSize: + type: string + title: Maximum file size + description: >- + Maximum allowed file size in MB as a plain number string (e.g. "5"). + The Sling model appends "MB" when exporting. Stored as JCR String. + Injected by FileInputImpl as PN_MAX_FILE_SIZE. + maxFileSizeMessage: + type: string + title: Max file size constraint message + description: Error shown when an uploaded file exceeds maxFileSize. + acceptMessage: + type: string + title: Accept constraint message + description: Error shown when an uploaded file type is not in the accepted list. + dragDropText: + type: string + title: Drag-and-drop area text (v1/v2) + description: >- + Label shown in the drag-and-drop zone. Stored as JCR String. + Used in v1/v2. PN_DRAG_DROP_TEXT in ReservedProperties. + "fd:dragDropText": + type: string + title: Drag-and-drop area text (v3+) + description: >- + Label shown in the drag-and-drop zone for v3+. + Stored as JCR String with fd: namespace. PN_DRAG_DROP_TEXT_V3. + buttonText: + type: string + title: Upload button label + description: >- + Custom label for the file upload button. Stored as JCR String. + Injected by FileInputImpl as PN_BUTTON_TEXT. Default value defined + by FileInput.DEFAULT_BUTTON_TEXT. diff --git a/docs/authoring-schema/components/formcontainer.authoring.schema.yaml b/docs/authoring-schema/components/formcontainer.authoring.schema.yaml new file mode 100644 index 0000000000..cb2b93a137 --- /dev/null +++ b/docs/authoring-schema/components/formcontainer.authoring.schema.yaml @@ -0,0 +1,217 @@ +$id: formcontainer.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: FormContainer JCR Authoring Properties +description: >- + Properties for the Adaptive Form Container (guideContainer). All submission and + auto-save properties are stored as FLAT properties on this node — NOT as child nodes. + The runtime JSON model groups them under "fd:submit" and "fd:autoSave" keys for + convenience, but those groupings exist only in the JSON output, not in JCR. + JCR resource types: + core/fd/components/form/container/v1/container (FormContainerImpl v1) + core/fd/components/form/container/v2/container (FormContainerImpl v2) +allOf: + - $ref: ../container.authoring.schema.yaml + - type: object + properties: + + # ----------------------------------------------------------------------- + # Auto-save (flat JCR properties — appear grouped under fd:autoSave in + # the JSON model output only, via AutoSaveConfigurationImpl injected + # with @Self into FormContainerImpl v2) + # ----------------------------------------------------------------------- + "fd:enableAutoSave": + type: [boolean, string] + default: false + title: Enable auto-save + description: >- + Flat JCR property on the FormContainer node. Read by + AutoSaveConfigurationImpl (@ValueMapValue FD_ENABLE_AUTO_SAVE). + Appears grouped under "fd:autoSave" in the JSON model output only. + v2 only. Omit from JCR when false — absent property = runtime default false. + + "fd:autoSaveStrategyType": + type: string + title: Auto-save strategy type + description: >- + Flat JCR property on the FormContainer node. Read by + AutoSaveConfigurationImpl (@ValueMapValue FD_AUTO_SAVE_STRATEGY_TYPE). + The raw string is converted to an AutoSaveStrategyType enum at + PostConstruct time. Appears grouped under "fd:autoSave" in JSON output. + v2 only. + enum: [time, fieldFocus] + + "fd:autoSaveInterval": + type: [integer, string] + title: Auto-save interval (seconds) + description: >- + Flat JCR property on the FormContainer node. Read by + AutoSaveConfigurationImpl (@ValueMapValue FD_AUTO_SAVE_INTERVAL). + Specifies the polling interval in seconds when strategy is "time". + Appears grouped under "fd:autoSave" in JSON output. v2 only. + + # ----------------------------------------------------------------------- + # Submission (flat JCR properties — appear grouped under fd:submit in + # the JSON model output only, via FormContainerImpl v2 getSubmitProperties()) + # ----------------------------------------------------------------------- + actionType: + type: string + title: Submit action type + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_ACTION_TYPE. Collected by + getSubmitProperties() and emitted under "fd:submit" in JSON output. + + actionName: + type: string + title: Submit action name + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_ACTION_NAME. Collected by + getSubmitProperties() and emitted under "fd:submit" in JSON output. + + mailto: + title: Email — To + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_EMAIL_TO. Collected by + getSubmitProperties() and emitted nested under "fd:submit.email" + in JSON output. May be stored as a JCR multi-value String[]. + type: [string, array] + items: + type: string + + from: + type: string + title: Email — From + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_EMAIL_FROM. Emitted nested under + "fd:submit.email" in JSON output. + + subject: + type: string + title: Email — Subject + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_EMAIL_SUBJECT. Emitted nested under + "fd:submit.email" in JSON output. + + cc: + type: string + title: Email — CC + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_EMAIL_CC. Emitted nested under + "fd:submit.email" in JSON output. + + bcc: + type: string + title: Email — BCC + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_EMAIL_BCC. Emitted nested under + "fd:submit.email" in JSON output. + + spreadsheetUrl: + type: string + title: Spreadsheet URL + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SUBMIT_SPREADSHEETURL. Emitted nested under + "fd:submit.spreadsheet" in JSON output. + + # ----------------------------------------------------------------------- + # Post-submission / Thank-you + # ----------------------------------------------------------------------- + thankYouOption: + type: string + title: Thank-you option + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_THANK_YOU_OPTION. Determines whether a + message or a redirect URL is shown after successful submission. + Injected by FormContainerImpl v2 (@ValueMapValue). v2 only. + enum: [message, redirect, page] + + thankYouMessage: + type: string + title: Thank-you message (v2) + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_THANK_YOU_MSG_V2 ("thankYouMessage" — capital Y). + Injected by FormContainerImpl v2 (@ValueMapValue). v2 only. + + thankyouMessage: + type: string + title: Thank-you message (v1) + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_THANK_YOU_MSG_V1 ("thankyouMessage" — lowercase y). + Injected by FormContainerImpl v1 (@ValueMapValue). v1 only. + + redirect: + type: string + title: Redirect URL + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_REDIRECT. Path or URL to redirect to after + a successful form submission when thankYouOption is "redirect". + Injected by FormContainerImpl v2 (@ValueMapValue). v2 only. + + # ----------------------------------------------------------------------- + # General + # ----------------------------------------------------------------------- + prefillService: + type: string + title: Prefill service + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_PREFILL_SERVICE. Sling selector string used + to resolve the prefill service. Injected by FormContainerImpl v2 + (@ValueMapValue). When non-blank, fd:formDataEnabled is set to true + in JSON output. v2 only. + + specVersion: + type: string + title: Adaptive Forms spec version + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_SPEC_VERSION. Defaults to + FormContainer.DEFAULT_FORMS_SPEC_VERSION when not present. + Injected by FormContainerImpl v2 (@ValueMapValue). v2 only. + examples: ["1.0.0"] + + clientLibRef: + type: string + title: Client library reference + description: >- + Flat JCR property on the FormContainer node. Corresponds to + ReservedProperties.PN_CLIENTLIB_REF. Custom client library category + added to the page's client libraries at runtime via FormClientLibManager. + Injected by FormContainerImpl v2 (@ValueMapValue). v2 only. + + # ----------------------------------------------------------------------- + # v2-only child node: fd:view/print + # This is a GENUINE JCR child node, NOT a flat property. + # Path relative to the FormContainer node: fd:view/print + # ----------------------------------------------------------------------- + "fd:view/print": + type: object + title: DOR print view settings (v2 child node) + description: >- + This is a genuine JCR child node located at the relative path + "fd:view/print" under the FormContainer node. It is NOT a flat + property. Read by FormContainerImpl v2 initExcludeFromDoRIfHidden() + via resource.getChild("fd:view/print"). v2 only. + properties: + excludeFromDoRIfHidden: + type: boolean + default: false + title: Exclude hidden fields from Document of Record + description: >- + When true, fields hidden at submission time are excluded from + the generated Document of Record. Stored at the child node + path fd:view/print. Corresponds to + ReservedProperties.FD_EXCLUDE_FROM_DOR_IF_HIDDEN + ("fd:excludeFromDoRIfHidden") in getDorProperties() output. + Omit from JCR when false — absent property = runtime default false. diff --git a/docs/authoring-schema/components/fragment.authoring.schema.yaml b/docs/authoring-schema/components/fragment.authoring.schema.yaml new file mode 100644 index 0000000000..95ba995d4f --- /dev/null +++ b/docs/authoring-schema/components/fragment.authoring.schema.yaml @@ -0,0 +1,23 @@ +$id: fragment.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Fragment JCR Authoring Properties +description: >- + Properties for the Adaptive Form Fragment component (v1). + FragmentImpl extends PanelImpl which extends AbstractContainerImpl. + The fragment's two key properties (fragmentPath and lazy) are already + defined in container.authoring.schema.yaml because they are handled at + the container level. This schema extends container and documents no + additional flat JCR properties; all fragment-specific behaviour is + derived at runtime from the referenced fragment path. + JCR resource type: core/fd/components/form/fragment/v1/fragment +allOf: + - $ref: ../container.authoring.schema.yaml + - type: object + description: >- + No additional flat JCR properties beyond what container.authoring.schema + defines. FragmentImpl reads fragmentPath and lazy from the container + schema; all other child data is loaded from the referenced fragment + resource at runtime. The property fd:fragment (boolean) is written + dynamically to the JSON model properties map by getProperties() and + is not a JCR-authored value. + properties: {} diff --git a/docs/authoring-schema/components/hcaptcha.authoring.schema.yaml b/docs/authoring-schema/components/hcaptcha.authoring.schema.yaml new file mode 100644 index 0000000000..ffe11be844 --- /dev/null +++ b/docs/authoring-schema/components/hcaptcha.authoring.schema.yaml @@ -0,0 +1,31 @@ +$id: hcaptcha.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: hCaptcha JCR Authoring Properties +description: >- + Properties for the Adaptive Form hCaptcha component (v1). + HCaptchaImpl extends AbstractCaptchaImpl which extends AbstractFieldImpl, + so it inherits all field and base properties. The two component-specific + properties point to the cloud service configuration and control the widget + display size. At runtime HCaptchaImpl resolves the HCaptchaConfiguration + from the cloud service path via CloudConfigurationProvider to obtain the + site key and client-side JS URL. + JCR resource type: core/fd/components/form/hcaptcha/v1/hcaptcha +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + cloudServicePath: + type: string + title: hCaptcha cloud service configuration path + description: >- + JCR path to the cloud configuration resource that holds the hCaptcha + site key and client-side JS URL. At runtime HCaptchaImpl resolves the + HCaptchaConfiguration from this path via CloudConfigurationProvider. + Injected via ReservedProperties.PN_CLOUD_SERVICE_PATH ("cloudServicePath"). + size: + type: string + title: hCaptcha widget size + description: >- + Controls the visual size/style of the hCaptcha widget. Injected by + HCaptchaImpl via ReservedProperties.PN_SIZE ("size"). Stored as JCR String. + Common values depend on hCaptcha's supported size parameter. diff --git a/docs/authoring-schema/components/image.authoring.schema.yaml b/docs/authoring-schema/components/image.authoring.schema.yaml new file mode 100644 index 0000000000..4f46b0ebdd --- /dev/null +++ b/docs/authoring-schema/components/image.authoring.schema.yaml @@ -0,0 +1,41 @@ +$id: image.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Image JCR Authoring Properties +description: >- + Properties for the Adaptive Form Image component (image field type). + Image is a non-data-capturing display component; it extends base (not field). +allOf: + - $ref: ../base.authoring.schema.yaml + - type: object + properties: + fileReference: + type: string + title: DAM asset path + description: >- + Path to the image asset in the DAM. Injected by StaticImageImpl + as PN_FILE_REF. Stored as JCR String. When set, the model also + exports this value under the "fd:repoPath" custom property key. + altText: + type: string + title: Alt text + description: >- + Alternate text for the image shown when the image cannot be displayed. + Injected by StaticImageImpl as PN_ALT_TEXT. Stored as JCR String. + imageSrc: + type: string + title: Image source URL override + description: >- + Direct URL override for the image source. Injected by StaticImageImpl + as PN_IMAGE_SRC. When absent the model derives the src from the DAM + asset referenced by fileReference. Stored as JCR String. + description: + type: string + title: Long description + description: >- + Long description of the image (not rendered in JSON model output — + @JsonIgnore). Injected by StaticImageImpl as PN_DESCRIPTION. + Stored as JCR String. + NOTE: This shadows the `description` in base.authoring.schema.yaml. + For StaticImageImpl, description is injected @JsonIgnore and is NOT + exported to the JSON model — it exists only as metadata in JCR. + This differs from the base schema behavior where description IS rendered. diff --git a/docs/authoring-schema/components/numberinput.authoring.schema.yaml b/docs/authoring-schema/components/numberinput.authoring.schema.yaml new file mode 100644 index 0000000000..7925d7dc18 --- /dev/null +++ b/docs/authoring-schema/components/numberinput.authoring.schema.yaml @@ -0,0 +1,28 @@ +$id: numberinput.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: NumberInput JCR Authoring Properties +description: >- + NumberInput-specific JCR properties. All field constraints (minimum, maximum, + exclusiveMinimum, exclusiveMaximum, etc.) are inherited from field.authoring.schema. +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + step: + title: Step + description: Value must be a multiple of step. Stored as String or Long in JCR. + oneOf: + - type: number + - type: string + excludeMaximumCheck: + type: boolean + title: Exclude maximum check (backward compat) + description: >- + Actively injected by NumberInputImpl (@ValueMapValue). Legacy XFA-era property; + use exclusiveMaximum for new content. + excludeMinimumCheck: + type: boolean + title: Exclude minimum check (backward compat) + description: >- + Actively injected by NumberInputImpl (@ValueMapValue). Legacy XFA-era property; + use exclusiveMinimum for new content. diff --git a/docs/authoring-schema/components/panelcontainer.authoring.schema.yaml b/docs/authoring-schema/components/panelcontainer.authoring.schema.yaml new file mode 100644 index 0000000000..9e7ddb3a29 --- /dev/null +++ b/docs/authoring-schema/components/panelcontainer.authoring.schema.yaml @@ -0,0 +1,12 @@ +$id: panelcontainer.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Panel Container JCR Authoring Properties +description: >- + Properties for the Adaptive Form Panel Container component (v1). + All JCR-authored properties for panelcontainer are inherited from PanelImpl + (readOnly, wrapData, breakBeforeText, breakAfterText, overflowText). + See panelimpl.authoring.schema.yaml for the full property set. +allOf: + - $ref: ../panelimpl.authoring.schema.yaml + - type: object + properties: {} diff --git a/docs/authoring-schema/components/radiobutton.authoring.schema.yaml b/docs/authoring-schema/components/radiobutton.authoring.schema.yaml new file mode 100644 index 0000000000..ec77244d3c --- /dev/null +++ b/docs/authoring-schema/components/radiobutton.authoring.schema.yaml @@ -0,0 +1,46 @@ +$id: radiobutton.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: RadioButton JCR Authoring Properties +description: >- + Properties for the Adaptive Form Radio Button component (radio-group field type). +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + enum: + type: [array, string] + title: Option values + items: + type: ["string", "number", "boolean"] + description: >- + Available radio button values. + Accepts string when a single value is stored as a scalar (Granite quirk). + enumNames: + type: [array, string] + title: Option display labels + items: + type: string + description: >- + Display text for each enum value. + Accepts string when a single label is stored as a scalar (Granite quirk). + orientation: + type: string + title: Options orientation + description: >- + Layout direction for radio buttons. Injected by RadioButtonImpl (@ValueMapValue). + Stored as JCR String. + enum: [horizontal, vertical] + enforceEnum: + type: boolean + title: Enforce enum + default: true + description: Omit from JCR when true — absent property = runtime default true. + enforceEnumMessage: + type: string + title: Enforce enum constraint message + areOptionsRichText: + type: [boolean, string] + title: Options are rich text + description: >- + When true, enumNames are rendered as rich text HTML. + Reserved in ReservedProperties but not currently injected via @ValueMapValue. diff --git a/docs/authoring-schema/components/recaptcha.authoring.schema.yaml b/docs/authoring-schema/components/recaptcha.authoring.schema.yaml new file mode 100644 index 0000000000..dd83f59101 --- /dev/null +++ b/docs/authoring-schema/components/recaptcha.authoring.schema.yaml @@ -0,0 +1,39 @@ +$id: recaptcha.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: reCAPTCHA JCR Authoring Properties +description: >- + Properties for the Adaptive Form Google reCAPTCHA component (v1). + RecaptchaImpl extends AbstractCaptchaImpl which extends AbstractFieldImpl, + so it inherits all field and base properties. The two component-specific + properties point to the cloud service configuration and control the widget + display size. Note that RecaptchaImpl uses a different JCR property name + for cloud service path ("rcCloudServicePath") than hCaptcha/Turnstile + ("cloudServicePath") — this is intentional and historically fixed. + JCR resource type: core/fd/components/form/recaptcha/v1/recaptcha +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + rcCloudServicePath: + type: string + title: reCAPTCHA cloud service configuration path + description: >- + JCR path to the cloud configuration resource that holds the reCAPTCHA + site key, secret key, and version (v2 or enterprise). At runtime + RecaptchaImpl resolves the ReCaptchaConfigurationModel from this path + via CloudConfigurationProvider. Injected via + ReservedProperties.PN_RECAPTCHA_CLOUD_SERVICE_PATH ("rcCloudServicePath"). + Note: this property name differs from the "cloudServicePath" used by + hCaptcha and Turnstile. + recaptchaSize: + type: string + title: reCAPTCHA widget size + description: >- + Controls the visual size of the reCAPTCHA widget. Valid for reCAPTCHA v2 + and reCAPTCHA Enterprise checkbox keys; disabled for score-based (invisible) + Enterprise keys. Common values: "normal", "compact". Injected by + RecaptchaImpl via ReservedProperties.PN_RECAPTCHA_SIZE ("recaptchaSize"). + Stored as JCR String. + enum: + - normal + - compact diff --git a/docs/authoring-schema/components/review.authoring.schema.yaml b/docs/authoring-schema/components/review.authoring.schema.yaml new file mode 100644 index 0000000000..6525baa7b2 --- /dev/null +++ b/docs/authoring-schema/components/review.authoring.schema.yaml @@ -0,0 +1,37 @@ +$id: review.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Review JCR Authoring Properties +description: >- + Properties for the Adaptive Form Review component (v1). + ReviewImpl extends AbstractBaseImpl directly (not AbstractFieldImpl or + AbstractContainerImpl), so it inherits only the base properties. + The two component-specific properties are stored under the fd: namespace + and are written dynamically to the JSON model's custom properties map + via getProperties(). The component renders a read-only review of all or + specific linked panels in the form. + JCR resource type: core/fd/components/form/review/v1/review +allOf: + - $ref: ../base.authoring.schema.yaml + - type: object + properties: + "fd:linkedPanels": + type: array + items: + type: string + title: Linked panels + description: >- + Array of panel paths (or names) that this Review component should + display. When empty or absent the component renders the entire form. + Injected by ReviewImpl as String[] via @ValueMapValue with name + "fd:linkedPanels". Stored as JCR multi-value String property. + Written to the JSON model properties map under key "fd:linkedPanels" + by getProperties(). + "fd:editModeAction": + type: string + title: Edit mode action + description: >- + Specifies the edit action available in review mode. Controls whether + the user can edit individual fields, entire panels, both, or neither. + Injected by ReviewImpl as String via @ValueMapValue with name + "fd:editModeAction". Stored as JCR String. Written to the JSON model + properties map under key "fd:editModeAction" by getProperties(). diff --git a/docs/authoring-schema/components/scribble.authoring.schema.yaml b/docs/authoring-schema/components/scribble.authoring.schema.yaml new file mode 100644 index 0000000000..176ed232a0 --- /dev/null +++ b/docs/authoring-schema/components/scribble.authoring.schema.yaml @@ -0,0 +1,26 @@ +$id: scribble.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Scribble JCR Authoring Properties +description: >- + Properties for the Adaptive Form Scribble (signature) component. + Scribble renders with fieldType "file-input" and fd:viewType "signature". +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + "fd:dialogLabel": + type: string + title: Dialog label + description: >- + Label shown at the top of the Scribble authoring/capture dialog + (e.g. "Please sign here"). Injected by ScribbleImpl as FD_DIALOG_LABEL. + Stored as JCR String. Default value defined by Scribble.DEFAULT_DIALOG_LABEL. + Exported via getProperties() under the same "fd:dialogLabel" key. + format: + type: string + title: Data format hint + description: >- + General format hint for the scribble data type (e.g. "data-url"). + Injected by ScribbleImpl as PN_FORMAT. Distinct from displayFormat/dataFormat + on AbstractFieldImpl. Stored as JCR String. Included in JSON model output + via @JsonInclude(NON_NULL). diff --git a/docs/authoring-schema/components/switch.authoring.schema.yaml b/docs/authoring-schema/components/switch.authoring.schema.yaml new file mode 100644 index 0000000000..d4cc73ef5c --- /dev/null +++ b/docs/authoring-schema/components/switch.authoring.schema.yaml @@ -0,0 +1,33 @@ +$id: switch.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Switch JCR Authoring Properties +description: >- + Properties for the Adaptive Form Switch component (switch field type). + Switch uses the same checked/unchecked value pattern as Checkbox. + SwitchImpl extends AbstractCheckboxImpl; the only behavioral difference is + that enumNames are trimmed to one entry when enableUncheckedValue is false. +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + checkedValue: + title: On value + description: Value submitted when switch is in the "on" state. + oneOf: + - type: string + - type: boolean + - type: number + uncheckedValue: + title: Off value + description: Value submitted when switch is in the "off" state (only when enableUncheckedValue=true). + oneOf: + - type: string + - type: boolean + - type: number + enableUncheckedValue: + type: boolean + title: Submit value when off + default: false + description: >- + When true, uncheckedValue is submitted when the switch is in the off state. + Omit from JCR when false — absent property = runtime default false. diff --git a/docs/authoring-schema/components/tabsontop.authoring.schema.yaml b/docs/authoring-schema/components/tabsontop.authoring.schema.yaml new file mode 100644 index 0000000000..e2637c6f61 --- /dev/null +++ b/docs/authoring-schema/components/tabsontop.authoring.schema.yaml @@ -0,0 +1,12 @@ +$id: tabsontop.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Tabs On Top JCR Authoring Properties +description: >- + Properties for the Adaptive Form Tabs On Top component (v1). + All JCR-authored properties for tabsontop are inherited from PanelImpl + (readOnly, wrapData, breakBeforeText, breakAfterText, overflowText). + See panelimpl.authoring.schema.yaml for the full property set. +allOf: + - $ref: ../panelimpl.authoring.schema.yaml + - type: object + properties: {} diff --git a/docs/authoring-schema/components/telephoneinput.authoring.schema.yaml b/docs/authoring-schema/components/telephoneinput.authoring.schema.yaml new file mode 100644 index 0000000000..a9830b42e5 --- /dev/null +++ b/docs/authoring-schema/components/telephoneinput.authoring.schema.yaml @@ -0,0 +1,13 @@ +$id: telephoneinput.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: TelephoneInput JCR Authoring Properties +description: >- + Telephone Input has no component-specific JCR properties beyond field.authoring.schema. + The fieldType is hard-coded to "tel" in TelephoneInputImpl.getFieldType(). +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + description: >- + No additional JCR properties beyond field.authoring.schema.yaml. + EmailImpl/TelephoneImpl inject no extra @ValueMapValue fields. + properties: {} diff --git a/docs/authoring-schema/components/termsandconditions.authoring.schema.yaml b/docs/authoring-schema/components/termsandconditions.authoring.schema.yaml new file mode 100644 index 0000000000..68d3b90177 --- /dev/null +++ b/docs/authoring-schema/components/termsandconditions.authoring.schema.yaml @@ -0,0 +1,46 @@ +$id: termsandconditions.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Terms and Conditions JCR Authoring Properties +description: >- + Properties for the Adaptive Form Terms and Conditions component (v1). + TermsAndConditionsImpl extends PanelImpl (a container), so it inherits + all container and base properties. The three component-specific boolean + flags control which child nodes are rendered and how consent is presented. + JCR resource type: core/fd/components/form/termsandconditions/v1/termsandconditions +allOf: + - $ref: ../container.authoring.schema.yaml + - type: object + properties: + showApprovalOption: + type: boolean + title: Show approval option + default: true + description: >- + When true an approval/consent checkbox is rendered inside the component, + allowing the user to explicitly accept the terms. When false the checkbox + is omitted. Injected by TermsAndConditionsImpl via + ReservedProperties.PN_SHOW_APPROVAL_OPTION ("showApprovalOption"). + Stored as JCR Boolean. Decorated with @JsonIgnore — consumed by the + component's HTL template rather than exported to the JSON model. + Omit from JCR when true — absent property = runtime default true. + showLink: + type: boolean + title: Show links instead of text content + default: false + description: >- + When true the component renders checkboxGroup children (links) rather + than plain-text children. TermsAndConditionsImpl filters child resources + based on this flag in getFilteredChildrenResources(). Injected via + ReservedProperties.PN_SHOW_LINK ("showLink"). Stored as JCR Boolean. + Decorated with @JsonIgnore — not exported to the JSON model. + Omit from JCR when false — absent property = runtime default false. + showAsPopup: + type: boolean + title: Show terms content as modal popup + default: false + description: >- + When true the terms content is displayed inside a modal dialog overlay + rather than inline. Injected by TermsAndConditionsImpl via + ReservedProperties.PN_SHOW_AS_POPUP ("showAsPopup"). Stored as JCR Boolean. + Decorated with @JsonIgnore — not exported to the JSON model. + Omit from JCR when false — absent property = runtime default false. diff --git a/docs/authoring-schema/components/text.authoring.schema.yaml b/docs/authoring-schema/components/text.authoring.schema.yaml new file mode 100644 index 0000000000..feee3a9a20 --- /dev/null +++ b/docs/authoring-schema/components/text.authoring.schema.yaml @@ -0,0 +1,21 @@ +$id: text.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: Text JCR Authoring Properties +description: >- + Properties for the Adaptive Form Text (static text / plain-text) component. +allOf: + - $ref: ../base.authoring.schema.yaml + - type: object + properties: + textIsRich: + type: [boolean, string] + title: Content is rich text + default: false + description: >- + When true the static text content is treated as HTML rich text. + Injected by TextImpl (@Nullable Boolean, PN_TEXT_IS_RICH). + JSON key is "richText" (via @JsonProperty on getRichText()). + IMPORTANT: This is PN_TEXT_IS_RICH ("textIsRich"), NOT "richText" which + is reserved in ReservedProperties but not injected by any Sling model. + Omit from JCR when false — absent property = null → @JsonInclude(NON_NULL) + suppresses "richText" from JSON output → runtime uses interface default false. diff --git a/docs/authoring-schema/components/textinput.authoring.schema.yaml b/docs/authoring-schema/components/textinput.authoring.schema.yaml new file mode 100644 index 0000000000..b93cd31fe3 --- /dev/null +++ b/docs/authoring-schema/components/textinput.authoring.schema.yaml @@ -0,0 +1,26 @@ +$id: textinput.authoring.schema +$schema: "http://json-schema.org/draft-07/schema#" +title: TextInput JCR Authoring Properties +description: >- + Properties specific to Adaptive Form Text Input (v1) beyond those in + field.authoring.schema. JCR resource type: core/fd/components/form/textinput/v1/textinput +allOf: + - $ref: ../field.authoring.schema.yaml + - type: object + properties: + multiLine: + type: [boolean, string] + title: Allow multiple lines (textarea) + default: false + description: >- + When true the widget renders as a